Skip to content

Commit f950b26

Browse files
author
David Heinemeier Hansson
committed
Added ActiveRecord::QueryMethods#rewhere which will overwrite an existing, named where condition.
1 parent 4d7080f commit f950b26

File tree

3 files changed

+52
-0
lines changed

3 files changed

+52
-0
lines changed

activerecord/CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,16 @@
22

33
*Jon Leighton*
44

5+
* Added ActiveRecord::QueryMethods#rewhere which will overwrite an existing, named where condition.
6+
7+
Examples:
8+
9+
Post.where(trashed: true).where(trashed: false) #=> WHERE `trashed` = 1 AND `trashed` = 0
10+
Post.where(trashed: true).rewhere(trashed: false) #=> WHERE `trashed` = 0
11+
Post.where(active: true).where(trashed: true).rewhere(trashed: false) #=> WHERE `active` = 1 AND `trashed` = 0
12+
13+
*DHH*
14+
515
* Extend ActiveRecord::Base#cache_key to take an optional list of timestamp attributes of which the highest will be used.
616

717
Example:

activerecord/lib/active_record/relation/query_methods.rb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,18 @@ def where!(opts = :chain, *rest) # :nodoc:
550550
end
551551
end
552552

553+
# Allows you to change a previously set where condition for a given attribute, instead of appending to that condition.
554+
#
555+
# Post.where(trashed: true).where(trashed: false) #=> WHERE `trashed` = 1 AND `trashed` = 0
556+
# Post.where(trashed: true).rewhere(trashed: false) #=> WHERE `trashed` = 0
557+
# Post.where(active: true).where(trashed: true).rewhere(trashed: false) #=> WHERE `active` = 1 AND `trashed` = 0
558+
#
559+
# This is short-hand for unscope(where: conditions.keys).where(conditions). Note that unlike reorder, we're only unscoping
560+
# the named conditions -- not the entire where statement.
561+
def rewhere(conditions)
562+
unscope(where: conditions.keys).where(conditions)
563+
end
564+
553565
# Allows to specify a HAVING clause. Note that you can't use HAVING
554566
# without also specifying a GROUP clause.
555567
#

activerecord/test/cases/relation/where_chain_test.rb

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,5 +76,35 @@ def test_chaining_multiple
7676
expected = Arel::Nodes::NotEqual.new(Post.arel_table[@name], 'ruby on rails')
7777
assert_equal(expected, relation.where_values[1])
7878
end
79+
80+
def test_rewhere_with_one_condition
81+
relation = Post.where(title: 'hello').where(title: 'world').rewhere(title: 'alone')
82+
83+
expected = Arel::Nodes::Equality.new(Post.arel_table[@name], 'alone')
84+
assert_equal 1, relation.where_values.size
85+
assert_equal expected, relation.where_values.first
86+
end
87+
88+
def test_rewhere_with_multiple_overwriting_conditions
89+
relation = Post.where(title: 'hello').where(body: 'world').rewhere(title: 'alone', body: 'again')
90+
91+
title_expected = Arel::Nodes::Equality.new(Post.arel_table['title'], 'alone')
92+
body_expected = Arel::Nodes::Equality.new(Post.arel_table['body'], 'again')
93+
94+
assert_equal 2, relation.where_values.size
95+
assert_equal title_expected, relation.where_values.first
96+
assert_equal body_expected, relation.where_values.second
97+
end
98+
99+
def test_rewhere_with_one_overwriting_condition_and_one_unrelated
100+
relation = Post.where(title: 'hello').where(body: 'world').rewhere(title: 'alone')
101+
102+
title_expected = Arel::Nodes::Equality.new(Post.arel_table['title'], 'alone')
103+
body_expected = Arel::Nodes::Equality.new(Post.arel_table['body'], 'world')
104+
105+
assert_equal 2, relation.where_values.size
106+
assert_equal body_expected, relation.where_values.first
107+
assert_equal title_expected, relation.where_values.second
108+
end
79109
end
80110
end

0 commit comments

Comments
 (0)