以 DRY 方式覆盖 ActiveRecord 中的“查找”
-
09-06-2019 - |
题
我有一些模型需要为其设置自定义查找条件。例如,如果我有一个联系人模型,则每次调用 Contact.find 时,我想限制返回的联系人仅属于正在使用的帐户。
我通过谷歌找到了这个(我对其进行了一些定制):
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
这也很有效,但是,我希望它是 DRY 的。现在我有几个不同的模型,我希望使用这种功能。做这个的最好方式是什么?
当您回答时,请附上代码以帮助我们的头脑掌握元编程 Ruby-fu。
(我使用的是Rails v2.1)
解决方案
您没有告诉我们您正在使用哪个版本的 Rails [编辑 - 它是在 Rails 2.1 上,因此以下建议是完全可操作的],但我建议您使用以下形式而不是重载 find myself :
account.contacts.find(...)
这将自动将查找结果包含在包含 user 子句的范围内(因为您有 account_id,我假设您在附近有该帐户)
我建议您检查以下有关范围的资源
其他提示
吉恩的建议是正确的。假设您的模型如下所示:
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
为了给您的问题提供具体的答案,我建议将上述方法移动到一个模块中,以包含在相关模型中;所以你会有
class Contact
include NarrowFind
...
end
附言。注意 account_id 的 sql 转义,你应该使用 :conditions=>[".... =?", $account_id]
句法。
不隶属于 StackOverflow