Skip to content

Commit

Permalink
Make Arel nodes more invertable
Browse files Browse the repository at this point in the history
It makes node detection for `unscope` and `merge` more easier.
  • Loading branch information
kamipo committed Jun 14, 2020
1 parent b6a9d3a commit 3ebcbe4
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 6 deletions.
54 changes: 48 additions & 6 deletions activerecord/lib/arel/nodes/binary.rb
Expand Up @@ -40,12 +40,54 @@ def fetch_attribute
end

class Between < Binary; include FetchAttribute; end
class NotIn < Binary; include FetchAttribute; end
class GreaterThan < Binary; include FetchAttribute; end
class GreaterThanOrEqual < Binary; include FetchAttribute; end
class NotEqual < Binary; include FetchAttribute; end
class LessThan < Binary; include FetchAttribute; end
class LessThanOrEqual < Binary; include FetchAttribute; end

class GreaterThan < Binary
include FetchAttribute

def invert
Arel::Nodes::LessThanOrEqual.new(left, right)
end
end

class GreaterThanOrEqual < Binary
include FetchAttribute

def invert
Arel::Nodes::LessThan.new(left, right)
end
end

class LessThan < Binary
include FetchAttribute

def invert
Arel::Nodes::GreaterThanOrEqual.new(left, right)
end
end

class LessThanOrEqual < Binary
include FetchAttribute

def invert
Arel::Nodes::GreaterThan.new(left, right)
end
end

class NotEqual < Binary
include FetchAttribute

def invert
Arel::Nodes::Equality.new(left, right)
end
end

class NotIn < Binary
include FetchAttribute

def invert
Arel::Nodes::In.new(left, right)
end
end

class Or < Binary
def fetch_attribute(&block)
Expand Down
18 changes: 18 additions & 0 deletions activerecord/test/cases/relation/merging_test.rb
Expand Up @@ -175,6 +175,24 @@ def test_merge_not_in_clause
assert_equal [david], Author.where(id: mary).merge(non_mary_and_bob, rewhere: true)
end

def test_merge_not_range_clause
david, mary, bob = authors(:david, :mary, :bob)

less_than_bob = Author.where.not(id: bob.id..Float::INFINITY).order(:id)

assert_equal [david, mary], less_than_bob

assert_deprecated do
assert_equal [david], Author.where(id: david).merge(less_than_bob)
end
assert_equal [david, mary], Author.where(id: david).merge(less_than_bob, rewhere: true)

assert_deprecated do
assert_equal [mary], Author.where(id: mary).merge(less_than_bob)
end
assert_equal [david, mary], Author.where(id: mary).merge(less_than_bob, rewhere: true)
end

def test_merge_doesnt_duplicate_same_clauses
david, mary, bob = authors(:david, :mary, :bob)

Expand Down
12 changes: 12 additions & 0 deletions activerecord/test/cases/relation/where_clause_test.rb
Expand Up @@ -90,14 +90,26 @@ class WhereClauseTest < ActiveRecord::TestCase
test "invert replaces each part of the predicate with its inverse" do
original = WhereClause.new([
table["id"].in([1, 2, 3]),
table["id"].not_in([1, 2, 3]),
table["id"].eq(1),
table["id"].not_eq(2),
table["id"].gt(1),
table["id"].gteq(2),
table["id"].lt(1),
table["id"].lteq(2),
table["id"].is_not_distinct_from(1),
table["id"].is_distinct_from(2),
"sql literal"
])
expected = WhereClause.new([
table["id"].not_in([1, 2, 3]),
table["id"].in([1, 2, 3]),
table["id"].not_eq(1),
table["id"].eq(2),
table["id"].lteq(1),
table["id"].lt(2),
table["id"].gteq(1),
table["id"].gt(2),
table["id"].is_distinct_from(1),
table["id"].is_not_distinct_from(2),
Arel::Nodes::Not.new(Arel::Nodes::SqlLiteral.new("sql literal"))
Expand Down

0 comments on commit 3ebcbe4

Please sign in to comment.