require 'criterion' module Criteria # Negation criterion class Not < Criterion def condition "( NOT #{super} )" unless @restrictions.empty? end end # Join criterion class Join < Criterion attr_reader :prefix def initialize(attribute) super() @attribute = attribute end def parent=(parent) super(parent) @model_class = Object.const_get(parent.model_class.reflect_on_association(@attribute.intern).class_name) @prefix = query.join_alias(@attribute, @model_class, @parent.model_class) end def joins { @attribute.intern => super } end def prefix @prefix end end # Disjunction (OR) criterion class Disjunction < Criterion def condition '(' << @restrictions.collect { |r| r.condition }.compact.join(" OR ") << ')' unless @restrictions.empty? end end # Conjunction (AND) criterion class Disjunction < Criterion def condition '(' << @restrictions.collect { |r| r.condition }.compact.join(" OR ") << ')' unless @restrictions.empty? end end # Base class for criteria requiring an attribute name class AttributeRestriction < Criterion def initialize(attribute_name) super() @attribute_name = attribute_name end def attribute_name pf = prefix return "#{pf}.#{@attribute_name}" if pf @attribute_name unless pf end end # Base class for criteria requiring an attribute name and a value class NameValueRestriction < AttributeRestriction def initialize(attribute_name, value) super(attribute_name) @value = value end end # Base class for criteria requiring an attribute name, a value and an operator class OperatorRestriction < NameValueRestriction def condition " (#{attribute_name}#{operator}?) " if @value end def params [@value] end end # Null restriction class IsNull < AttributeRestriction def condition " (#{attribute_name} IS NULL) " end end # Not Null restriction class IsNotNull < AttributeRestriction def condition " (#{attribute_name} IS NOT NULL) " end end #In restriction class In < NameValueRestriction def condition " (#{attribute_name} IN (?) ) " if @value end def params [@value] end end # meta method which generates an OperatorRestriction with class name _name_ and the given _operator_ def Criteria.operator_restriction(name, operator) module_eval <<-END class #{name} < OperatorRestriction def operator ' #{operator} ' end end END module_eval <<-END class CriterionContainer def #{name.underscore}(attribute_name, value) res = #{name}.new(attribute_name, value) self << res self end end END end operator_restriction 'Eq', '=' operator_restriction 'Ne', '<>' operator_restriction 'Like', 'LIKE' operator_restriction 'Gt', '>' operator_restriction 'Gte', '>=' operator_restriction 'Lt', '<' operator_restriction 'Lte', '<=' end