Permalink
Browse files

Document the default scopes change on the release notes, CHANGELOG

and upgrating guides

[ci skip]
  • Loading branch information...
1 parent 28a0dd4 commit 6370e69143b5edce1b61135259e1f81006aaee6a @rafaelfranca rafaelfranca committed Feb 18, 2014
Showing with 134 additions and 0 deletions.
  1. +61 −0 activerecord/CHANGELOG.md
  2. +6 −0 guides/source/4_1_release_notes.md
  3. +67 −0 guides/source/upgrading_ruby_on_rails.md
View
61 activerecord/CHANGELOG.md
@@ -1,3 +1,64 @@
+* Default scopes are no longer overriden by chained conditions.
+
+ Before this change when you defined a `default_scope` in a model
+ it was overriden by chained conditions in the same field. Now it
+ is merged like any other scope.
+
+ Before:
+
+ class User < ActiveRecord::Base
+ default_scope { where state: 'pending' }
+ scope :active, -> { where state: 'active' }
+ scope :inactive, -> { where state: 'inactive' }
+ end
+
+ User.all
+ # => SELECT "users".* FROM "users" WHERE "users"."state" = 'pending'
+
+ User.active
+ # => SELECT "users".* FROM "users" WHERE "users"."status" = 'active'
+
+ User.where(state: 'inactive')
+ # => SELECT "users".* FROM "users" WHERE "users"."status" = 'inactive'
+
+ After:
+
+ class User < ActiveRecord::Base
+ default_scope { where state: 'pending' }
+ scope :active, -> { where state: 'active' }
+ scope :inactive, -> { where state: 'inactive' }
+ end
+
+ User.all
+ # => SELECT "users".* FROM "users" WHERE "users"."state" = 'pending'
+
+ User.active
+ # => SELECT "users".* FROM "users" WHERE "users"."status" = 'pending' AND "users"."status" = 'active'
+
+ User.where(state: 'inactive')
+ # => SELECT "users".* FROM "users" WHERE "users"."status" = 'pending' AND "users"."status" = 'inactive'
+
+ To get the previous behavior it is needed to explicitly remove the
+ `default_scope` condition using `unscoped`, `unscope`, `rewhere` or
+ `except`.
+
+ Example:
+
+ class User < ActiveRecord::Base
+ default_scope { where state: 'pending' }
+ scope :active, -> { unescope(where: :state).where(state: 'active') }
+ scope :inactive, -> { rewhere state: 'inactive' }
+ end
+
+ User.all
+ # => SELECT "users".* FROM "users" WHERE "users"."state" = 'pending'
+
+ User.active
+ # => SELECT "users".* FROM "users" WHERE "users"."status" = 'active'
+
+ User.inactive
+ # => SELECT "users".* FROM "users" WHERE "users"."status" = 'inactive'
+
* Perform necessary deeper encoding when hstore is inside an array.
Fixes #11135.
View
6 guides/source/4_1_release_notes.md
@@ -453,6 +453,12 @@ for detailed changes.
### Notable changes
+* Default scopes are no longer overriden by chained conditions.
+
+ Before this change when you defined a `default_scope` in a model
+ it was overriden by chained conditions in the same field. Now it
+ is merged like any other scope. [More Details](upgrading_ruby_on_rails.html#changes-on-default-scopes).
+
* Added `ActiveRecord::Base.to_param` for convenient "pretty" URLs derived from
a model's attribute or
method. ([Pull Request](https://github.com/rails/rails/pull/12891))
View
67 guides/source/upgrading_ruby_on_rails.md
@@ -262,6 +262,73 @@ authors = Author.where(name: 'Hank Moody').to_a
authors.compact!
```
+### Changes on Default Scopes
+
+Default scopes are no longer overriden by chained conditions.
+
+In previous versions when you defined a `default_scope` in a model
+it was overriden by chained conditions in the same field. Now it
+is merged like any other scope.
+
+Before:
+
+```ruby
+class User < ActiveRecord::Base
+ default_scope { where state: 'pending' }
+ scope :active, -> { where state: 'active' }
+ scope :inactive, -> { where state: 'inactive' }
+end
+
+User.all
+# => SELECT "users".* FROM "users" WHERE "users"."state" = 'pending'
+
+User.active
+# => SELECT "users".* FROM "users" WHERE "users"."status" = 'active'
+
+User.where(state: 'inactive')
+# => SELECT "users".* FROM "users" WHERE "users"."status" = 'inactive'
+```
+
+After:
+
+```ruby
+class User < ActiveRecord::Base
+ default_scope { where state: 'pending' }
+ scope :active, -> { where state: 'active' }
+ scope :inactive, -> { where state: 'inactive' }
+end
+
+User.all
+# => SELECT "users".* FROM "users" WHERE "users"."state" = 'pending'
+
+User.active
+# => SELECT "users".* FROM "users" WHERE "users"."status" = 'pending' AND "users"."status" = 'active'
+
+User.where(state: 'inactive')
+# => SELECT "users".* FROM "users" WHERE "users"."status" = 'pending' AND "users"."status" = 'inactive'
+```
+
+To get the previous behavior it is needed to explicitly remove the
+`default_scope` condition using `unscoped`, `unscope`, `rewhere` or
+`except`.
+
+```ruby
+class User < ActiveRecord::Base
+ default_scope { where state: 'pending' }
+ scope :active, -> { unescope(where: :state).where(state: 'active') }
+ scope :inactive, -> { rewhere state: 'inactive' }
+end
+
+User.all
+# => SELECT "users".* FROM "users" WHERE "users"."state" = 'pending'
+
+User.active
+# => SELECT "users".* FROM "users" WHERE "users"."status" = 'active'
+
+User.inactive
+# => SELECT "users".* FROM "users" WHERE "users"."status" = 'inactive'
+```
+
Upgrading from Rails 3.2 to Rails 4.0
-------------------------------------

0 comments on commit 6370e69

Please sign in to comment.