Overriding "find" in ActiveRecord in a dry way

I have several models that must have custom search terms installed on them. For example, if I have a Contact model, every time Contact.find is called, I want to restrict returned contacts that belong only to the account in use.

I found this via Google (which I set up a bit):

def self.find(*args)
  with_scope(:find => { :conditions =>  "account_id = #{$account.id}" }) do
    super(*args)
  end
end

This works fine, except in a few cases where account_id is ambiguous, so I adapted it for:

def self.find(*args)
  with_scope(:find => { :conditions =>  "#{self.to_s.downcase.pluralize}.account_id = #{$account.id}" }) do
    super(*args)
  end
end

It also works great, however, I want it to be DRY. Now I have several different models in which I want to use this function. What is the best way to do this?

When you answer, please include code to help our mind understand Ruby-fu metaprogramming.

( Rails v2.1)

+5
3

. , :

class Contact < ActiveRecord::Base
  belongs_to :account
end

class Account < ActiveRecord::Base
  has_many :contacts
end

contacts , , Contact, , :

@account.contacts

, , find:

@account.contacts.find(:conditions => { :activated => true })

, :

class Contact < ActiveRecord::Base
  belongs_to :account
  named_scope :activated, :conditions => { :activated => true }
end

:

@account.contacts.activated
+5

, , ;

class Contact
  include NarrowFind
  ...
end

PS. sql- account_id, , , :conditions=>[".... =?", $account_id].

0
source

All Articles