【问题标题】:Rails - Don't repeat yourself on scope definitionRails - 不要重复范围定义
【发布时间】:2014-08-01 09:20:18
【问题描述】:

这是一个示例模型:

class Book < AR::Base
  has_many :pages

  scope :with_some_conditions, ->(var) {
    where(... something with var ...)
    .joins(... some joins ...)
  }
end

class Page << AR::Base
  # Attrs : a, b (integers)
  belongs_to :book

  scope :with_c, {
    select("#{Page.table_name}.*, (a+b) AS c")
  }

  def c; a+b; end
end

我正在努力获得c 值最大的10 个pages,在某些条件下属于books

此代码正在运行:

Book.with_some_conditions('foo').map(&:pages).map(&:c)[0...10]

或者更好

Book.with_some_conditions('foo').includes(:pages).map(&:pages).map(&:c)[0...10]

现在想象c 方法不像+ 那样简单,而是一个真的 更复杂的函数(带有连接和其他一些东西)。这段代码只是尽可能地未优化...所有c 必须在 Rails 中计算和排序...SQL 会很有帮助。

Page 模型中定义范围是我发现的更好的解决方案:

scope :big_scope, ->(var) {
  joins(:book)
  .where(... something with var ...) # The 2 lines are C/P from Book model
  .joins(... some joins ...)
  .select("#{Page.table_name}.*, (a+b) AS c")
}

然后,调用Page.big_scope('foo').order(:c =&gt; :desc) 就完美了。

问题是我在重复自己:完整的范围在 2 个不同的类中写了 2 次。

  .where(... something with var ...)
  .joins(... some joins ...)

有什么方法可以通过关系“调用”作用域吗?

问候

【问题讨论】:

  • 处理重复的常用方法是将代码放在一个模块中,并将该模块包含在两个类中。
  • @MaxWilliams 如何将 2 个不同类的“范围”包含到一个模块中?

标签: ruby-on-rails ruby-on-rails-4 has-many


【解决方案1】:

如果我想在两个或多个类之间共享方法,这是我使用的标准模块“模板”。

module MyModule
  def self.included(base)
    base.extend(ClassMethods)
    base.class_eval do 
      #associations, callbacks, scopes, validations etc go here
    end
  end

  #instance methods go here

  module ClassMethods
    #class methods go here
  end    
end

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-08-02
    • 2018-01-28
    • 2013-08-22
    • 1970-01-01
    • 1970-01-01
    • 2012-05-11
    • 2017-11-14
    • 2018-10-05
    相关资源
    最近更新 更多