
Default scope and Named scope in rails
08/30/2010 12:36 am By Sameera Gayan | Articles: 9
Rails is all about making coders happy. It has so many elegant features which boosts developers productivity while keeping the code simplicity. Today I will show you two features that will definitely come handy in your developments. Namely those are
- named scope
- default scope
Let me take an example and go through with you. Just think about the following simple scenario. We have a database table called users. There we have following fields
name → user name
gender → male (m) or female (f)
active → representing if a given user is active or not
Ok , lets start our journey. Say you have written a nice code to display all the users in the screen

Then suddenly your client says he/she wants to see only the active users (active = 1), where as currently you are showing all the users.
No problem you say. And you can add following code to your model
class User < ActiveRecord::Base
def self.active_users
self.find_all_by_active(1)
end
end
and in your controller you say
@users = User.active_users
done.. But. In the very next day your client again calls you and tells you he/she wanted to filter active males and active females
Then you might think a bit.. Ah.. OK.. you write the following code
def self.active_users_with_type(type)
self.find_all_by_active_and_gender(1,type)
end
self.find_all_by_active_and_gender(1,type)
end
and you pass male (m) or female (f) as the parameter. Cool.. you saved the day.. But unfortunately that is also only for 2-3 days. Then your client comes with following requirements
1- should be able to see all the active users
2- should be able to see all the males/females (both active and inactive)
3- should be able to see all the active male/ female users
For these kind of requirements, if you use the above scenario , you will end up by having so many methods which are different only by slight condition. With rails there should be a way of achieve this. So its ‘named scope’ to the rescue.
named scope
Think of it in this way. Named scope is a labeled condition of set of conditions. Let me explain our example further.
Get the 1 st requirement
1 - should be able to see all the active users
So instead of writing our own method we can use a named scope for this.
In your model
named_scope :active, :conditions => {:active => 1}
Syntax - named_scope <scope name>, :conditions => <sql conditions>
class User < ActiveRecord::Base
named_scope :active, :conditions => {:active => 1}
end
Syntax - named_scope <scope name>, :conditions => <sql conditions>
class User < ActiveRecord::Base
named_scope :active, :conditions => {:active => 1}
end
So then you call it from controller
@users = User.active
Isn't that simple and more elegant !.
OK, then let’s take the next requirement
2- should be able to see all the males/females (both active and inactive
This is also same as earlier, but the only difference is it takes an argument (male or female)
Lets see how we can write this
named_scope :gender, lambda {|gender|{:conditions => "gender='"+ gender + "'"}}
syntax : named_scope <scope name>, lambda {|<parameter>|{:conditions => “<condition with parameter>”}}
syntax : named_scope <scope name>, lambda {|<parameter>|{:conditions => “<condition with parameter>”}}
So now your model will be like this
class User < ActiveRecord::Base
named_scope :active, :conditions => {:active => 1}
named_scope :gender, lambda {|gender|{:conditions => "gender='"+ gender + "'"}}
end
named_scope :active, :conditions => {:active => 1}
named_scope :gender, lambda {|gender|{:conditions => "gender='"+ gender + "'"}}
end
and call it as
@users = User.gender('f')
Isn’t it clean than the previous approach!
OK now we have one more requirement to develop
3 - should be able to see all the active male/ female users
Here is the beauty of named scope, that is you can combine two or more named scopes. Yes you heard it right to get all the active male/ female users you don't have to write anything in the model
all you have to do is, in your controller
@users = User.gender('m').active
here you have combine gender named scope and active name scope. This is a very good example of rails DRY (Dont Repeat Yourself) principles.
I hope now you can understand the power of using named scope
Hold on, this isn’t the end of it. Now your client is very thrilled and ask you to sort all these queries using the user name
Ah...... isn't there another rails magic for this? Without you writing order by clues for each of these selects.. Yes there is. Its called ‘default scope’
default scope
Default scope will apply all the sql queries by default
just add following line to your model
default_scope :order => 'name ASC'
syntax : default_scope <condition>
This will do the trick..
So those are the basic usages of named scope and default scope. This is a very useful feature in rails and this will cut off so many un-necessary codes
So thats it for today and see you next time with another ruby/rails tip, until then happy programing



Post new comment