A Rubyologist and a believer of 37Signal philosophy “always under do your competition” . Currently working as a Senior software engineer / Team Lead at Ridgecrest Asia (pvt) Ltd, leading several projects including www.ticketslk.com
 

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

  1. named scope
  2. 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

 

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

 

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>”}}

 

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

 

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

Share/Save
No votes yet

Post new comment