【问题标题】:Overriding "find" in ActiveRecord the DRY way以 DRY 方式覆盖 ActiveRecord 中的“查找”
【发布时间】:2010-09-09 23:22:50
【问题描述】:

我有几个模型需要自定义查找条件。例如,如果我有一个 Contact 模型,每次调用 Contact.find 时,我都想限制返回的联系人仅属于正在使用的 Account。

我通过谷歌找到了这个(我已经定制了一点):

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 v2.1)

【问题讨论】:

    标签: ruby-on-rails ruby activerecord metaprogramming overriding


    【解决方案1】:

    您没有告诉我们您使用的是哪个版本的 rails [编辑 - 它在 rails 2.1 上,因此遵循的建议是完全可操作的],但我建议您使用以下形式而不是重载自己:

    account.contacts.find(...) 
    

    这将自动将 find 包装在包含 user 子句的范围内(因为您有 account_id,我假设您的帐户在某个附近)

    我建议您查看以下有关范围的资源

    【讨论】:

    • 感谢 Jean,这将是一种享受,并且可能是正确的方法。 Account 的引入是对现有代码的新补充,所以我想我从这个角度来看过于复杂了。我将通过并修改现有代码以由 Account 限定范围。
    【解决方案2】:

    要对您的问题给出具体答案,我建议将上述方法移入模块中,以包含在相关模型中;所以你会有

    class Contact
      include NarrowFind
      ...
    end
    

    附言。注意account_id的sql转义,你应该使用:conditions=>[".... =?", $account_id]语法。

    【讨论】:

    • 完全覆盖模型的基本查找器很可能是个坏主意,因为它会打破团队外任何人的期望,包括插件作者(想想搜索插件),更不用说打破轨道的风险本身(不太可能但并非不可能)
    【解决方案3】:

    Jean 的建议很有道理。假设您的模型如下所示:

    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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-09-27
      • 1970-01-01
      • 2020-04-25
      • 2019-11-29
      • 2011-02-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多