Class: DataMapper::Collection

Inherits:
Object
  • Object
show all
Defined in:
lib/dm-adjust/collection.rb

Instance Method Summary collapse

Instance Method Details

#adjust(attributes = {}, reload = false) ⇒ Object

Raises:

  • (NotImplementedError)


4
5
6
# File 'lib/dm-adjust/collection.rb', line 4

def adjust(attributes = {}, reload = false)
  raise NotImplementedError, 'adjust *with* validations has not be written yet, try adjust!'
end

#adjust!(attributes = {}, reload = false) ⇒ Object

increment or decrement attributes on a collection

Examples:

Usage

* People.all.adjust(:salary => +1000)
* Children.all(:age.gte => 18).adjust(:allowance => -100)

Parameters:

  • attributes (Hash) (defaults to: {})

    A hash of attributes to adjust, and their adjustment

  • reload (FalseClass, TrueClass) (defaults to: false)

    If true, affected objects will be reloaded



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/dm-adjust/collection.rb', line 19

def adjust!(attributes = {}, reload = false)
  return true if attributes.empty?

  adjust_attributes = {}

  model.properties(repository.name).slice(*attributes.keys).each do |property|
    adjust_attributes[property] = attributes[property.name] if property
  end

  each { |r| attributes.each_pair{|a,v| r.attribute_set(a,r.send(a) + v) }; r.save } if loaded?

  # if none of the attributes that are adjusted is part of the collection-query
  # there is no need to load the collection (it will not change after adjustment)
  # if the query contains a raw sql-string, we cannot (truly) know, and must load.
  altered = query.conditions.detect{|c| adjust_attributes.include?(c[1]) || c[0] == :raw }

  identity_map   = repository.identity_map(model)
  key_properties = model.key(repository.name)

  if identity_map.any? && reload
    reload_query = key_properties.zip(identity_map.keys.transpose).to_hash

    if altered
      keys = all(reload_query.merge(:fields => key_properties)).map { |r| r.key }
      reload_query = model.key(repository.name).zip(keys.transpose).to_hash
    end
  end

  repository.adjust(adjust_attributes,scoped_query)

  # Reload affected objects in identity-map. if collection was affected, dont use the scope.
  (altered ? model : self).all(reload_query).reload(:fields => attributes.keys) if reload_query && reload_query.any?

  # if preload was set to false, and collection was affected by updates,
  # something is now officially borked. We'll try the best we can (still many cases this is borked for)
  query.conditions.each do |c|
    if adjustment = adjust_attributes[c[1]]
      case c[2]
        when Numeric then c[2] += adjustment
        when Range   then c[2] = (c[2].first+adjustment)..(c[2].last+adjustment)
      end if adjustment = adjust_attributes[c[1]]
    end
  end if altered

  true
end