113

I've recently started an internship. My employer uses ruby on rails, and I frequently encounter new syntax that I need to look up to understand. I've googled around for a good explanation of named_scope, but what I've found so far is mostly blog posts giving high praise for it, rather a straight definition or introduction.

What exactly is named_scope (now simply called scope) in ruby on rails?

Arslan Ali
  • 17,418
  • 8
  • 58
  • 76
Ziggy
  • 21,845
  • 28
  • 75
  • 104
  • possible duplicate of [What's the significance of named scope in Rails?](http://stackoverflow.com/questions/2919730/whats-the-significance-of-named-scope-in-rails) – jdl Feb 02 '11 at 01:50
  • 2
    This blog post was invaluable to me when learning named scopes: http://ryandaigle.com/articles/2008/8/20/named-scope-it-s-not-just-for-conditions-ya-know – Peter Brown Feb 02 '11 at 02:00
  • 1
    @notapatch the link is dead do you have another one? – mbigras Apr 11 '18 at 20:24
  • Ryan Daigle: Named Scope: It's Not Just for Conditions, Ya Know?: https://web.archive.org/web/20160306110506/http://archives.ryandaigle.com/articles/2008/8/20/named-scope-it-s-not-just-for-conditions-ya-know – notapatch Apr 12 '18 at 12:36

4 Answers4

220

A scope is a subset of a collection. Sounds complicated? It isn't. Imagine this:

You have Users. Now, some of those Users are subscribed to your newsletter. You marked those who receive a newsletter by adding a field to the Users Database (user.subscribed_to_newsletter = true). Naturally, you sometimes want to get those Users who are subscribed to your newsletter.

You could, of course, always do this:

User.where(subscribed_to_newsletter: true).each do #something

Instead of always writing this you could, however, do something like this.

#File: users.rb
class User < ActiveRecord::Base
  scope :newsletter, where(subscribed_to_newsletter: true)
  #yada yada
end

If you're using Rails 4 or newer, do this instead:

#File: users.rb
class User < ActiveRecord::Base
  scope :newsletter, -> { where(subscribed_to_newsletter: true) }
  #yada yada
end

This allows you to access your subscribers by simply doing this:

User.newsletter.each do #something

This is a very simple example but in general scopes can be very powerful tools to easy your work.

Check out this link: API Description

Andreas
  • 958
  • 12
  • 14
Michael Schäfermeyer
  • 2,794
  • 1
  • 16
  • 8
  • 7
    Can I ask whats the advantages of this over say defining a method in the User Class called 'subscribedUsers'? e.g. 'def self.subscribedUsers self.where(:subscribed_to_newsletter => true) end – redroot Apr 29 '11 at 09:05
  • 3
    @redroot the advantage is the `scope` syntax is much cleaner, you get the same result but with just one line – Aldo 'xoen' Giambelluca Apr 03 '12 at 15:47
  • 11
    @redroot There used to be a big efficiency advantage, as scopes would query the database lazily while methods would do it eagerly. In Rails 3, methods got lazy too, so now the difference is more syntactic. [Source](http://stackoverflow.com/a/5899890/414220) – evanrmurphy Jan 31 '13 at 18:15
  • API doc link is broken please update http://api.rubyonrails.org/classes/ActiveRecord/Scoping/Named/ClassMethods.html – Lohith MV Apr 17 '14 at 06:54
  • Also allows using scoped routes [link](http://api.rubyonrails.org/classes/ActionDispatch/Routing/Mapper/Scoping.html#method-i-scope) – Benjineer Apr 26 '14 at 01:10
34

scope in active record is like class methods but they return Relation object which means you can call another scope or active record querying method on it.

For example, if you have a Zombie model (zombies table) with below mentioned scope methods,

class Zombie
  scope :rotting, -> { where(rotting: true) }
  scope :fresh, -> { where('age < ?', 25) }
  scope :recent, -> { order(created_at: :desc) }
end

And you call

Zombie.rotting.fresh.recent.limit(3)

It translates to the below in SQL,

select "zombies.*" from "zombies" where "zombies"."rotting" = 't' and (age<20) order by create_at desc limit 3

Example above is based on rails 4 syntax

Rael Gugelmin Cunha
  • 3,327
  • 30
  • 25
Akshatha
  • 460
  • 4
  • 7
  • I can't find an example of order(:created_at, :desc) in any documentation. Is it possible you meant `scope :recent, -> { order(created_at: :desc) }` ? https://apidock.com/rails/v4.2.9/ActiveRecord/QueryMethods/order – notapatch Jul 18 '19 at 15:09
7

The best way to understand about the details is to go to API Documentation.

You'll get the complete details and the ways we can use Scopes.

API Documentation of Scope

123
  • 764
  • 2
  • 8
  • 21
1
  • Imagine you have a model: Person.

Now imagine you :

  • want all the people in the world who have red hair.
  • want all the people in the world who play cricket

You could get those particular classes of people by using a scope!

Person.red_hair.cricket ## finds all people with red hair who play cricket
Person.red_hair ## finds all people with red hair
Person.cricket ## finds all people who play cricket.

Now that wasn't so hard was it?

BenKoshy
  • 33,477
  • 14
  • 111
  • 80