diff options
author | Neeraj Singh <neerajdotname@gmail.com> | 2013-03-08 08:38:43 -0500 |
---|---|---|
committer | Neeraj Singh <neerajdotname@gmail.com> | 2013-03-08 08:38:43 -0500 |
commit | 2b8a05f35fbf510907cd133616f45cae120e235f (patch) | |
tree | e7b8b6399ca7bf2b1732b7172378b6ea5b80a747 | |
parent | c27f9481dfd1d8196ff727b6f4934892b567bc01 (diff) | |
download | rails-2b8a05f35fbf510907cd133616f45cae120e235f.tar.gz rails-2b8a05f35fbf510907cd133616f45cae120e235f.tar.bz2 rails-2b8a05f35fbf510907cd133616f45cae120e235f.zip |
Explained how merging of scope works
-rw-r--r-- | guides/source/active_record_querying.md | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/guides/source/active_record_querying.md b/guides/source/active_record_querying.md index 575666aafb..da1b4fcbf9 100644 --- a/guides/source/active_record_querying.md +++ b/guides/source/active_record_querying.md @@ -1196,6 +1196,62 @@ Using a class method is the preferred way to accept arguments for scopes. These category.posts.created_before(time) ``` +### Merging of scopes + +Just like `where` clauses scopes are merged using `AND` conditions. + +```ruby +class User < ActiveRecord::Base + scope :active, -> { where state: 'active' } + scope :inactive, -> { where state: 'active' } +end + +```ruby +User.active.inactive +# => SELECT "users".* FROM "users" WHERE "users"."state" = 'active' AND "users"."state" = 'inactive' +``` + +We can mix and match `scope` and `where` conditions and the final sql +will have all conditions joined with `AND` . + +```ruby +User.active.where(state: 'finished') +# => SELECT "users".* FROM "users" WHERE "users"."state" = 'active' AND +"users"."state" = 'finished' +``` + +If we do want the `last where clause` to win then `Relation#merge` can +be used . + +```ruby +User.active.merge(User.inactive) +# => SELECT "users".* FROM "users" WHERE "users"."state" = 'inactive' +``` + +One important caveat is that `default_scope` will be overridden by +`scope` and `where` conditions. + +```ruby +class User < ActiveRecord::Base + default_scope { where state: 'pending' } + scope :active, -> { where state: 'active' } + scope :inactive, -> { where state: 'active' } +end + +User.all +# => SELECT "users".* FROM "users" WHERE "users"."state" = 'pending' + +User.active +# => SELECT "users".* FROM "users" WHERE "users"."state" = 'active' + +User.where(state: 'inactive') +# => SELECT "users".* FROM "users" WHERE "users"."state" = 'inactive' +``` + +As you can see above the `default_scope` is being overridden by both +`scope` and `where` condition. + + ### Applying a default scope If we wish for a scope to be applied across all queries to the model we can use the |