2008-09-17 56 views
5

我有幾個模型需要在其上放置自定義查找條件。例如,如果我有一個聯繫人模型,每次調用Contact.find時,我想限制只屬於正在使用的帳戶返回的聯繫人。在ActiveRecord中重寫「查找」DRY方式

我發現這個通過谷歌(我已經定製了一點):

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

這除了少數場合ACCOUNT_ID是模糊的偉大工程,所以我把它適用於:

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

這也很好,但是,我希望它是乾的。現在我有幾個不同的模型,我希望使用這種功能。做這個的最好方式是什麼?

當您回答時,請包含代碼以幫助我們的頭腦掌握元編程Ruby-fu。

(我用Rails 2.1)

回答

8

你不告訴我們你在使用軌道的版本[編輯 - 這是在軌道上2.1以下這樣的建議是完全運行],但我會建議您使用以下形式代替超載發現自己:

account.contacts.find(...) 

這將自動換行發現,在一個包含用戶子句的範圍(因爲你有ACCOUNT_ID我假設你有帳號的地方接近)

我建議你檢查以下內容在範圍

+0

感謝吉恩,將工作一種享受,它可能是正道去做吧。帳戶的引入是對現有代碼的新增加,所以我想從這個角度來看,我已經完成了複雜的事情。我只需通過並修改現有的代碼,使其受到帳戶的限制。 – 2008-09-17 06:22:04

0

給出具體回答你的問題,我建議把上述方法成模塊被包含在有問題的模型中;所以你會有

class Contact 
    include NarrowFind 
    ... 
end 

PS。注意sql轉義的account_id,你應該使用:conditions=>[".... =?", $account_id]語法。

+0

完全覆蓋模型的基本查找器很可能是一個壞主意,因爲它會打破團隊以外任何人的期望,包括插件作者(認爲搜索插件),更不用說破壞導軌本身的風險(不太可能但不可能) – Jean 2008-09-17 07:37:55

5

讓的建議是健全的。假設你的模式是這樣的:

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 }) 

如果你發現自己合作nstantly查詢激活的用戶,你可以重構它到一個名爲範圍:

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

,你會再使用這樣的:

@account.contacts.activated