Class: DataMapper::Query

Attributes

Instance Attributes

model [RW] public

Returns the value of attribute model.

repository [RW] public

Returns the value of attribute repository.

Constants

OPTIONS
[ :reload, :offset, :limit, :order, :fields, :links, :includes, :conditions ]

Constructor Summary

private initialize(repository, model, options = {})
[View source]


205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
# File 'dm-core/lib/dm-core/query.rb', line 205

def initialize(repository, model, options = {})
  raise TypeError, "+repository+ must be a Repository, but is #{repository.class}" unless repository.kind_of?(Repository)

  options.each_pair { |k,v| option[k] = v.call if v.is_a? Proc } if options.is_a? Hash

  validate_model(model)
  validate_options(options)

  @repository = repository
  @properties = model.properties(@repository.name)

  @model      = model                           # must be Class that includes DM::Resource
  @reload     = options.fetch :reload,   false  # must be true or false
  @offset     = options.fetch :offset,   0      # must be an Integer greater than or equal to 0
  @limit      = options.fetch :limit,    nil    # must be an Integer greater than or equal to 1
  @order      = options.fetch :order,    []     # must be an Array of Symbol, DM::Query::Direction or DM::Property
  @fields     = options.fetch :fields,   @properties.defaults  # must be an Array of Symbol, String or DM::Property
  @links      = options.fetch :links,    []     # must be an Array of Tuples - Tuple [DM::Query,DM::Assoc::Relationship]
  @includes   = options.fetch :includes, []     # must be an Array of DM::Query::Path
  @conditions = []                              # must be an Array of triplets (or pairs when passing in raw String queries)

  # normalize order and fields
  normalize_order
  normalize_fields

  # XXX: should I validate that each property in @order corresponds
  # to something in @fields?  Many DB engines require they match,
  # and I can think of no valid queries where a field would be so
  # important that you sort on it, but not important enough to
  # return.

  # normalize links and includes.
  # NOTE: this must be done after order and fields
  normalize_links
  normalize_includes

  translate_custom_types(@properties, options)

  # treat all non-options as conditions
  (options.keys - OPTIONS - OPTIONS.map(&:to_s)).each do |k|
    append_condition(k, options[k])
  end

  # parse raw options[:conditions] differently
  if conditions = options[:conditions]



    if conditions.kind_of?(Array)



      raw_query, *bind_values = conditions
      @conditions << if bind_values.empty?



        [ :raw, raw_query ]
      else
        [ :raw, raw_query, bind_values ]
      end
    end
  end

  # freeze the internal attributes
  OPTIONS.each do |attribute|
    instance_variable_get("@#{attribute}").freeze
  end

#      freeze
end

Public Visibility

Public Instance Method Summary

#==(other)
#inspect
#merge(other)
#merge_sub_select_conditions(operator, property, value)

find the point in self.

#update(other)

Public Instance Methods Inherited from Object

validatable?

Public Instance Method Details

==

public ==(other)
[View source]


134
135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'dm-core/lib/dm-core/query.rb', line 134

def ==(other)
  return true if super
  # TODO: add a #hash method, and then use it in the comparison, eg:
  #   return hash == other.hash
  @model    == other.model    &&
  @reload   == other.reload   &&
  @offset   == other.offset   &&
  @limit    == other.limit    &&
  @order    == other.order    &&  # order is significant, so do not sort this
  @fields   == other.fields   &&  # TODO: sort this so even if the order is different, it is equal
  @links    == other.links    &&  # TODO: sort this so even if the order is different, it is equal
  @includes == other.includes &&  # TODO: sort this so even if the order is different, it is equal
  @conditions.sort_by { |c| c.at(0).hash + c.at(1).hash + c.at(2).hash } == other.conditions.sort_by { |c| c.at(0).hash + c.at(1).hash + c.at(2).hash }
end

inspect

public inspect
[View source]


187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'dm-core/lib/dm-core/query.rb', line 187

def inspect


  attrs = [
    [ :repository, repository.name ],
    [ :model,      model           ],
    [ :fields,     fields          ],
    [ :links,      links           ],
    [ :conditions, conditions      ],
    [ :order,      order           ],
    [ :limit,      limit           ],
    [ :offset,     offset          ],
    [ :reload,     reload          ],
  ]

  "#<#{self.class.name} #{attrs.map { |(k,v)| "@#{k}=#{v.inspect}" } * ' '}>"
end

merge

public merge(other)
[View source]


130
131
132
# File 'dm-core/lib/dm-core/query.rb', line 130

def merge(other)
  dup.update(other)
end

merge_sub_select_conditions

public merge_sub_select_conditions(operator, property, value)

find the point in self.conditions where the sub select tuple is located. Delete the tuple and add value.conditions. value must be a <DM::Query>

[View source]


169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
# File 'dm-core/lib/dm-core/query.rb', line 169

def merge_sub_select_conditions(operator, property, value)
  raise ArgumentError, "+value+ is not a #{self.class}, but was #{value.class}", caller unless self.class === value

  new_conditions = []
  conditions.each do |tuple|
    if tuple.at(0).to_s == operator.to_s && tuple.at(1) == property && tuple.at(2) == value



      value.conditions.each do |sub_select_tuple|
        new_conditions << sub_select_tuple
      end
    else
      new_conditions << tuple
    end
  end
  @conditions = new_conditions
end

update

public update(other)
[View source]


112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'dm-core/lib/dm-core/query.rb', line 112

def update(other)
  other = self.class.new(@repository, model, other) if Hash === other

  @model, @reload = other.model, other.reload

  @offset = other.offset unless other.offset == 0
  @limit  = other.limit  unless other.limit.nil?

  @order    |= other.order
  @fields   |= other.fields
  @links    |= other.links
  @includes |= other.includes

  update_conditions(other)

  self
end