Gemfile · I codes and I blogs

Paperclip attachments in RSpec factories

Assuming one has a model whose attachments are handled by Paperclip, i.e.

$ rails generate paperclip user photo

app/models/user.rb:

class User < ActiveRecord::Base
  has_attached_file :photo
end

then to generate a test model with FactoryGirl, including the attachment:

spec/factories/user_factory.rb:

include ActionDispatch::TestProcess
FactoryGirl.define do
  factory :user do
    name 'Sample User'
    ...
    photo { fixture_file_upload(Rails.root.join('spec/fixtures/test_img.png'), 'image/png') }
  end
end

Various manipulations of the attached image through the web interface can then be tested with RSpec and Capybara.

Testing images with RSpec

To test whether the right image is displayed on a page:

expect(page).to have_css("img[src*='image_name.png']")

i.e. “Expect page to have an <img> tag whose src attribute contains the name of the required image.”

Learn to delegate (your model methods)

delegate is neat trick that allows one to write cleaner, neater code. Particularly when dealing with ActiveRecord associations, delegate makes it possible to “outsource” a method to an associated object.

class Book < ActiveRecord::Base
  # has attribute 'author'
end

class Chapter < ActiveRecord::Base
  belongs_to :book
  delegate :author, to: :book
end

Without delegate, when dealing with a Chapter object, you’d need to access the book’s author via chapter.book.author. With delegation, this can be neatly shortened to chapter.author, with the .author getting handed off to the associated Book object.

An object can delegate multiple methods to its association, as shown in the example below. Another handy option is to use prefixes with delegate. For instance, using the same approach as above to refer to the book’s title would create chapter.title, which is confusing. With prefixes, however:

class Chapter < ActiveRecord::Base
  belongs_to :book
  delegate :author, :title, to: :book, prefix: true
end

chapter.book_title   # returns book's title
chapter.book_author  # returns book's author

(Of course, if chapters had their own titles, the above code would make them inaccessible, but that’s what you get with contrived examples. See this post on the Pivotal Labs’ blog for a solution.)

One final tidbit to touch upon is that delegate is not limited to deliberately created methods and attributes but extends equally well to those created behind the scenes by the association:

class Quote < ActiveRecord::Base
  belongs_to :chapter
  delegate :book, to: :chapter
end

quote.book  # returns the book object associated with the chapter to which the quote belongs

For more on delegate, including custom prefixes and how to handle NoMethodErrors, see the API Docs.

Is it changed?

Rails has some useful methods to check whether an object has changed since first being loaded into memory. Here are some examples:

2.1.0 :001 > user = User.find(1)
 => #<User id: 1, name: "Roderick", email: "rod@example.com", created_at: ..., updated_at: ...>
2.1.0 :002 > user.name = 'Jimmy'
 => "Jimmy"
2.1.0 :003 > user.changed?
 => true
2.1.0 :004 > user.changed
 => ["name"]
2.1.0 :005 > user.changes
 => {"name"=>["Roderick", "Jimmy"]}
2.1.0 :006 > user.name_changed?
 => true
2.1.0 :007 > user.email_changed?
 => false
2.1.0 :008 > user.name_was
 => "Roderick"
2.1.0 :009 > user.save
 => true
2.1.0 :010 > user.changed?
 => false

More info here: ActiveModel::Dirty.

do..end vs {}: Not just a matter of style!

“Use curly braces for single-line blocks and do..end for multi-lines blocks.” After seeing various permutations of that statement dozens of times, one can come to believe that the difference between the two is purely stylistic and that there is no practical reason to opt for one vs. the other. Most of the time, that is, indeed, true. Until that one-time-in-a-thousand when it’s not.

The trouble with do..end vs. {} can show up thanks to (a) Ruby’s laid-back attitude towards syntax, and (b) the fact that the two kinds of block delimiters do not behave 100% identically.

The syntax slackness in question is the optional usage of parentheses around method parameters. For instance, the following line pairs of code are identical:

FactoryGirl.create(:user) # is the same as
FactoryGirl.create :user

<%= link_to('Sign in', signin_path) %> # is the same as
<%= link_to 'Sign in', signin_path %>

The parentheses can be safely omitted from method calls in the vast majority of cases. That is, unless a block is involved, which brings us to (b). The not-so-subtle difference between do..end and {} is their order of precedence - the curly braces rank higher on that score than do..end. This means that in a parentheses-less method call, the curly braces will bind the block to the preceding parameter, while do..end will bind it to the method.

Example:

$ rails console
2.1.0 :001 > puts [1, 2, 3].map { |x| x * 2 }
2
4
6
2.1.0 :002 > puts [1, 2, 3].map do |x| x * 2; end
#<Enumerator:hex_code>

The first command was equivalent to

puts([1, 2, 3].map { |x| x * 2 })

while the second was interpreted as

puts([1, 2, 3].map) { |x| x * 2 }

In the first case, the block was passed to .map, which evaluated it and then gave the result back to puts. In the second case, the block was passed to puts, which ignored it and only reported that calling .map on an array yields an Enumerator object.