Why the Rails default_scope is a bad thing
Contact me at LinkedIn  RailsZilla at Facebook  RailsZilla at twitter   google +1  Contact me at Xing  connect me at github

Why the Rails default_scope is a bad thing

Posted in Rails

Activerecord provides default_scope to set a default scope for all operations on the model. I was never a friend of using default_scope, even when many friends used it in their projects. At the first look, it looks convenient but will lead to a headache very soon. We should avoid using it and here is why:

Assume we defined a default_scope in Comment model

1
2
3
class Comment
  default_scope where(published: true).order("created_at desc")
end

In this case the default_scope added some behaviors that we don’t recognize at the first look. The bad news: You can’t override default_scope by default! It lists comments order by created_at. Let’s have a look

1
2
> Comment.limit(10)
  Comment Load (3.3ms)  SELECT `comments`.* FROM `comments` WHERE `comments`.`published` = 1 ORDER BY created_at desc LIMIT 10


If you want to display comments order by updated_at rather than created_at, you may use the following line

1
2
> Comment.order("updated_at desc").limit(10)
  Comment Load (17.3ms)  SELECT `comments`.* FROM `comments` WHERE `comments`.`published` = 1 ORDER BY created_at desc, updated_at desc LIMIT 10

Now we can see, that the call now order by created_at AND updated_at (both). The default scope is not overriden. We have to use unscoped to disable default scope explicitly like this:

1
2
> Comment.unscoped.order("updated_at desc").limit(10)
  Comment Load (1.9ms)  SELECT `comments`.* FROM `comments` ORDER BY updated_at desc LIMIT 10

So we have to remember the model has a default_scope and add unscoped if we want to override the default scope. The default_scope will affect our model initialization:

1
2
> Comment.new
=> #<Comment id: nil, title: nil, created_at: nil, updated_at: nil, user_id: nil, published: true>

My friends and many developers I worked with are not aware this fact. They might think that default_scope only affect queries. In real life it is the wrong way default_scope does the job.

I would suggest not using default_scope any more. A good thing is to define it as a scope and explictly call that scope.

Tags: ,

Leave a Reply

Your email address will not be published. Required fields are marked *

Please enter a secure code to see if you are a spammer ;-)

 

Copyright © 2011-2017  - RailsZilla – Ruby on Rails tutorials, tips and tricks All rights reserved. | Imprint | Privacy