17

Can somebody explain what this method does and what I can pass to it?

scoped(options = nil)
Returns an anonymous scope.

And also what the scope method does? I don't understand after reading the documentation.

LuckyLuke
  • 47,771
  • 85
  • 270
  • 434

2 Answers2

32

In ActiveRecord, all query building methods (like where, order, joins, limit and so forth) return a so called scope. Only when you call a kicker method like all or first the built-up query is executed and the results from the database are returned.

The scoped class method also returns a scope. The scope returned is by default empty meaning the result set would not be restricted in any way meaning all records would be returned if the query was executed. You can use it to provide an "empty" alternative like in the query_by_date example by MurifoX. Or you can use it to combine multiple conditions into one method call, like for example:

Model.scoped(:conditions => 'id < 100', :limit => 10, :order => 'title ASC')

# which would be equivalent to
Model.where('id < 100').limit(10).order('title ASC')

The scope class method allows you to define a class method that also returns a scope, like for example:

class Model
  scope :colored, lambda {|col|
    where(:color => col)
  }
end

which can be used like this:

Model.colored

The nice thing with scopes is that you can combine them (almost) as you wish, so the following is absolutely possible:

Model.red.where('id < 100').order('title ASC').scoped(:limit => 10)

I also strongly suggest reading through http://guides.rubyonrails.org/active_record_querying.html

severin
  • 10,148
  • 1
  • 39
  • 40
  • Thanks severin, it helped. How do I know what I can pass to .scoped? I see :conditions => etc. – LuckyLuke Aug 10 '12 at 12:58
  • 1
    You'll find a full list of all options here: http://api.rubyonrails.org/classes/ActiveRecord/FinderMethods.html#method-i-find-label-Options – severin Aug 10 '12 at 14:31
  • 3
    fyi as of Rails 4, `.scoped` is deprecated. `.all` instead replaces `.scoped` http://stackoverflow.com/questions/18198963/with-rails-4-model-scoped-is-deprecated-but-model-all-cant-replace-it/ – Jordan Michael Rushing Aug 29 '14 at 15:26
  • @JordanMichaelRushing you are right, but the question was explicitly about `.scoped` in Rails 3; so I'll just leave my answer as it is... – severin Sep 15 '14 at 07:13
7

I have used it in the past.When you make chained calls to the ActiveRecord query interface like this:

Model.where(:conditions).where(:more_conditions).where(:final_conditions)

Each one of them is already scoped, making the chain work without any problems. But let's say you have something like this:

Model.query_by_date(date).query_by_user(user).query_by_status(status)

scope :query_by_date, lambda { |date|
  case date
  when "today"
    where(:date => Date.today)
  when "tomorrow"
    where(:date => Date.tomorrow)
  else
    # Any value like '' or 0 or Date.whatever
  end
}

This would cause an error if the date param is not today or tomorrow. It would pick the last value and try to chain this query with the next one query_by_user, resulting in a undefined method default_scoped? for ''. But if you put a scoped method in the else condition, it would work without any flaws, because you are saying to activerecord that you pass through this method/named scope and didn't make any calls to where/find/other activerecord methods, but returned a scoped object, so you can continue chaining queries and stuff.
It would be this way in the end.

else
  scoped
end

Hope you understand this simple example.

MurifoX
  • 14,991
  • 3
  • 36
  • 60
  • Could you explain what it means to be "scoped"? – LuckyLuke Aug 10 '12 at 12:14
  • 1
    It's like "being" an ActiveRecord compliant. Encapsulated by all of ActiveRecords specifications. – MurifoX Aug 10 '12 at 12:17
  • I am not sure if I understand "scoped" other than that I understand what you mean...that is, I see it will fail otherwise. But I don't understand what the "scoped" can do and is. – LuckyLuke Aug 10 '12 at 14:11
  • So scoped means, "pretend the results I return were returned by a scope" or even "here is an empty scope" – traday May 15 '16 at 17:14