From 2b8a05f35fbf510907cd133616f45cae120e235f Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Fri, 8 Mar 2013 08:38:43 -0500 Subject: Explained how merging of scope works --- guides/source/active_record_querying.md | 56 +++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) (limited to 'guides/source') 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 -- cgit v1.2.3