在ActiveRecord中重写“查找”DRY方式
我有几个模型需要在其上放置自定义查找条件。例如,如果我有一个联系人模型,每次调用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)
你不告诉我们你在使用轨道的版本[编辑 - 这是在轨道上2.1以下这样的建议是完全运行],但我会建议您使用以下形式代替超载发现自己:
account.contacts.find(...)
这将自动换行发现,在一个包含用户子句的范围(因为你有ACCOUNT_ID我假设你有帐号的地方接近)
我建议你检查以下内容在范围
给出具体回答你的问题,我建议把上述方法成模块被包含在有问题的模型中;所以你会有
class Contact
include NarrowFind
...
end
PS。注意sql转义的account_id,你应该使用:conditions=>[".... =?", $account_id]
语法。
完全覆盖模型的基本查找器很可能是一个坏主意,因为它会打破团队以外任何人的期望,包括插件作者(认为搜索插件),更不用说破坏导轨本身的风险(不太可能但不可能) – Jean 2008-09-17 07:37:55
让的建议是健全的。假设你的模式是这样的:
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
感谢吉恩,将工作一种享受,它可能是正道去做吧。帐户的引入是对现有代码的新增加,所以我想从这个角度来看,我已经完成了复杂的事情。我只需通过并修改现有的代码,使其受到帐户的限制。 – 2008-09-17 06:22:04