首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >ActiveRecord Rails 3作用域与类方法

ActiveRecord Rails 3作用域与类方法
EN

Stack Overflow用户
提问于 2011-05-05 22:50:42
回答 2查看 16K关注 0票数 53

我刚接触ActiveRecord的新查询接口,所以我还在摸索中。

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

据我所知,作用域总是需要返回关系,而类方法不一定要返回关系。这是真的吗?

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

代码语言:javascript
运行
复制
class Person
  scope :grouped_counts, group(:name).count
end

但这不管用。我得到了这个错误:

代码语言:javascript
运行
复制
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

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

代码语言:javascript
运行
复制
def self.grouped_counts
  group(:name).count
end

我很想知道人们对何时使用作用域和何时使用类方法的想法。假设一个作用域必须总是返回一个关系,但是一个类方法可以返回它想要的任何东西,这样的假设正确吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-05-05 23:00:22

在Rails 2.x中有更大的不同,因为named_scopes不执行您的查询(因此您可以链接它们),而类方法通常执行查询(因此您不能链接它们),除非您手动将查询包装在scoped(...)调用中。

在Rails3中,在需要实际结果之前,所有内容都返回一个计数,因此作用域可以与类方法链接在一起,反之亦然(只要类方法返回ActiveRecord::Relation对象,而不是其他对象类型(如ActiveRecord::Relation ))。

通常,我对简单的一行程序使用scope条目来过滤我的结果集。但是,如果我在“作用域”中做任何复杂的事情,可能需要详细的逻辑、lambdas、多行等,我更喜欢使用类方法。正如你所了解的,如果我需要返回计数或类似的东西,我会使用一个类方法。

票数 85
EN

Stack Overflow用户

发布于 2013-11-07 19:28:58

正如Dylan在他的回答中提到的,作用域和类方法之间的一个区别是,作用域是在类加载时计算的。这可能会导致意外的结果。

例如,

代码语言:javascript
运行
复制
class Post < ActiveRecord::Base
    scope :published_earlier, where('published_at < ?', Date.today)
end

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

代码语言:javascript
运行
复制
class Post < ActiveRecord::Base
    scope :published_earlier, -> { where('published_at < ?', Date.today) }
end

Lambda块被懒惰地评估。因此,Date.today是在调用作用域时运行的,而不是在计算类时运行的。

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

代码语言:javascript
运行
复制
class Post < ActiveRecord::Base
    def self.published_earlier
        where('published_at < ?', Date.today)
    end
end

因为使用类方法时,代码在方法调用时运行。

票数 15
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5899765

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档