Skip to content

Instantly share code, notes, and snippets.

@ernie
Created November 3, 2010 12:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ernie/661022 to your computer and use it in GitHub Desktop.
Save ernie/661022 to your computer and use it in GitHub Desktop.
From 124de9bdb3109236af68d06052ce21a4522059e6 Mon Sep 17 00:00:00 2001
From: Ernie Miller <ernie@metautonomo.us>
Date: Wed, 27 Oct 2010 09:43:20 -0400
Subject: [PATCH 1/2] Refactor predication methods to be available to SqlLiterals as well.
---
lib/arel.rb | 1 +
lib/arel/attributes/attribute.rb | 175 +-------------------------------------
lib/arel/nodes/sql_literal.rb | 1 +
lib/arel/predications.rb | 177 ++++++++++++++++++++++++++++++++++++++
test/nodes/test_sql_literal.rb | 24 +++++
5 files changed, 204 insertions(+), 174 deletions(-)
create mode 100644 lib/arel/predications.rb
diff --git a/lib/arel.rb b/lib/arel.rb
index 1a1f4c1..bcf71c0 100644
--- a/lib/arel.rb
+++ b/lib/arel.rb
@@ -1,6 +1,7 @@
require 'arel/crud'
require 'arel/expressions'
+require 'arel/predications'
require 'arel/table'
require 'arel/attributes'
require 'arel/compatibility/wheres'
diff --git a/lib/arel/attributes/attribute.rb b/lib/arel/attributes/attribute.rb
index ba18533..e027a65 100644
--- a/lib/arel/attributes/attribute.rb
+++ b/lib/arel/attributes/attribute.rb
@@ -2,180 +2,7 @@ module Arel
module Attributes
class Attribute < Struct.new :relation, :name, :column
include Arel::Expressions
-
- def not_eq other
- Nodes::NotEqual.new self, other
- end
-
- def not_eq_any others
- grouping_any :not_eq, others
- end
-
- def not_eq_all others
- grouping_all :not_eq, others
- end
-
- def eq other
- Nodes::Equality.new self, other
- end
-
- def eq_any others
- grouping_any :eq, others
- end
-
- def eq_all others
- grouping_all :eq, others
- end
-
- def in other
- case other
- when Arel::SelectManager
- Nodes::In.new self, other.to_a.map { |x| x.id }
- when Range
- if other.exclude_end?
- left = Nodes::GreaterThanOrEqual.new(self, other.min)
- right = Nodes::LessThan.new(self, other.max + 1)
- Nodes::And.new left, right
- else
- Nodes::Between.new(self, Nodes::And.new(other.min, other.max))
- end
- else
- Nodes::In.new self, other
- end
- end
-
- def in_any others
- grouping_any :in, others
- end
-
- def in_all others
- grouping_all :in, others
- end
-
- def not_in other
- case other
- when Arel::SelectManager
- Nodes::NotIn.new self, other.to_a.map { |x| x.id }
- when Range
- if other.exclude_end?
- left = Nodes::LessThan.new(self, other.min)
- right = Nodes::GreaterThanOrEqual.new(self, other.max)
- Nodes::Or.new left, right
- else
- left = Nodes::LessThan.new(self, other.min)
- right = Nodes::GreaterThan.new(self, other.max)
- Nodes::Or.new left, right
- end
- else
- Nodes::NotIn.new self, other
- end
- end
-
- def not_in_any others
- grouping_any :not_in, others
- end
-
- def not_in_all others
- grouping_all :not_in, others
- end
-
- def matches other
- Nodes::Matches.new self, other
- end
-
- def matches_any others
- grouping_any :matches, others
- end
-
- def matches_all others
- grouping_all :matches, others
- end
-
- def does_not_match other
- Nodes::DoesNotMatch.new self, other
- end
-
- def does_not_match_any others
- grouping_any :does_not_match, others
- end
-
- def does_not_match_all others
- grouping_all :does_not_match, others
- end
-
- def gteq right
- Nodes::GreaterThanOrEqual.new self, right
- end
-
- def gteq_any others
- grouping_any :gteq, others
- end
-
- def gteq_all others
- grouping_all :gteq, others
- end
-
- def gt right
- Nodes::GreaterThan.new self, right
- end
-
- def gt_any others
- grouping_any :gt, others
- end
-
- def gt_all others
- grouping_all :gt, others
- end
-
- def lt right
- Nodes::LessThan.new self, right
- end
-
- def lt_any others
- grouping_any :lt, others
- end
-
- def lt_all others
- grouping_all :lt, others
- end
-
- def lteq right
- Nodes::LessThanOrEqual.new self, right
- end
-
- def lteq_any others
- grouping_any :lteq, others
- end
-
- def lteq_all others
- grouping_all :lteq, others
- end
-
- def asc
- Nodes::Ordering.new self, :asc
- end
-
- def desc
- Nodes::Ordering.new self, :desc
- end
-
- private
-
- def grouping_any method_id, others
- first = send method_id, others.shift
-
- Nodes::Grouping.new others.inject(first) { |memo,expr|
- Nodes::Or.new(memo, send(method_id, expr))
- }
- end
-
- def grouping_all method_id, others
- first = send method_id, others.shift
-
- Nodes::Grouping.new others.inject(first) { |memo,expr|
- Nodes::And.new(memo, send(method_id, expr))
- }
- end
+ include Arel::Predications
end
class String < Attribute; end
diff --git a/lib/arel/nodes/sql_literal.rb b/lib/arel/nodes/sql_literal.rb
index e591862..c76a16d 100644
--- a/lib/arel/nodes/sql_literal.rb
+++ b/lib/arel/nodes/sql_literal.rb
@@ -2,6 +2,7 @@ module Arel
module Nodes
class SqlLiteral < String
include Arel::Expressions
+ include Arel::Predications
end
end
end
diff --git a/lib/arel/predications.rb b/lib/arel/predications.rb
new file mode 100644
index 0000000..8a8960f
--- /dev/null
+++ b/lib/arel/predications.rb
@@ -0,0 +1,177 @@
+module Arel
+ module Predications
+ def not_eq other
+ Nodes::NotEqual.new self, other
+ end
+
+ def not_eq_any others
+ grouping_any :not_eq, others
+ end
+
+ def not_eq_all others
+ grouping_all :not_eq, others
+ end
+
+ def eq other
+ Nodes::Equality.new self, other
+ end
+
+ def eq_any others
+ grouping_any :eq, others
+ end
+
+ def eq_all others
+ grouping_all :eq, others
+ end
+
+ def in other
+ case other
+ when Arel::SelectManager
+ Nodes::In.new self, other.to_a.map { |x| x.id }
+ when Range
+ if other.exclude_end?
+ left = Nodes::GreaterThanOrEqual.new(self, other.min)
+ right = Nodes::LessThan.new(self, other.max + 1)
+ Nodes::And.new left, right
+ else
+ Nodes::Between.new(self, Nodes::And.new(other.min, other.max))
+ end
+ else
+ Nodes::In.new self, other
+ end
+ end
+
+ def in_any others
+ grouping_any :in, others
+ end
+
+ def in_all others
+ grouping_all :in, others
+ end
+
+ def not_in other
+ case other
+ when Arel::SelectManager
+ Nodes::NotIn.new self, other.to_a.map { |x| x.id }
+ when Range
+ if other.exclude_end?
+ left = Nodes::LessThan.new(self, other.min)
+ right = Nodes::GreaterThanOrEqual.new(self, other.max)
+ Nodes::Or.new left, right
+ else
+ left = Nodes::LessThan.new(self, other.min)
+ right = Nodes::GreaterThan.new(self, other.max)
+ Nodes::Or.new left, right
+ end
+ else
+ Nodes::NotIn.new self, other
+ end
+ end
+
+ def not_in_any others
+ grouping_any :not_in, others
+ end
+
+ def not_in_all others
+ grouping_all :not_in, others
+ end
+
+ def matches other
+ Nodes::Matches.new self, other
+ end
+
+ def matches_any others
+ grouping_any :matches, others
+ end
+
+ def matches_all others
+ grouping_all :matches, others
+ end
+
+ def does_not_match other
+ Nodes::DoesNotMatch.new self, other
+ end
+
+ def does_not_match_any others
+ grouping_any :does_not_match, others
+ end
+
+ def does_not_match_all others
+ grouping_all :does_not_match, others
+ end
+
+ def gteq right
+ Nodes::GreaterThanOrEqual.new self, right
+ end
+
+ def gteq_any others
+ grouping_any :gteq, others
+ end
+
+ def gteq_all others
+ grouping_all :gteq, others
+ end
+
+ def gt right
+ Nodes::GreaterThan.new self, right
+ end
+
+ def gt_any others
+ grouping_any :gt, others
+ end
+
+ def gt_all others
+ grouping_all :gt, others
+ end
+
+ def lt right
+ Nodes::LessThan.new self, right
+ end
+
+ def lt_any others
+ grouping_any :lt, others
+ end
+
+ def lt_all others
+ grouping_all :lt, others
+ end
+
+ def lteq right
+ Nodes::LessThanOrEqual.new self, right
+ end
+
+ def lteq_any others
+ grouping_any :lteq, others
+ end
+
+ def lteq_all others
+ grouping_all :lteq, others
+ end
+
+ def asc
+ Nodes::Ordering.new self, :asc
+ end
+
+ def desc
+ Nodes::Ordering.new self, :desc
+ end
+
+ private
+
+ def grouping_any method_id, others
+ first = send method_id, others.shift
+
+ Nodes::Grouping.new others.inject(first) { |memo,expr|
+ Nodes::Or.new(memo, send(method_id, expr))
+ }
+ end
+
+ def grouping_all method_id, others
+ first = send method_id, others.shift
+
+ Nodes::Grouping.new others.inject(first) { |memo,expr|
+ Nodes::And.new(memo, send(method_id, expr))
+ }
+ end
+ end
+end
\ No newline at end of file
diff --git a/test/nodes/test_sql_literal.rb b/test/nodes/test_sql_literal.rb
index 5cf91ce..d280d6d 100644
--- a/test/nodes/test_sql_literal.rb
+++ b/test/nodes/test_sql_literal.rb
@@ -23,6 +23,30 @@ module Arel
viz.accept(node).must_be_like %{ COUNT(DISTINCT *) }
end
end
+
+ describe 'equality' do
+ it 'makes an equality node' do
+ node = SqlLiteral.new('foo').eq(1)
+ viz = Visitors::ToSql.new Table.engine
+ viz.accept(node).must_be_like %{ foo = 1 }
+ end
+ end
+
+ describe 'grouped "or" equality' do
+ it 'makes a grouping node with an or node' do
+ node = SqlLiteral.new('foo').eq_any([1,2])
+ viz = Visitors::ToSql.new Table.engine
+ viz.accept(node).must_be_like %{ (foo = 1 OR foo = 2) }
+ end
+ end
+
+ describe 'grouped "and" equality' do
+ it 'makes a grouping node with an or node' do
+ node = SqlLiteral.new('foo').eq_all([1,2])
+ viz = Visitors::ToSql.new Table.engine
+ viz.accept(node).must_be_like %{ (foo = 1 AND foo = 2) }
+ end
+ end
end
end
end
--
1.7.2.2
From a76e68da2644a6ec06dccf9e6367d46248111811 Mon Sep 17 00:00:00 2001
From: Ernie Miller <ernie@metautonomo.us>
Date: Wed, 3 Nov 2010 08:14:20 -0400
Subject: [PATCH 2/2] Add ToSql visitor for NilClass
---
lib/arel/visitors/to_sql.rb | 1 +
test/visitors/test_to_sql.rb | 4 ++++
2 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/lib/arel/visitors/to_sql.rb b/lib/arel/visitors/to_sql.rb
index f52ce10..1412797 100644
--- a/lib/arel/visitors/to_sql.rb
+++ b/lib/arel/visitors/to_sql.rb
@@ -277,6 +277,7 @@ module Arel
alias :visit_Symbol :visit_String
alias :visit_Time :visit_String
alias :visit_TrueClass :visit_String
+ alias :visit_NilClass :visit_String
def quote value, column = nil
@connection.quote value, column
diff --git a/test/visitors/test_to_sql.rb b/test/visitors/test_to_sql.rb
index d7cf719..a6042ef 100644
--- a/test/visitors/test_to_sql.rb
+++ b/test/visitors/test_to_sql.rb
@@ -45,6 +45,10 @@ module Arel
@visitor.accept Date.today
end
+ it "should visit_NilClass" do
+ @visitor.accept(nil).must_be_like "NULL"
+ end
+
it "should visit_Arel_Nodes_And" do
node = Nodes::And.new @attr.eq(10), @attr.eq(11)
@visitor.accept(node).must_be_like %{
--
1.7.2.2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment