Class: Criteria

Inherits:
Object
  • Object
show all
Defined in:
lib/criteria.rb

Overview

Criteria is a collection of Criterion as well as additional constraints regarding the order, limit and offset

see the readme for usage examples.

Defined Under Namespace

Modules: VERSION Classes: Association, ClassHeirarchyContext, Column, Criterion, ManyToOneAssociation, NotCriterion, OneToManyAssociation, Order

Constant Summary collapse

@@debug =
false

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(clazz = nil, def_operator = :AND) ⇒ Criteria

Create a new criteria, optionally pass in a Criterion object You can also pass a block, and self will be yielded



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/criteria.rb', line 30

def initialize(clazz=nil, def_operator=:AND) # :yields: self
  @associations = []
  @criteria = []
  @operator = def_operator
  # @and = []
  # @or = []
  @order_by = []
  @group_by = []
  @select = []
  @limit = nil
  @offset = nil    
  @joins = []
  # @default_operator = :or
@clazz = clazz if clazz.is_a? Class

# Add the supplied criterion if it is defined
  # add(clazz) if clazz.is_a? Criterion
  # add(c) if c.is_a? Criterion 

  yield(self) if block_given?
end

Instance Attribute Details

#limitObject

, :default_operator #, :operator



18
19
20
# File 'lib/criteria.rb', line 18

def limit
  @limit
end

#offsetObject

, :default_operator #, :operator



18
19
20
# File 'lib/criteria.rb', line 18

def offset
  @offset
end

Class Method Details

.debugObject



20
21
22
# File 'lib/criteria.rb', line 20

def self.debug
  @@debug
end

.debug=(val) ⇒ Object



24
25
26
# File 'lib/criteria.rb', line 24

def self.debug=(val)
  @@debug=val
end

Instance Method Details

#&(criterion) ⇒ Object

AND this with another criterion



152
153
154
# File 'lib/criteria.rb', line 152

def &(criterion)
  self.and(criterion)
end

#<<(c) ⇒ Object



107
108
109
110
# File 'lib/criteria.rb', line 107

def <<(c)
  raise "<< does not accept a block, perhaps you were trying to pass it to Criteria.new?" if block_given?
  add(c)
end

#add(c = nil, operator = @operator, opts = {}, &block) ⇒ Object



112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/criteria.rb', line 112

def add(c=nil, operator=@operator, opts={}, &block)
  
  # If we are using an :or and this is an :and, or vice versa, then create a new sub-criteria to contain it
  if operator!=@operator
    newcriteria = Criteria.new(bound_class, @operator==:AND ? :OR : :AND)
    newcriteria << self
    newcriteria.add(c, operator, opts, &block)
    return newcriteria
  end
  
  # If the criterion object is nil, and there is a block given, yield a new Criteria to the block
  c = yield(self) if c.nil? and block_given?
  
  raise "Supplied argument is nil" if c.nil?
    
  # puts "Criteria.add: #{self} #{operator} #{c}"
  # If the c is a column, moan about it and refuse to continue
  if c.is_a? Column
    raise "You cannot directly #{operator.to_s.upcase} an instanceof Column, you must call some sort of expression (eq, ne, gt, ge, etc) on it."
  end
  
  # If the criterion is bound to a class and this is also bound to a class we try and find an applicable association for the criterion
  if !c.bound_class.nil? and !@clazz.nil?
    # puts " + #{c.bound_class} AND #{@clazz}"
    a=@clazz.find_associations_with(c.bound_class)
    
    if a.size>1 and a.include? opts[:via]
      @associations << opts[:via]
    elsif a.size==0
      # do nothing
    else
      @associations << a.first
    end
  end
  
  @criteria << c
  self
end

#all_criteriaObject

Returns an unmodifiable array of all AND’d and OR’d criteria



60
61
62
# File 'lib/criteria.rb', line 60

def all_criteria
  and_criteria+or_criteria
end

#and(c = nil, &block) ⇒ Object

AND a criterion with the existing Criteria



98
99
100
# File 'lib/criteria.rb', line 98

def and(c=nil, &block)
  add(c, :AND, &block)
end

#and_criteriaObject

Return a modifiable array of AND’d criteria



65
66
67
68
69
70
71
# File 'lib/criteria.rb', line 65

def and_criteria
  if operator==:AND
    @criteria
  else
    @other_criteria.and_criteria
  end
end

#associationsObject



200
201
202
203
204
205
206
# File 'lib/criteria.rb', line 200

def associations
  out = @associations
  @criteria.each do |c| 
    out+=c.associations
  end
  out
end

#bound_classObject

If this Criteria was created by passing an ActiveRecord::Base subclass as the first argument to the constructor, then this will return that class. Criteria that are bound to classes can perform additional introspection to resolve association dependencies



55
56
57
# File 'lib/criteria.rb', line 55

def bound_class
  @clazz
end

#columnsObject

Return a unique list of column objects that are referenced in this query



184
185
186
187
188
189
190
191
192
# File 'lib/criteria.rb', line 184

def columns
  columns = []
  @criteria.each do |c|
   c.columns.each do |c2|
     columns << c2
   end
  end 
  columns.uniq
end

#countObject



212
213
214
# File 'lib/criteria.rb', line 212

def count
  @clazz.count(self)
end

#firstObject



216
217
218
# File 'lib/criteria.rb', line 216

def first
  @clazz.find(:first, self)
end

#group_byObject

Get the collection of columns to group by



88
89
90
# File 'lib/criteria.rb', line 88

def group_by
  @group_by
end

#inspect(indent = 0) ⇒ Object



267
268
269
270
271
272
# File 'lib/criteria.rb', line 267

def inspect(indent=0)
  indent_str = " " * indent
  "(\n" + @criteria.collect do |c| 
    "#{" " * (indent+1)}#{@operator} #{c.inspect(indent+1)}"
  end.join("\n") + "\n#{indent_str})"
end

#listObject



208
209
210
# File 'lib/criteria.rb', line 208

def list
  @clazz.find(:all, self)
end

#or(c = nil, &block) ⇒ Object

OR a criterion with the existing Criteria



103
104
105
# File 'lib/criteria.rb', line 103

def or(c=nil, &block)
  add(c, :OR, &block)
end

#or_criteriaObject

Return a modifiable array of OR’d criteria



74
75
76
77
78
79
80
# File 'lib/criteria.rb', line 74

def or_criteria
  if operator==:OR
    @criteria
  else
    @other_criteria.or_criteria
  end
end

#order_byObject

Get the collection of Order objects to order by



93
94
95
# File 'lib/criteria.rb', line 93

def order_by
  @order_by
end

#selectObject

Returns an array of column’s to be selected



83
84
85
# File 'lib/criteria.rb', line 83

def select
  @select
end

#tablesObject

Get a read-only array of all the table names that will be included in this query



196
197
198
# File 'lib/criteria.rb', line 196

def tables
  columns.collect {|c| c.table_name }.uniq
end

#to_group_by_sqlObject



175
176
177
# File 'lib/criteria.rb', line 175

def to_group_by_sql
  @group_by.size>0 ? @group_by.collect {|g| g.to_s}.join(",") : nil
end

#to_hashObject

FIXME: this returns a list of table names in :include, whereas it should contain the relationship names



251
252
253
254
255
256
257
258
259
260
261
# File 'lib/criteria.rb', line 251

def to_hash
  {
    :include => self.associations,
    :conditions => self.to_where_sql,
    :limit => self.limit,
    :offset => self.offset,
    :order => self.to_order_by_sql,
    :group => self.to_group_by_sql,
    :select => self.to_select_sql
  }
end

#to_order_by_sqlObject



171
172
173
# File 'lib/criteria.rb', line 171

def to_order_by_sql
  @order_by.size>0 ? @order_by.collect {|o| o.to_s}.join(",") : nil
end

#to_sObject



263
264
265
# File 'lib/criteria.rb', line 263

def to_s
  "Criteria(#{to_hash.inspect})"
end

#to_select_sqlObject



179
180
181
# File 'lib/criteria.rb', line 179

def to_select_sql
  @select.size>0 ? @select.collect{|s| s.to_s}.join(",") : nil
end

#to_where_sqlObject

Convert the AND and OR statements into the WHERE SQL



162
163
164
165
166
167
168
169
# File 'lib/criteria.rb', line 162

def to_where_sql
  if @criteria.size>0
    out = @criteria.collect {|c| "#{c.to_where_sql}"}.join(" #{@operator} ")
    "(#{out})"
  else
    ""
  end
end

#|(criterion) ⇒ Object

OR this with another criterion



157
158
159
# File 'lib/criteria.rb', line 157

def |(criterion)
  self.or(criterion)
end