I am working on ScrumPad chat refactoring now. In rails 2, the named_scope feature works really great for ActiveRecord models. Lets start with the code first-
The Source Code:
class ChatUser < ActiveRecord::Base
belongs_to :chat
belongs_to :user
belongs_to :chat_status, :foreign_key => "status_id"
named_scope :closed, lambda {|chat_id| {:conditions => ["status_id = #{ChatStatus::CLOSED} AND chat_id = ? ", chat_id]}} do
def invite()
each { |chat_user| chat_user.update_attribute(:status_id, ChatStatus::INVITED) }
end
end
named_scope :active_chats, lambda {|user_id| {:conditions => ["user_id = ? AND status_id not in (#{ChatStatus::CLOSED}, #{ChatStatus::LEFT})", user_id]}}
named_scope :with_chat, :include => :chat
end
So, you get an idea about the ChatUser class. Its a relation object between user, chat and chat_status with some additional fields.
How am I Using My named_scope?
ChatUser.closed(chat_id)
Gives me all the chat users who closed their chat windows for the chat having chat_id.
ChatUser.closed(chat_id).with_chat
Gives me the same objects as previous but eager loads the chat object. So, it saves plenty of database calls when I need to iterate through the chats!
ChatUser.closed(chat_id).invite()
Invites all users to a chat with chat_id if the buddy closed the chat window.
Why named_scope?
- named_scope is not just a syntactic sugar. It generates much less query using WHERE IN clause instead of WHERE = clause. So, reduces the number of calls to a single call.
- Chaining the named_scope will generate only a single query for the chain. So, ChatUser.closed(chat_id).with_chat will produce only one query.
- You get rid of looping in many cases! It will help you to write concise and clear codes.
- When you can divide the objects in your classes in partitions, then you may wish to write the named_scope for partitioning the data. In my example, the :closed named_scope does this. So, I can add methods to this named_scope which actually works for the closed chats. It is kind of dividing your objects into named groups. So, it increases readability.
Let me know if you have another good example of a real life named_scope in your project.