Ruby on rails 作用域的真正好处是什么
我已经看了10多页,试图找到作用域相对于任何其他返回ActiveRecord::Relation的ActiveRecord类方法的优势 例如,在下面的示例中,为什么作用域比下面做同样事情的备选方案更好:Ruby on rails 作用域的真正好处是什么,ruby-on-rails,activerecord,scope,Ruby On Rails,Activerecord,Scope,我已经看了10多页,试图找到作用域相对于任何其他返回ActiveRecord::Relation的ActiveRecord类方法的优势 例如,在下面的示例中,为什么作用域比下面做同样事情的备选方案更好: #scope :pat1, lambda {{:conditions => ["name like ?", 'J%']}} #scope :pat2, lambda {{:conditions => ["id > 5"]}} def self.p
#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对象,该对象将允许对其调用其他方法(如其他作用域)。”
-
“作用域优于普通类方法的主要原因是它们可以与其他方法链接”
…但上述替代方案也可以链接起来产生相同的结果
我只是想知道这里是否有皇帝的新衣。即使从句法的角度来看,似乎也没有什么好处。它们更快吗?一些消息来源含糊其辞地暗示了这一点 是的,它们是语法上的捷径,基本上代表了您找到的方法。
为什么更好?
最直接的效果是,2行代码比9行代码更易于阅读和维护
Rails总是寻求一种枯燥的方法,在这里重复的
def self.method end
掩盖了实际的代码 当您编写一个作用域时,它实际上也在做同样的事情。以下是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\u id
ActiveRecord作用域实际上只是一种最佳实践中的语法糖衣,如前所述
在Rails的2.x时代,当它们被称为“named_scope”时,它们更为重要。它们允许轻松链接生成查询的条件。通过使用Arel改进Rails3.x,可以很容易地为查询关系创建函数,如您所述。Scopes只是为可链接的预定义查询提供了一个简单而优雅的解决方案。将所有作用域放在模型的顶部可以提高可读性,并有助于展示如何使用模型。作用域和返回关系的类方法之间有一些非常有趣的区别
param.present?
check的作用域,更容易处理nil参数,对于类方法,如果param会导致nil关系,则必须显式返回非nil关系要了解详细情况,请参阅。感谢您和肖恩·希尔确认这不是速度问题。上面的railstutorial.org链接一开始就明确指出,他们使用作用域的替代实现在某种程度上更快,但显然与使用作用域的替代实现无关。我假设Arel意味着ActiveRecord::Relation。好啊对我来说,语法上的好处似乎是有争议的。但如果他们在做一些标准方法在以前的版本中无法做到的事情,那么这就是原因。rails使用更好的语法是很重要的。不是针对第1天(甚至100天)的代码库,而是针对第1000天的代码库。