范围的真正好处是什么?

时间:2012-03-15 21:41:22

标签: ruby-on-rails activerecord scope

我查看了10多页试图找到范围的好处,而不是任何其他返回ActiveRecord :: Relation的ActiveRecord类方法。

在下面的示例中,为什么范围比其下方的替代方案更好,它们做同样的事情:

  #scope :pat1,  lambda {{:conditions => ["name like ?", 'J%']}}    
  #scope :pat2,  lambda {{:conditions => ["id  > 5"]}}  

  def self.pat1
    where("name like ?", 'J%')
  end  

  def self.pat2 
    where("id  > 5")
  end  

  def patx 
    self.class.pat1.pat2.first
  end

文档一遍又一遍地说,范围是有益的,因为它们可以被链接......

“所有范围方法都将返回一个ActiveRecord :: Relation对象,该对象将允许在其上调用更多方法(例如其他范围)。” - guides.rubyonrails.org

“范围优于普通类方法的主要原因是它们可以与其他方法链接” http://ruby.railstutorial.org

...但上面的替代方案也可以链接产生相同的结果。

试图弄清楚皇帝的衣服是否会在这里发生。即使从句法角度来看,似乎也没有任何好处。它们是否更快 - 一些消息来源含糊地暗示这一点。

4 个答案:

答案 0 :(得分:3)

当你编写一个范围时,它基本上做同样的事情。以下是Rails源代码:

    def scope(name, scope_options = {})
      name = name.to_sym
      valid_scope_name?(name)
      extension = Module.new(&Proc.new) if block_given?

      scope_proc = lambda do |*args|
        options = scope_options.respond_to?(:call) ? unscoped { scope_options.call(*args) } : scope_options
        options = scoped.apply_finder_options(options) if options.is_a?(Hash)

        relation = scoped.merge(options)

        extension ? relation.extending(extension) : relation
      end

      singleton_class.send(:redefine_method, name, &scope_proc)
    end

在这种情况下,范围的好处是它们是定义查询的惯用方法,在某些情况下,代码行数较少,您可以进行扩展。

源代码中的示例如下所示:

scope :red, where(:color => 'red') do
  def dom_id
    'red_shirts'
  end
end

允许您拨打Model.red.dom_id

答案 1 :(得分:3)

ActiveRecord范围实际上只是最佳实践中包含的语法糖,如前所述。

在Rails的2.x天里,当它们被称为“named_scope”时,它们更重要。它们允许轻松链接生成查询的条件。通过使用Arel对Rails 3.x的改进,如您所述,为查询关系创建函数非常简单。范围只为可链接的预定义查询提供简单而优雅的解决方案。将所有示波器置于模型顶部可提高可读性,并有助于显示模型的使用方式。

答案 2 :(得分:2)

是的,它们是语法快捷方式,基本上代表了你找到的方法 为什么更好?
最直接的影响是2行代码比9行代码更容易阅读和维护。

Rails总是寻求DRY方法,这里重复的def self.method end模糊了实际的代码。

答案 3 :(得分:0)

返回关系的范围和类方法之间存在一些非常有趣的差异。

  1. 使用简单的param.present?检查处理范围的nil参数更容易,对于类方法,如果param会导致nil关系,则必须显式返回非零关系。

  2. 范围比类方法更容易扩展。只需传递一个块(例如处理分页)来添加方法。类方法可以扩展,但不能优雅。

  3. 完整的纲要请参阅this post from Plataformatec