提交 0ea798a4 编写于 作者: R Ryuta Kamizono

Allow difference for `and`/`or` unless other values are set explicitly

I often hit the inconvenience (recently in #39558).

`and`/`or` are focused to combine where-like clauses, so we often use
one-time relation which has only where clause. But if the receiver has
values other than where clause (e.g. `order`, `select`, `includes`,
etc), `and`/`or` will raise structurally incompatible error.

Since it is harder to predict the receiver has which values other than
where clause before doing `and`/`or`, that restriction is a little
annoying to me.

So I'd like to relax that restriction, at least unless other values are
set explicitly for multiple values.
上级 28e089db
......@@ -1513,8 +1513,11 @@ def structurally_incompatible_values_for_or(other)
values = other.values
STRUCTURAL_OR_METHODS.reject do |method|
v1, v2 = @values[method], values[method]
v1 = v1.uniq if v1.is_a?(Array)
v2 = v2.uniq if v2.is_a?(Array)
if v1.is_a?(Array)
next true unless v2.is_a?(Array)
v1 = v1.uniq
v2 = v2.uniq
end
v1 == v2 || (!v1 || v1.empty?) && (!v2 || v2.empty?)
end
end
......
......@@ -43,7 +43,7 @@ def test_merge_in_clause
assert_equal [mary], david_and_mary.and(mary_and_bob)
assert_equal authors, david_and_mary.or(mary_and_bob)
david_and_bob = Author.where(id: david).or(Author.where(name: "Bob")).order(:id)
david_and_bob = Author.where(id: david).or(Author.where(name: "Bob"))
assert_equal [david], david_and_mary.merge(david_and_bob)
assert_equal [david], david_and_mary.merge(david_and_bob, rewhere: true)
......@@ -96,7 +96,7 @@ def test_merge_between_clause
assert_equal [mary], david_and_mary.and(mary_and_bob)
assert_equal authors, david_and_mary.or(mary_and_bob)
david_and_bob = Author.where(id: david).or(Author.where(name: "Bob")).order(:id)
david_and_bob = Author.where(id: david).or(Author.where(name: "Bob"))
assert_equal [david], david_and_mary.merge(david_and_bob)
assert_equal [david], david_and_mary.merge(david_and_bob, rewhere: true)
......@@ -149,7 +149,7 @@ def test_merge_or_clause
assert_equal [mary], david_and_mary.and(mary_and_bob)
assert_equal authors, david_and_mary.or(mary_and_bob)
david_and_bob = Author.where(id: david).or(Author.where(name: "Bob")).order(:id)
david_and_bob = Author.where(id: david).or(Author.where(name: "Bob"))
assert_equal [david], david_and_mary.merge(david_and_bob)
assert_equal [david], david_and_mary.merge(david_and_bob, rewhere: true)
......
......@@ -84,11 +84,12 @@ def test_or_with_unscope_where_column
def test_or_with_unscope_order
expected = Post.where("id = 1 or id = 2")
assert_equal expected, Post.order("body asc").where("id = 1").unscope(:order).or(Post.where("id = 2")).to_a
assert_equal expected, Post.order(:id).where("id = 1").or(Post.order(:id).where("id = 2").unscope(:order)).to_a
end
def test_or_with_incompatible_unscope
error = assert_raises ArgumentError do
Post.order("body asc").where("id = 1").or(Post.order("body asc").where("id = 2").unscope(:order)).to_a
Post.order("body asc").where("id = 1").unscope(:order).or(Post.order("body asc").where("id = 2")).to_a
end
assert_equal "Relation passed to #or must be structurally compatible. Incompatible values: [:order]", error.message
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册