ActiveRecord Rails 3 scope vs class method

匿名 (未验证) 提交于 2019-12-03 08:41:19

问题:

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 `'     from script/rails:6:in `require'     from script/rails:6:in `
' 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?

回答1:

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.



回答2:

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 

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

class Post  { where('published_at 

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 

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



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!