我查看了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
...但上面的替代方案也可以链接产生相同的结果。
试图弄清楚皇帝的衣服是否会在这里发生。即使从句法角度来看,似乎也没有任何好处。它们是否更快 - 一些消息来源含糊地暗示这一点。
答案 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)
返回关系的范围和类方法之间存在一些非常有趣的差异。
使用简单的param.present?
检查处理范围的nil参数更容易,对于类方法,如果param会导致nil关系,则必须显式返回非零关系。
范围比类方法更容易扩展。只需传递一个块(例如处理分页)来添加方法。类方法可以扩展,但不能优雅。
完整的纲要请参阅this post from Plataformatec。