diff options
author | Ernie Miller <ernie@metautonomo.us> | 2010-03-25 20:18:36 -0400 |
---|---|---|
committer | Ernie Miller <ernie@metautonomo.us> | 2010-05-07 13:05:14 -0400 |
commit | 32fbb70f100d0d6f9800020ef519a09a0852ae47 (patch) | |
tree | 584136c3fec48b0db0e409bb3d6ff1b203b12ced | |
parent | def75c7b54ccc18f3a8daf79b6144ddcb538d4e8 (diff) | |
download | rails-32fbb70f100d0d6f9800020ef519a09a0852ae47.tar.gz rails-32fbb70f100d0d6f9800020ef519a09a0852ae47.tar.bz2 rails-32fbb70f100d0d6f9800020ef519a09a0852ae47.zip |
Add grouped predicates (_any/_all) and refactored predication method definitions
-rw-r--r-- | lib/arel/algebra/attributes/attribute.rb | 72 | ||||
-rw-r--r-- | lib/arel/algebra/predicates.rb | 26 | ||||
-rw-r--r-- | lib/arel/engines/sql/predicates.rb | 18 |
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 |