aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorErnie Miller <ernie@metautonomo.us>2010-03-25 20:18:36 -0400
committerErnie Miller <ernie@metautonomo.us>2010-05-07 13:05:14 -0400
commit32fbb70f100d0d6f9800020ef519a09a0852ae47 (patch)
tree584136c3fec48b0db0e409bb3d6ff1b203b12ced /lib
parentdef75c7b54ccc18f3a8daf79b6144ddcb538d4e8 (diff)
downloadrails-32fbb70f100d0d6f9800020ef519a09a0852ae47.tar.gz
rails-32fbb70f100d0d6f9800020ef519a09a0852ae47.tar.bz2
rails-32fbb70f100d0d6f9800020ef519a09a0852ae47.zip
Add grouped predicates (_any/_all) and refactored predication method definitions
Diffstat (limited to 'lib')
-rw-r--r--lib/arel/algebra/attributes/attribute.rb72
-rw-r--r--lib/arel/algebra/predicates.rb26
-rw-r--r--lib/arel/engines/sql/predicates.rb18
3 files changed, 78 insertions, 38 deletions
diff --git a/lib/arel/algebra/attributes/attribute.rb b/lib/arel/algebra/attributes/attribute.rb
index d9ea588128..5689d69b02 100644
--- a/lib/arel/algebra/attributes/attribute.rb
+++ b/lib/arel/algebra/attributes/attribute.rb
@@ -82,48 +82,44 @@ module Arel
include Congruence
module Predications
- def eq(other)
- Predicates::Equality.new(self, other)
- end
-
- def not(other)
- Predicates::Not.new(self, other)
- end
-
- def lt(other)
- Predicates::LessThan.new(self, other)
- end
-
- def lteq(other)
- Predicates::LessThanOrEqualTo.new(self, other)
- end
-
- def gt(other)
- Predicates::GreaterThan.new(self, other)
- end
-
- def gteq(other)
- Predicates::GreaterThanOrEqualTo.new(self, other)
- end
-
- def matches(regexp)
- Predicates::Match.new(self, regexp)
- end
-
- def notmatches(regexp)
- Predicates::NotMatch.new(self, regexp)
- end
+ methods = {
+ :eq => "Equality",
+ :not => "Not",
+ :lt => "LessThan",
+ :lteq => "LessThanOrEqualTo",
+ :gt => "GreaterThan",
+ :gteq => "GreaterThanOrEqualTo",
+ :matches => "Match",
+ :notmatches => "NotMatch",
+ :in => "In",
+ :notin => "NotIn"
+ }
- def in(array)
- if array.is_a?(Range) && array.exclude_end?
- [Predicates::GreaterThanOrEqualTo.new(self, array.begin), Predicates::LessThan.new(self, array.end)]
- else
- Predicates::In.new(self, array)
+ def self.predication(name, klass)
+ methods = {
+ :operator => "
+ def #{name}(other)
+ Predicates::#{klass}.new(self, other)
+ end
+ ",
+ :any => "
+ def #{name}_any(*others)
+ Predicates::Any.new(Predicates::#{klass}, self, *others)
+ end
+ ",
+ :all => "
+ def #{name}_all(*others)
+ Predicates::All.new(Predicates::#{klass}, self, *others)
+ end
+ "
+ }
+ [:operator, :any, :all].each do |method_name|
+ module_eval methods[method_name], __FILE__, __LINE__
end
end
- def notin(array)
- Predicates::NotIn.new(self, array)
+ methods.each_pair do |method_name, class_name|
+ predication(method_name, class_name)
end
end
include Predications
diff --git a/lib/arel/algebra/predicates.rb b/lib/arel/algebra/predicates.rb
index 05a1de983d..ea1f771abb 100644
--- a/lib/arel/algebra/predicates.rb
+++ b/lib/arel/algebra/predicates.rb
@@ -9,6 +9,32 @@ module Arel
And.new(self, other_predicate)
end
end
+
+ class Grouped < Predicate
+ attributes :operator, :operand1, :operands2
+
+ def initialize(operator, operand1, *operands2)
+ @operator = operator
+ @operand1 = operand1
+ @operands2 = operands2.uniq
+ end
+
+ def ==(other)
+ self.class === other and
+ @operand1 == other.operand1 and
+ same_elements?(@operands2, other.operands2)
+ end
+
+ private
+
+ def same_elements?(a1, a2)
+ [:select, :inject, :size].each do |m|
+ return false unless [a1, a2].each {|a| a.respond_to?(m) }
+ end
+ a1.inject({}) { |h,e| h[e] = a1.select { |i| i == e }.size; h } ==
+ a2.inject({}) { |h,e| h[e] = a2.select { |i| i == e }.size; h }
+ end
+ end
class Binary < Predicate
attributes :operand1, :operand2
diff --git a/lib/arel/engines/sql/predicates.rb b/lib/arel/engines/sql/predicates.rb
index e9a068fb13..53bac7a2ca 100644
--- a/lib/arel/engines/sql/predicates.rb
+++ b/lib/arel/engines/sql/predicates.rb
@@ -19,6 +19,24 @@ module Arel
class And < CompoundPredicate
def predicate_sql; "AND" end
end
+
+ class GroupedPredicate < Grouped
+ def to_sql(formatter = nil)
+ "(" +
+ operands2.inject([]) { |predicates, operand|
+ predicates << operator.new(operand1, operand).to_sql
+ }.join(" #{predicate_sql} ") +
+ ")"
+ end
+ end
+
+ class Any < GroupedPredicate
+ def predicate_sql; "OR" end
+ end
+
+ class All < GroupedPredicate
+ def predicate_sql; "AND" end
+ end
class Equality < Binary
def predicate_sql