ActiveRecord Rails 3 范围与类方法

发布于 2024-11-05 04:02:48 字数 1560 浏览 0 评论 0原文

我对 ActiveRecord 的新查询界面很陌生,所以我仍在弄清楚。

我希望有人能够解释在 ActiveRecord 模型中使用 scope 和仅使用类方法(即 self.some_method)之间的区别

。总是期望返回一个关系,而类方法不一定必须返回。这是真的吗?

例如,我认为这样做是有意义的:

class Person
  scope :grouped_counts, group(:name).count
end

但这不起作用。我收到此错误:

ArgumentError: Unknown key(s): communicating, failed, matched, unmatched
    from /Users/bradrobertson/.rvm/gems/ruby-1.9.2-p180@influitive/gems/activesupport-3.0.5/lib/active_support/core_ext/hash/keys.rb:43:in `assert_valid_keys'
    from /Users/bradrobertson/.rvm/gems/ruby-1.9.2-p180@influitive/gems/activerecord-3.0.5/lib/active_record/relation/spawn_methods.rb:110:in `apply_finder_options'
    from /Users/bradrobertson/.rvm/gems/ruby-1.9.2-p180@influitive/gems/activerecord-3.0.5/lib/active_record/named_scope.rb:110:in `block in scope'
    from (irb):48
    from /Users/bradrobertson/.rvm/gems/ruby-1.9.2-p180@influitive/gems/railties-3.0.5/lib/rails/commands/console.rb:44:in `start'
    from /Users/bradrobertson/.rvm/gems/ruby-1.9.2-p180@influitive/gems/railties-3.0.5/lib/rails/commands/console.rb:8:in `start'
    from /Users/bradrobertson/.rvm/gems/ruby-1.9.2-p180@influitive/gems/railties-3.0.5/lib/rails/commands.rb:23:in `<top (required)>'
    from script/rails:6:in `require'
    from script/rails:6:in `<main>'
r

但是它确实可以作为类方法工作

def self.grouped_counts
  group(:name).count
end

我有兴趣了解人们对何时使用范围以及何时使用类方法的想法。我是否正确地假设范围必须始终返回关系,但类方法可以返回它想要的任何内容?

I'm new to the new query interface of ActiveRecord so I'm still figuring things out.

I was hoping someone could explain the difference between using a scope in an ActiveRecord model and just using a class method (ie self.some_method)

From what I can gather, a scope is always expected to return a relation, whereas a class method doesn't necessarily have to. Is this true?

For instance, I thought it would make sense to do something like:

class Person
  scope :grouped_counts, group(:name).count
end

But this doesn't work. I get this error:

ArgumentError: Unknown key(s): communicating, failed, matched, unmatched
    from /Users/bradrobertson/.rvm/gems/ruby-1.9.2-p180@influitive/gems/activesupport-3.0.5/lib/active_support/core_ext/hash/keys.rb:43:in `assert_valid_keys'
    from /Users/bradrobertson/.rvm/gems/ruby-1.9.2-p180@influitive/gems/activerecord-3.0.5/lib/active_record/relation/spawn_methods.rb:110:in `apply_finder_options'
    from /Users/bradrobertson/.rvm/gems/ruby-1.9.2-p180@influitive/gems/activerecord-3.0.5/lib/active_record/named_scope.rb:110:in `block in scope'
    from (irb):48
    from /Users/bradrobertson/.rvm/gems/ruby-1.9.2-p180@influitive/gems/railties-3.0.5/lib/rails/commands/console.rb:44:in `start'
    from /Users/bradrobertson/.rvm/gems/ruby-1.9.2-p180@influitive/gems/railties-3.0.5/lib/rails/commands/console.rb:8:in `start'
    from /Users/bradrobertson/.rvm/gems/ruby-1.9.2-p180@influitive/gems/railties-3.0.5/lib/rails/commands.rb:23:in `<top (required)>'
    from script/rails:6:in `require'
    from script/rails:6:in `<main>'
r

It does however work as a class method

def self.grouped_counts
  group(:name).count
end

I'm interested to know peoples' thoughts on when to use scopes and when to use class methods. Am I correct in assuming that a scope must always return a relation, but a class method can return whatever it wants?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

千笙结 2024-11-12 04:02:49

Rails 2.x 中存在更多差异,因为named_scopes 不执行查询(因此您可以链接它们),而类方法通常会执行查询(因此您无法链接它们),除非您手动包装查询在 scoped(...) 调用中。

在 Rails 3 中,所有内容都会返回 ActiveRecord::Relation 直到您需要实际结果,因此作用域可以针对类方法进行链接,反之亦然(只要类方法返回 ActiveRecord::关系对象,而不是其他对象类型(如计数))。

一般来说,我使用 scope 条目作为简单的单行语句来过滤结果集。但是,如果我在“范围”中做任何复杂的事情,可能需要详细的逻辑、lambda、多行等,我更喜欢使用类方法。正如您所发现的,如果我需要返回计数或类似的内容,我会使用类方法。

There was more of a difference in Rails 2.x, since named_scopes did not execute your queries (so you could chain them), whereas class methods generally did execute the queries (so you could not chain them), unless you manually wrapped your query in a scoped(...) call.

In Rails 3, everything returns an ActiveRecord::Relation until you need the actual results, so scopes can be chained against class methods and vice versa (as long as the class methods return ActiveRecord::Relation objects, not some other object type (like a count)).

Generally, I use scope entries for simple one-liners to filter down my result set. However, if I'm doing anything complicated in a "scope" which may require detailed logic, lambdas, multiple lines, etc., I prefer to use a class method. And as you caught, if I need to return counts or anything like that, I use a class method.

ヅ她的身影、若隐若现 2024-11-12 04:02:49

正如 Dylan 在他的回答中提到的,作用域和类方法之间的一个区别是,作用域是在类被调用时评估的。已加载。这可能会导致意想不到的结果。

例如,

class Post < ActiveRecord::Base
    scope :published_earlier, where('published_at < ?', Date.today)
end

容易出错。正确的方法是使用 lambda

class Post < ActiveRecord::Base
    scope :published_earlier, -> { where('published_at < ?', Date.today) }
end

Lambda 块被延迟计算。因此 Date.today 在您调用作用域时运行,而不是
当评估班级时。

如果使用类方法,则不需要使用 lambda。

class Post < ActiveRecord::Base
    def self.published_earlier
        where('published_at < ?', Date.today)
    end
end

因为对于类方法,代码是在方法调用时运行的。

As Dylan alluded to in his answer, one difference between scope and class method is that scopes are evaluated when the class is loaded. This may lead to unexpected result.

For example,

class Post < ActiveRecord::Base
    scope :published_earlier, where('published_at < ?', Date.today)
end

is prone to error. The correct way is to use a lambda

class Post < ActiveRecord::Base
    scope :published_earlier, -> { where('published_at < ?', Date.today) }
end

Lambda block is lazily evaluated. So Date.today is run when you call the scope, not
when the class is evaluated.

If you use a class method, then you don't need to use lambda.

class Post < ActiveRecord::Base
    def self.published_earlier
        where('published_at < ?', Date.today)
    end
end

Because with class method, the code is run at the time of method call.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文