Favorite Gems That You Should Absolutely Be Using

  1. Annotate Models
    I didn’t realize how much I loved Annotate Models until I moved to a project where we didn’t have it. Annotate Models basically adds the schema to the bottom of the models and the factories. I LOVE IT. The amount of times I’ve been looking through a model and trying to remember what fields I actually have is immeasurable.
  2. Guard
    Guard can be a pain in the ass. Sometimes it runs all your tests when you don’t want them to be run. But damn if it doesn’t help when you are refactoring a ton of your app and sorta wondering which tests you broke (answer: all of them). I’ve been doing a lot of refactoring and basically wish I had added Guard to the project on Monday instead of Friday.
  3. Paloma
    Paloma is another one I didn’t realize I would miss until it was no longer in my project. All of a sudden, instead of having all my javascript in a particular place, it’s scattered throughout the app, who knows where. I’m adding Paloma to the app I’m working on right now because, dammit, I need this level of organization!

Misconceptions about and, or, &&, and ||

Everyone should read this wonderful post by Avdi Grimm about ‘and’ and ‘or’ operators in Ruby. IMHO they are underutilized, partly in thanks to style guides that say ‘NEVER USE THESE!!!’. You absolutely should use them when it is the right time and place. As Avdi mentions, they are wonderful control-flow operators, so don’t shy away!

New Gig!

I just started a new job at an early stage startup. The app was actually built by a junior developer, so I will probably be posting some of the code that we are changing, since it will cover mistakes that junior devs often make.

First up: listen to Sandi Metz  and try to limit the number of objects instantiated in your controllers. Sometimes you need more than one, but 5+ is usually preventable.

SitePrism is awesome and you should use it

I mentioned SitePrism yesterday and so I wanted to go in a little more depth. From my example yesterday, I used an inventory show page and an inventory index page. I had a find_inventory method on inventory index and a displayed? method on inventory show. I actually reconsidered the displayed? method and so I’m going to show how to use SitePrism to validate that the page has loaded in a different way.

Let’s look at the InventoriesIndex SitePrism page:

module Inventories
  class InventoriesIndex < SitePrism::Page
    set_url '/inventories'
    set_url_matcher %r{/inventories}
    section :list, "#inventories-list" do
      elements :inventories, '.inventory'
      def selector_for_inventory(inventory)
        "#inventory_#{inventory.id.to_s}_row"
      end

      def find_inventory(inventory)
        find selector_for_inventory(inventory)
      end
    end
  end
end

This makes my tests much each to read. Instead of typing

find "#inventory_#{inv.id.to_s}_row"

in my test, it instead looks like:

find_inventory(inv)

SO MUCH PRETTIER!

Let’s look at how SitePrism can help our InventoryShow page:

module Inventories
  class InventoriesShow < SitePrism::Page
    set_url '/inventories/{id}'
    set_url_matcher %r{/inventories/\d+}
    
    section :inventory_info, '#inventory-information' do
      element :name, '.inventory-name'
    end
  end
end

With just that little bit, we can validate that the page loaded what we want:

expect(page.inventory_info.name.text).to include inv.name

Overall, so much nicer than having all the css/xpath selectors all over your RSpec tests. Check it out!

Integration Tests: Cucumber vs. RSpec

I’ve recently started writing integration tests in RSpec instead of Cucumber and I have been LOVING IT. It’s taken much less time and a lot less terrible code. Here is what I need for a test using Cucumber:

features/show_inventory.feature

Background:
    And I am signed in as a user
    And an inventory "I" exists

Scenario: I can view the inventory page from the inventory list page
    Given I am on the inventories page
    When I click on the inventory row for that inventory "I"
    Then I should be on inventory "I"'s page

features/inventory_steps.rb

Given %r{^I am signed in as an? #{capture_model}$} do |model_name|
  user = create_model model_name
  login_with(user.email, user.password)
  @current_user = user
end

When %r{^I click on the inventory row for #{capture_model}$} do |model_name|
  inventory = find_model model_name
  App.inventories_index.list.find_inventory(inventory).click
end

The steps that aren’t covered manually are covered using a tool called pickle. Pretty useful, but can also be sorta frustrating. We also use SitePrism for both styles of tests and if you aren’t using it, you should reconsider.

So what does an RSpec integration test look like? If I was covering the same simple problem, here’s what I would do:

spec/features/user_inventory_spec.rb

require 'rails_helper'

RSpec.feature 'load inventory as user', :js do
  let(:user) { create :user }
  before do
    3.times do
      create :inventory
    end
  end
  
  scenario 'select inventory and view the page' do
    Sessions::SessionsNew.sign_in user.email, 'my_test_pass'
    inventory = Inventory.first
    
    Inventories::InventoriesIndex.new.tap do |page|
      page.load
      page.list.find_inventory(inventory).click
    end
    
    Inventories::InventoriesShow.new.tap do |page|
      page.displayed?
    end
  end
end

And that’s it. I just have to have the SitePrism pages for Sessions::SessionsNew, Inventories::InventoriesIndex, and Inventories::InventoriesShow designed correctly as well. But those I will use multiple times in other tests, so after the inital setup, I save a lot of time. In this case, I had already set the pages up while we were using Cucumber, so I didn’t have to do anything new to start writing tests in RSpec.

TL;DR unless you have a PM that is actually writing your Cucumber tests, just do them in RSpec. You’ll save yourself many a headache.

Eliminating Extra Code with each_with_object

I’ve been listening to Avdi Grimm’s Confident Ruby screencast and came across a function I’d never really used before: each_with_object. each_with_object allows you to iterate over a collection, passing the current item and the memo (the object that was passed in) to the block. The memo must be a mutable object, like an array or hash, not an immutable object such as a string or integer.

Here’s an example:

Without each_with_object, I have to set up a result hash, return if what I’m attempting to iterate over is a blank array, and return the result hash at the end.

def get_results(users)
  users = users.to_a
  result = {}
  return result if users.blank?

  users.each do |u|
    result[u.result_id] = u
  end

  result
end

With each_with_object, I am able to eliminate three lines of code, practically cutting my method in half. I instantiate the empty hash by passing it to each_with_object and each_with_object also does the work of returning the finished hash.

def get_results(users)
  users = users.to_a

  users.each_with_object({}) do |u, result|
    result[u.result_id] = u
  end
end

Anonymous Classes in Ruby

I’m currently watching Dave Thomas’ ‘Ruby Meta-Programming’ screencast from PragProg and he just said something that sorta blew my mind. It both made sense and I hadn’t quite realized that Ruby works this way.

Let’s say you declare a string:

person = "Jennifer"

Then I can also create a method only on person:

def person.job
  'programmer'
end

And then when I call person.job, it returns ‘programmer’. Pretty cool, right? Apparently Ruby does this by creating an anonymous class. So when I’m looking for methods on person (which is a String), it first checks this anonymous class, then the String class, then Object, then BasicObject. I’m not quite sure of a real-life use case for this, but the idea is pretty neat.

INSTA-UPDATE:

Even cooler: if I define another method (say person.hobby), that will be put into the same anonymous class as person.job. Ruby will not create a new anonymous class for each singleton method; it knows that they should be part of the same class.

Retrieving Values from Hashes

In Ruby, there are at least two ways to get a specific value from a hash with two different results if the key is not found.

1. Hash#fetch

h = { "a" => 100, "b" => 200 }
h.fetch("z")
=> KeyError: key not found: "z"from (pry):26:in `fetch'

2. hsh[key] → value

h = { "a" => 100, "b" => 200 }
h["z"]
=> nil

Which one you want to use depends on whether you want to raise an error if it doesn’t exist or just check if it is nil.

Raising ActiveRecord::Rollback

I had a bit of code that I was running in a transaction block. Like so:

ActiveRecord::Base.transaction do
  @rating = Rating.new(rater: @user, rateable: @movie, score: params[:score])
  if !@rating.save
    Rails.logger.error("Error saving rating")
    raise ActiveRecord::Rollback
  end
end

I kept trying to test this by doing:

expect { post :create etc }.to raise_error ActiveRecord::Rollback

Total failure. Couldn’t figure out why for a while. Here’s the reason: raising ActiveRecord::Rollback just triggers a rollback of the transaction and does so silently. What I should’ve done is raise a different type of error (TBD) and that will still trigger a rollback of the transaction but the error will actually be raised and we can return an appropriate page to the user.

More info on StackOverflow.

Custom Validators

As an exercise, I created a simple custom validator. I had done this before at work, but I had managed to forget how to do it between then and now. I guess that’s why I need a bit of extra practice :)

So the idea is that, instead of including this ugly regex in the model, you can pull it out (or whatever you are using to validate your attribute) and put it in a separate validator class. It makes the model much simpler and makes it so it is no longer responsible for the logic behind the validation.

If you are using Rails, you would just put PhoneValidator within the validators folder and it will find it without requiring it in the model as I do here.

# person.rb

require 'phone_validator'

class Person
  include ActiveModel::Validations

  validates :phone_number, phone: true

  attr_accessor :phone_number

  def initialize(attributes = {})
    @phone_number = attributes[:phone_number]
  end
end

# phone_validator.rb

class PhoneValidator < ActiveModel::EachValidator
  PHONE_REGEX ||= /^(?:(?:\+?1\s*(?:[.-]\s*)?)?(?:\(\s*([2-9]1[02-9]|[2-9][02-8]1|[2-9][02-8][02-9])\s*\)|([2-9]1[02-9]|[2-9][02-8]1|[2-9][02-8][02-9]))\s*(?:[.-]\s*)?)?([2-9]1[02-9]|[2-9][02-9]1|[2-9][02-9]{2})\s*(?:[.-]\s*)?([0-9]{4})(?:\s*(?:#|x\.?|ext\.?|extension)\s*(\d+))?$/

  def validate_each(record, attribute, value)
    unless value =~ PHONE_REGEX
      record.errors[attribute] = "invalid phone number formatting" 
    end
  end
end

Converting Seconds to Midnight Back to Time

Rails has a nice little function for it’s DateTime class called ‘seconds_since_midnight’. Super handy if you (for some reason) just want to store time, without a date in your database. However, here is the next problem you will come across: how do I display this value of seconds as an actual, human-readable time?

Luckily, this is simple:

def convert_to_time_from_second_to_midnight(seconds)
  hh, mm = seconds.divmod(60)[0].divmod(60)
  Time.parse('%d:%d' % [hh, mm]).strftime("%I:%M %p")
end

divmod is an interesting little function that I’ve never used prior to writing this.  It’s very simple: just returns the quotient and the modulus. It helps us get the hours and minutes within just one line. Then all we have to do is format it and the result is a nicely formatted time like so “12:30 PM”.

Sandi Metz' Rules For Developers

I came across this post from thoughtbot about Sandi Metz’ rules for developers. This is a bit of an older post, but I had a few thoughts about it.

THE RULES:

  1. Classes can be no longer than one hundred lines of code.
  2. Methods can be no longer than five lines of code.
  3. Pass no more than four parameters into a method. Hash options are parameters.
  4. Controllers can instantiate only one object. Therefore, views can only know about one instance variable and views should only send messages to that object (@object.collaborator.value is not allowed).

How a mid-level developer feels about these rules:

  1. This tends to be pretty easy for me to keep to for regular classes, less so for specs. It’s hard to argue with this rule and it’s pretty *relatively* easy to follow.
  2. This one is a bit harder. Mainly, as thoughtbot points out, if you follow this rule, you can’t use elsif with else if following this rule. Sometimes, it’s not worth it to break things up. However, I do try to follow this rule as often as possible.
  3. This is another hard one. If you need more than four values, storing them in an object works fairly well. However, sometimes you don’t want to bulk up your code by creating another object instead of just passing params/a hash.
  4. I’m definitely a fan of the Facade Pattern as well. Keeping one instance variable per controller is another one that is fairly easy to keep.

Even for the ones that I find hard to follow, I am trying to keep to these rules with my own code. Definitely worth reviewing and incorporating into your development process.

Null Objects in Ruby

I just did an exercise running through null objects in ruby. We don’t really use them at any company I’ve worked for, so it was interesting to try out a new technique. If you are unfamiliar with null objects here’s the idea:

Null objects are beneficial when you would otherwise be checking if an object is nil or empty throughout your code.

The example in the assignment was subscriptions. You have a user and a user is attached to a subscription. However, a subscription can be a free trial or no plan, in addition to regular, paid subscription. For a free trial, price and charge are both 0 and nil, respectively. Instead of checking if subscription.nil? I can create a NullSubscription and do something like this within the user class:

def subscription
  if free_trial?
    FreeTrial.new
  else
    @subsciption || NullSubscription.new
  end
end

So now, instead of checking if @subscription is nil and then setting price, we can call @subscription.price and always get a real value (assuming we are seeing price to zero in our NullSubscription class.

Random Rubyisms That I Keep Forgetting

I haven’t been blogging because I thought that I hadn’t really solved any problems recently worth writing about. However, I forgot that I just recently came across a few Rubyisms that I had totally missed (or learned and forgotten). Here are a few bits that were enlightening to me:

  • if x && y: If x is nil, then y doesn’t run. I’ve had a few double if statements in my code previously because I forgot that the second part of the statement won’t even run if the first is nil/false.
  • x = if y then b else c end: assigned x = b if y is true, else c. I knew the inline x = b if y, but didn’t quite realize that you could do the full if else. NOTE: this is kept on one line for the sake of bullets. If you were really writing it, you would want to split it out into separate lines, with the first line being x = if y.
  • case statement when/then: Assuming you know what a full normal case statement looks like (if not, here’s a nice little post), have you seen them written as when/then? For example: when x then :is_x. To me that is much more easy to read than a when x (new line) :is_x. Definitely a personal preference though :)

That’s all for now. But I also have some Python/Ruby differences that I’ve found intriguing recently.

FactoryGirl vs. Bare Domain Objects

I’ve been doing a fair amount of research into testing and what are the best and fasted way to test. Recently, someone at work brought up the fact that using factories can drastically slow down your test suite. Especially when, like us, you create other factories within factories (ie. I need an advertiser for a campaign, so when I use Factory.build(:campaign), it also does Factory.create(:advertiser)). I tried using Factory.stub (check out this article), but it still would create in the background and I couldn’t change that without wrecking all of our other tests. I decided to start testing with bare domain objects, saving nothing to the database (when possible). Here is a comparison of using FactoryGirl vs. bare domain objects:

FactoryGirl

context '#validate flight dates with FactoryGirl' do
  setup do
    @campaign = FactoryGirl.build(:campaign, id: 1234, flight_start: Date.new(2014,01,28), flight_end: Date.new(2014,01,28))
  end
  
  should 'be valid if campaign has the same flight_start and flight_end' do
    assert_true @campaign.valid?
  end
  
  should 'be invalid if flight_end is before flight_start' do
    @campaign.flight_end = Date.new(2014,01,27)
    assert_false @campaign.valid?
    assert @campaign.errors.full_messages.include?('Flight start must be earlier than campaign flight end date')
  end
end

 

Bare Domain Objects

context '#validate flight dates with Bare Domain Objects' do
  should 'be valid if campaign has the same flight_start and flight_end' do
    campaign = Campaign.new(name: 'UNICORNS!!!', flight_start: Date.new(2014,01,28), flight_end: Date.new(2014,01,28))
    campaign.valid?
    assert_false campaign.errors.full_messages.include?('Flight start must be earlier than campaign flight end date')
  end
  
  should 'be invalid if flight_end is before flight_start' do
    campaign = Campaign.new(name: 'UNICORNS!!!', flight_start: Date.new(2014,01,28), flight_end: Date.new(2014,01,27))
    campaign.valid?
    assert campaign.errors.full_messages.include?('Flight start must be earlier than campaign flight end date')
  end
end

Not so different, right? Takes less time since I’m not writing to the database and the only major difference is that I don’t assert that the object is valid. Instead I check to see if it is adding my error message. This helps simplify tests, even for more complicated objects.

Test Unit + Shoulda

Do you use Thoughtbot’s shoulda matchers? If not you should. Super handy for testing Rails applications. However, I did ran into an issue that I banged my head on the wall for an hour before noticing the very simple problem.

I was adding some tests to a controller, and, in this case, they were already written but commented out, so I was just editing them and getting them to work. We use the shoulda matchers and the accompanying context blocks to organize our tests, but the tests I was editing were just using basic Test Unit syntax (test “this is what i’m testing” do). I kept getting an ArgumentError (1 for 2). However, the function I was testing only had one argument, so I couldn’t figure out why it was asking for a second. The issue ended up being that the tests were within a context block and context blocks do not work with Test Unit. Once I converted it to should “this is what I’m testing” do, it worked perfectly.

Simple mistake, but easy to miss if you are trying to fix up legacy code.

Git Rebase

For a while I was staying away from git rebase because I kept getting crazy errors and commits that weren’t mine whenever I tried to rebase. No more!

# rebase!
git checkout branch-i-want-to-merge
git log
git rebase -i HEAD~6
git log
git rebase old-branch
git checkout old-branch
git merge branch-i-want-to-merge

Command by command:

I have a branch called branch-i-want-to-merge that has 6 commits. I have a master branch called old-branch that I want to merge my branch into, but not before cleaning up the commit history (does everyone need to know that I forgot an s?).

I have branch-i-want-to-merge checked out. I double check my number of commits by doing a git log and counting them. I see 6, so I do a git rebase -i HEAD~6. After this, I do a git log again to verify that I only have 1 commit.

Now I want to make sure my new branch has all the commits from the old branch, so I do git rebase old-branch. Success!

Final steps: I check out old-branch, then do merge in my new branch with a git merge branch-i-want-to-merge. All done! That wasn’t so hard, right?