Nick Kallen noted that the behavior of has_many_with_args can be accomplished using has_finder.

Too true!

Imagine a system in which Users send Whispers to one another. We would like to see Whispers scoped so that:

  • A User viewing their own Whispers should see all Whispers they have received

  • A User viewing another User’s Whispers should see only Whispers they themselves sent

With the clean chainable syntax provided by has_finder, this is straight-forward. We return associations directly (notice, no find calls) and isolate declaration of the scoping the behavior to the class affected by it.

class Whisper < ActiveRecord::Base
  has_finder :from, lambda { |sender| { :conditions => [ 'sender_id = ?', sender.id ] } }
end
 
class User < ActiveRecord::Base
  has_many :received_whispers, :foreign_key => 'recipient_id'
 
  def whispers_viewable_by user
    return whispers if self == user
    whispers.from(user)
  end
end

How expressive is that? Business rules are cleanly captured in the models and our associations stay so limber!

Thanks to Pat Maddox for turning me on to has_finder, and Nick Kallen for writing it.

Leave a Comment

Enclose code in <code lang="ruby"></code> if you care.
Preview your comment using the button below.