ActiveRecord Rails 3 vs class method

I'm new to the new ActiveRecord query interface, so I'm still good at it.

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

From what I can compile, it is always expected that the scope returns a relation, whereas the class method does not have to. It's true?

For example, I thought it made sense to do something like:

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

But that does not 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 

However, it works as a class method

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

I am interested in knowing people's thoughts about when to use areas and when to use class methods. Am I right in assuming that a scope should always return a relation, but a class method can return what it wants?

+50
activerecord ruby-on-rails-3 class-method scopes
May 05 '11 at 14:50
source share
2 answers

There were more differences in Rails 2.x, because named_scopes didn’t fulfill your requests (so you could hook them), while class methods usually execute your requests (so you couldn’t bind them), unless you manually wrapped your request in a call scoped(...) .

In Rails 3, everything returns ActiveRecord::Relation until you need the actual results, so areas can be bound to class methods and vice versa (if class methods return ActiveRecord::Relation objects, and not some other type of object ( as an account)).

Typically, I use scope entries for simple single-line filters to filter my result set. However, if I am doing something complicated in a "scope" that may require detailed logic, lambdas, several lines, etc., I prefer to use the class method. And when you caught, if I need to return an account or something like that, I use the class method.

+81
May 05 '11 at 15:00
source share

Like the Dylan mentioned in his answer, the one difference between the scope and class method is that areas are computed when the class loads. This may lead to an unexpected result.

For example,

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

error prone. The right way is to use lambda

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

The lambda block is lazily evaluated. Therefore, Date.today starts when you call the scope, and not when the class is evaluated.

If you use a class method, you do not need to use lambda.

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

Because using the class method, the code is launched during the method call.

+10
Nov 07 '13 at 11:28
source share



All Articles