aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord')
-rw-r--r--activerecord/CHANGELOG.md23
-rw-r--r--activerecord/lib/active_record/relation/query_methods.rb15
-rw-r--r--activerecord/test/cases/relation/where_chain_test.rb30
-rw-r--r--activerecord/test/cases/scoping/default_scoping_test.rb2
4 files changed, 61 insertions, 9 deletions
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md
index d12534aaf2..f5b380b669 100644
--- a/activerecord/CHANGELOG.md
+++ b/activerecord/CHANGELOG.md
@@ -1,12 +1,25 @@
-* Extend ActiveRecord::Base#cache_key to take an optional list of timestamp attributes of which the highest will be used.
+* `.unscope` now removes conditions specified in `default_scope`.
+
+ *Jon Leighton*
- Example:
-
- # last_reviewed_at will be used, if that's more recent than updated_at, or vice versa
- Person.find(5).cache_key(:updated_at, :last_reviewed_at)
+* Added ActiveRecord::QueryMethods#rewhere which will overwrite an existing, named where condition.
+
+ Examples:
+
+ Post.where(trashed: true).where(trashed: false) #=> WHERE `trashed` = 1 AND `trashed` = 0
+ Post.where(trashed: true).rewhere(trashed: false) #=> WHERE `trashed` = 0
+ Post.where(active: true).where(trashed: true).rewhere(trashed: false) #=> WHERE `active` = 1 AND `trashed` = 0
*DHH*
+* Extend ActiveRecord::Base#cache_key to take an optional list of timestamp attributes of which the highest will be used.
+
+ Example:
+
+ # last_reviewed_at will be used, if that's more recent than updated_at, or vice versa
+ Person.find(5).cache_key(:updated_at, :last_reviewed_at)
+
+ *DHH*
* Added ActiveRecord::Base#enum for declaring enum attributes where the values map to integers in the database, but can be queried by name.
diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb
index bffd8b5d0f..62c555f6d6 100644
--- a/activerecord/lib/active_record/relation/query_methods.rb
+++ b/activerecord/lib/active_record/relation/query_methods.rb
@@ -341,9 +341,6 @@ module ActiveRecord
# User.where(name: "John", active: true).unscope(where: :name)
# == User.where(active: true)
#
- # This method is applied before the default_scope is applied. So the conditions
- # specified in default_scope will not be removed.
- #
# Note that this method is more generalized than ActiveRecord::SpawnMethods#except
# because #except will only affect a particular relation's values. It won't wipe
# the order, grouping, etc. when that relation is merged. For example:
@@ -553,6 +550,18 @@ module ActiveRecord
end
end
+ # Allows you to change a previously set where condition for a given attribute, instead of appending to that condition.
+ #
+ # Post.where(trashed: true).where(trashed: false) #=> WHERE `trashed` = 1 AND `trashed` = 0
+ # Post.where(trashed: true).rewhere(trashed: false) #=> WHERE `trashed` = 0
+ # Post.where(active: true).where(trashed: true).rewhere(trashed: false) #=> WHERE `active` = 1 AND `trashed` = 0
+ #
+ # This is short-hand for unscope(where: conditions.keys).where(conditions). Note that unlike reorder, we're only unscoping
+ # the named conditions -- not the entire where statement.
+ def rewhere(conditions)
+ unscope(where: conditions.keys).where(conditions)
+ end
+
# Allows to specify a HAVING clause. Note that you can't use HAVING
# without also specifying a GROUP clause.
#
diff --git a/activerecord/test/cases/relation/where_chain_test.rb b/activerecord/test/cases/relation/where_chain_test.rb
index 92d1e013e8..d44b4dfe3d 100644
--- a/activerecord/test/cases/relation/where_chain_test.rb
+++ b/activerecord/test/cases/relation/where_chain_test.rb
@@ -76,5 +76,35 @@ module ActiveRecord
expected = Arel::Nodes::NotEqual.new(Post.arel_table[@name], 'ruby on rails')
assert_equal(expected, relation.where_values[1])
end
+
+ def test_rewhere_with_one_condition
+ relation = Post.where(title: 'hello').where(title: 'world').rewhere(title: 'alone')
+
+ expected = Arel::Nodes::Equality.new(Post.arel_table[@name], 'alone')
+ assert_equal 1, relation.where_values.size
+ assert_equal expected, relation.where_values.first
+ end
+
+ def test_rewhere_with_multiple_overwriting_conditions
+ relation = Post.where(title: 'hello').where(body: 'world').rewhere(title: 'alone', body: 'again')
+
+ title_expected = Arel::Nodes::Equality.new(Post.arel_table['title'], 'alone')
+ body_expected = Arel::Nodes::Equality.new(Post.arel_table['body'], 'again')
+
+ assert_equal 2, relation.where_values.size
+ assert_equal title_expected, relation.where_values.first
+ assert_equal body_expected, relation.where_values.second
+ end
+
+ def test_rewhere_with_one_overwriting_condition_and_one_unrelated
+ relation = Post.where(title: 'hello').where(body: 'world').rewhere(title: 'alone')
+
+ title_expected = Arel::Nodes::Equality.new(Post.arel_table['title'], 'alone')
+ body_expected = Arel::Nodes::Equality.new(Post.arel_table['body'], 'world')
+
+ assert_equal 2, relation.where_values.size
+ assert_equal body_expected, relation.where_values.first
+ assert_equal title_expected, relation.where_values.second
+ end
end
end
diff --git a/activerecord/test/cases/scoping/default_scoping_test.rb b/activerecord/test/cases/scoping/default_scoping_test.rb
index 76f395ba83..4fd9d6f52a 100644
--- a/activerecord/test/cases/scoping/default_scoping_test.rb
+++ b/activerecord/test/cases/scoping/default_scoping_test.rb
@@ -103,7 +103,7 @@ class DefaultScopingTest < ActiveRecord::TestCase
def test_unscope_overrides_default_scope
expected = Developer.all.collect { |dev| [dev.name, dev.id] }
- received = Developer.order('name ASC, id DESC').unscope(:order).collect { |dev| [dev.name, dev.id] }
+ received = DeveloperCalledJamis.unscope(:where).collect { |dev| [dev.name, dev.id] }
assert_equal expected, received
end