EZ::Condition plugin for generating the :conditions where clause for ActiveRecord::Base.find. And an extension to ActiveRecord::Base called AR::Base.find_with_conditions that takes a block and builds the where clause dynamically for you.

Methods
Attributes
[R] clauses these are also reserved words regarding SQL column names use esc_* prefix to circumvent any issues
[RW] inner
[RW] outer
Public Class methods
new(*args, &block)

Initialize @clauses and eval the block so it invokes method_missing.

    # File lib/og/ez/condition.rb, line 25
25:       def initialize(*args, &block)
26:         options = args.last.is_a?(Hash) ? args.last : {}
27:         options[:table_name] = args.first if args.first.kind_of? Symbol        
28:         @table_name = options.delete(:table_name) || nil
29:         @outer = options.delete(:outer) || :and
30:         @inner = options.delete(:inner) || :and
31:         @clauses = []   
32:         instance_eval(&block) if block_given?
33:       end
Public Instance methods
<<(condition, outer = nil)

Append a condition element, which can be one of the following:

  • String: raw sql string
  • ActiveRecord instance, for attribute or PK cloning
  • Condition or Clause with to_sql method and outer property
  • Array in ActiveRecord format [‘column = ?’, 2]
This method is also aliased as sql_condition add_sql clone_from append
     # File lib/og/ez/condition.rb, line 113
113:       def <<(condition, outer = nil)
114:         if condition.kind_of?(String) and not condition.to_s.empty? 
115:           cond = SqlClause.new(condition)
116:           cond.outer = outer || :and      
117:           @clauses << cond
118:         elsif condition.kind_of?(Og::ModelMixin)
119:           if condition.attributes[condition.class.primary_key].nil?
120:             condition.attributes.each { |k, v| clause([condition.class.table_name, k]) == v unless v.to_s.empty? } 
121:           else
122:             clause([condition.class.table_name, condition.class.primary_key]) == condition.attributes[condition.class.primary_key]
123:           end                            
124:         else          
125:           if condition.kind_of?(Condition) or condition.kind_of?(AbstractClause)
126:             logic = condition.outer if outer.nil?
127:             condition = condition.to_sql 
128:           else
129:             logic = outer
130:           end
131:           if condition.kind_of?(Array) and not condition.empty?
132:             array_clause = ArrayClause.new(condition)
133:             array_clause.outer = logic
134:             @clauses << array_clause
135:           end
136:         end       
137:       end
add_sql(condition, outer = nil)

Alias for #<<

all(*args, &block)

Alias for #and_condition

and_condition(*args, &block)

Shortcut for adding a :and boolean joined subcondition

This method is also aliased as all
    # File lib/og/ez/condition.rb, line 85
85:       def and_condition(*args, &block)
86:         options = args.last.is_a?(Hash) ? args.last : {}
87:         options[:table_name] = args.first if args.first.kind_of? Symbol
88:         options[:outer] ||= @outer
89:         options[:inner] ||= :and
90:         define_sub(options, &block)
91:       end
any(*args, &block)

Alias for #or_condition

append(condition, outer = nil)

Alias for #<<

clause(name, *args)

You can define clauses dynamicly using this method. It will take a clause and create the correct Clause object to process the conditions

    # File lib/og/ez/condition.rb, line 56
56:       def clause(name, *args)
57:         if name.kind_of?(Array)
58:           c = Clause.new(name.first, name.last)
59:         elsif args.last.kind_of?(Symbol)
60:           c = Clause.new(args.pop, name)
61:         else 
62:           c = Clause.new(@table_name, name)
63:         end
64:         @clauses << c
65:         c
66:       end
clone_from(condition, outer = nil)

Alias for #<<

condition(*args, &block)

Alias for #define_sub

define_sub(*args, &block)

Create subcondition from a block, optionally specifying table_name, outer and inner. :outer determines how the subcondition is added to the condition, while :inner determines the internal ‘joining’ of conditions inside the subcondition. Both :inner & :outer defult to ‘AND‘

This method is also aliased as sub condition
    # File lib/og/ez/condition.rb, line 72
72:       def define_sub(*args, &block)
73:         options = args.last.is_a?(Hash) ? args.last : {}
74:         options[:table_name] = args.first if args.first.kind_of? Symbol
75:         options[:table_name] ||= @table_name
76:         cond = Condition.new(options, &block)
77:         self << cond
78:       end
method_missing(name, *args, &block)

When invoked with the name of the column in each statement inside the block: A new Clause instance is created and recieves the args. Then the operator hits method_missing and gets sent to a new Clause instance where it either matches one of the defined ops or hits method_missing there.

When invoked with an attached block a subcondition is created. The name is regarded as the table_name, additional parameters for outer and inner are passed on.

    # File lib/og/ez/condition.rb, line 43
43:       def method_missing(name, *args, &block)
44:         if block_given?         
45:           # handle name as table_name and create a subcondition
46:           options = args.last.is_a?(Hash) ? args.last : {}
47:           options[:table_name] ||= name
48:           define_sub(options, &block)
49:         else
50:           clause(name, *args)
51:         end
52:       end
or_condition(*args, &block)

Shortcut for adding a :or boolean joined subcondition

This method is also aliased as any
     # File lib/og/ez/condition.rb, line 97
 97:       def or_condition(*args, &block)
 98:         options = args.last.is_a?(Hash) ? args.last : {}
 99:         options[:table_name] = args.first if args.first.kind_of? Symbol
100:         options[:outer] ||= @outer
101:         options[:inner] ||= :or
102:         define_sub(options, &block)
103:       end
sql_condition(condition, outer = nil)

Alias for #<<

sub(*args, &block)

Alias for #define_sub

to_sql(logic=@inner)

Loop over all Clause onjects in @clauses array and call to_sql on each instance. Then join the queries and params into the :conditions array with logic defaulting to AND. Subqueries are joined together using their individual outer property setting if present. Also defaults to AND.

     # File lib/og/ez/condition.rb, line 154
154:       def to_sql(logic=@inner)
155:         params = []; query = []
156:         @clauses.each do |cv|
157:           q, p, e = cv.to_sql                 
158:           unless q.to_s.empty?
159:             logic = cv.outer ? cv.outer : logic
160:             logic = logic.to_s.upcase
161:             logic = 'AND NOT' if logic == 'NOT'
162:             query << logic unless query.empty?
163:             query << q
164:             if cv.test == :in 
165:               params << p if p.respond_to?(:map)
166:             elsif p.kind_of?(Array)
167:               p.flatten! unless q =~ /IN/
168:               params += p
169:             else
170:               params << p unless p.nil?
171:               params << e unless e.nil?
172:             end  
173:           end       
174:         end       
175:         [query.join(' '), *params ]
176:       end