Ruby on Rails ActiveRecord范围与类方法

Sub*_*dra 14 ruby ruby-on-rails rails-activerecord

Rails在内部将范围转换为类方法,那么为什么我们不能自己使用类方法而不是使用范围.

mu *_*ort 13

精美指南:

14作用域
[...]
为了定义一个简单的作用域,我们scope在类中使用该方法,在调用此作用域时传递我们想要运行的查询:

class Article < ActiveRecord::Base
  scope :published, -> { where(published: true) }
end
Run Code Online (Sandbox Code Playgroud)

这与定义类方法完全相同,您使用的是个人偏好:

class Article < ActiveRecord::Base
  def self.published
    where(published: true)
  end
end
Run Code Online (Sandbox Code Playgroud)

特别注意:

这与定义类方法完全相同,您使用的是个人偏好

而一个远一点(在Rails3中莅临指导也说了同样的事情BTW):

14.1传入参数
[...]
使用类方法是接受范围参数的首选方法.

所以你使用它是一个偏好的问题,甚至建议你对带参数的作用域使用类方法.

使用scope主要是一个符号问题.如果你说scope :whatever那么你明确地说这whatever是一个查询构建者; 如果你说def self.whatever那么你并没有暗示任何关于whatever方法的意图,你只是定义一些类方法可能会或可能不像一个范围.

当然,14.1通过建议scope你的范围采用参数时不要使用,使得这种符号的区别变得混乱.还要记住,在Rails3中你可以说:

scope :published, where(published: true)
Run Code Online (Sandbox Code Playgroud)

所以一个无争议的范围在视觉上"干净"并且简洁但是添加一个lambda来处理参数将使它看起来更加混乱:

scope :pancakes, ->(x) { where(things: x) }
Run Code Online (Sandbox Code Playgroud)

但是Rails4甚至想要无争议的范围内的lambdas,这种区别现在更没意义了.

我怀疑这一点上的差异是历史性的.范围在之前的时代可能是一些特殊的东西,但在Rails3时代变成了普通的旧类方法,以减少重复并更好地与Rails3附带的新查询接口进行网格化.


因此,scope如果您愿意,可以跳过并直接进入课程方法.当您的范围需要参数时,甚至鼓励您这样做.


Som*_*rma 5

Scopes只是在class methods. 内部活动记录将范围转换为类方法。

“它们之间没有区别”或“这是品味问题”。我倾向于同意这两个句子,但我想说明两者之间存在的一些细微差别。这个博客很好地解释了差异。