Created
November 3, 2010 12:20
-
-
Save ernie/661022 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From 124de9bdb3109236af68d06052ce21a4522059e6 Mon Sep 17 00:00:00 2001 | |
From: Ernie Miller <[email protected]> | |
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 <[email protected]> | |
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