2008-09-17 57 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