Class: DataMapper::Collection

Inherits:
LazyArray
  • Object
show all
Extended by:
Deprecate
Defined in:
lib/dm-core/collection.rb

Overview

The Collection class represents a list of resources persisted in a repository and identified by a query.

A Collection should act like an Array in every way, except that it will attempt to defer loading until the results from the repository are needed.

A Collection is typically returned by the Model#all method.

Direct Known Subclasses

Associations::OneToMany::Collection

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Deprecate

deprecate

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *args, &block) ⇒ Object (private)

Delegates to Model, Relationships or the superclass (LazyArray)

When this receives a method that belongs to the Model the Collection is scoped to, it will execute the method within the same scope as the Collection and return the results.

When this receives a method that is a relationship the Model has defined, it will execute the association method within the same scope as the Collection and return the results.

Otherwise this method will delegate to a method in the superclass (LazyArray) and return the results.

Returns:

  • (Object)

    the return values of the delegated methods



1342
1343
1344
1345
1346
1347
1348
1349
1350
# File 'lib/dm-core/collection.rb', line 1342

def method_missing(method, *args, &block)
  if model.model_method_defined?(method)
    delegate_to_model(method, *args, &block)
  elsif relationship = relationships[method] || relationships[method.to_s.singular.to_sym]
    delegate_to_relationship(relationship, *args)
  else
    super
  end
end

Instance Attribute Details

#queryQuery (readonly)

Returns the Query the Collection is scoped with

Returns:

  • (Query)

    the Query the Collection is scoped with



31
32
33
# File 'lib/dm-core/collection.rb', line 31

def query
  @query
end

Instance Method Details

#<<(resource) ⇒ self

Append one Resource to the Collection and relate it

Parameters:

  • resource (Resource)

    the resource to add to this collection

Returns:

  • (self)


462
463
464
465
466
467
468
469
# File 'lib/dm-core/collection.rb', line 462

def <<(resource)
  if resource.kind_of?(Hash)
    resource = new(resource)
  end

  resource_added(resource)
  super
end

#[](*args) ⇒ Resource, ... Also known as: slice

Simulates Array#slice and returns a new Collection whose query has a new offset or limit according to the arguments provided.

If you provide a range, the min is used as the offset and the max minues the offset is used as the limit.

Parameters:

  • *args (Integer, Array(Integer), Range)

    the offset, offset and limit, or range indicating first and last position

Returns:

  • (Resource, Collection, nil)

    The entry which resides at that offset and limit, or a new Collection object with the set limits and offset

  • (nil)

    The offset (or starting offset) is out of range

Raises:

  • (ArgumentError)

    “arguments may be 1 or 2 Integers, or 1 Range object, was: #DataMapper::Collection.argsargs.inspect”



331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
# File 'lib/dm-core/collection.rb', line 331

def [](*args)
  offset, limit = extract_slice_arguments(*args)

  if args.size == 1 && args.first.kind_of?(Integer)
    return at(offset)
  end

  query = sliced_query(offset, limit)

  if loaded? || partially_loaded?(offset, limit)
    new_collection(query, super)
  else
    new_collection(query)
  end
end

#[]=(*args) ⇒ Resource, ... Also known as: splice

Splice a list of Resources at a given offset or range

When nil is provided instead of a Resource or a list of Resources this will remove all of the Resources at the specified position.

Parameters:

  • *args (Integer, Array(Integer), Range)

    The offset, offset and limit, or range indicating first and last position. The last argument may be a Resource, a list of Resources or nil.

Returns:

  • (Resource, Enumerable)

    the Resource or list of Resources that was spliced into the Collection

  • (nil)

    If nil was used to delete the entries



395
396
397
398
399
400
401
402
403
404
405
406
407
408
# File 'lib/dm-core/collection.rb', line 395

def []=(*args)
  orphans = Array(superclass_slice(*args[0..-2]))

  # relate new resources
  resources = resources_added(super)

  # mark resources as removed
  resources_removed(orphans - loaded_entries)

  # ensure remaining orphans are still related
  (orphans & loaded_entries).each { |resource| relate_resource(resource) }

  resources
end

#all(query = nil) ⇒ Collection

Returns a new Collection optionally scoped by query

This returns a new Collection scoped relative to the current Collection.

cars_from_91 = Cars.all(:year_manufactured => 1991)
toyotas_91 = cars_from_91.all(:manufacturer => 'Toyota')
toyotas_91.all? { |car| car.year_manufactured == 1991 }       #=> true
toyotas_91.all? { |car| car.manufacturer == 'Toyota' }        #=> true

If query is a Hash, results will be found by merging query with this Collection’s query. If query is a Query, results will be found using query as an absolute query.

Parameters:

  • query (Hash, Query) (defaults to: nil)

    optional parameters to scope results with

Returns:



177
178
179
180
181
182
183
184
185
186
# File 'lib/dm-core/collection.rb', line 177

def all(query = nil)
  if query.nil? || (query.kind_of?(Hash) && query.empty?)
    dup
  else
    # TODO: if there is no order parameter, and the Collection is not loaded
    # check to see if the query can be satisfied by the head/tail

    new_collection(scoped_query(query))
  end
end

#at(offset) ⇒ Resource?

Lookup a Resource from the Collection by offset

Parameters:

  • offset (Integer)

    offset of the Resource in the Collection

Returns:

  • (Resource)

    Resource which matches the supplied offset

  • (nil)

    No Resource matches the supplied offset



291
292
293
294
295
296
297
298
299
300
# File 'lib/dm-core/collection.rb', line 291

def at(offset)
  if loaded? || partially_loaded?(offset)
    return unless resource = super
    orphan_resource(resource)
  elsif offset >= 0
    first(:offset => offset)
  else
    last(:offset => offset.abs - 1)
  end
end

#clean?Boolean

Checks if all the resources have no changes to save

Returns:

  • (Boolean)

    true if the resource may not be persisted



880
881
882
# File 'lib/dm-core/collection.rb', line 880

def clean?
  !dirty?
end

#clearself

Removes all Resources from the Collection

This should remove and orphan each Resource from the Collection

Returns:

  • (self)


659
660
661
662
663
664
# File 'lib/dm-core/collection.rb', line 659

def clear
  if loaded?
    resources_removed(self)
  end
  super
end

#collect! {|Resource| ... } ⇒ self Also known as: map!

Invoke the block for each resource and replace it the return value

Yields:

  • (Resource)

    Each resource in the collection

Returns:

  • (self)


448
449
450
# File 'lib/dm-core/collection.rb', line 448

def collect!
  super { |resource| resource_added(yield(resource_removed(resource))) }
end

#concat(resources) ⇒ self

Appends the resources to self

Parameters:

  • resources (Enumerable)

    List of Resources to append to the collection

Returns:

  • (self)


479
480
481
482
# File 'lib/dm-core/collection.rb', line 479

def concat(resources)
  resources_added(resources)
  super
end

#create(attributes = {}) ⇒ Resource

Create a Resource in the Collection

Parameters:

  • attributes (Hash(Symbol => Object)) (defaults to: {})

    attributes to set

Returns:

  • (Resource)

    the newly created Resource instance



720
721
722
# File 'lib/dm-core/collection.rb', line 720

def create(attributes = {})
  _create(true, attributes)
end

#create!(attributes = {}) ⇒ Resource

Create a Resource in the Collection, bypassing hooks

Parameters:

  • attributes (Hash(Symbol => Object)) (defaults to: {})

    attributes to set

Returns:

  • (Resource)

    the newly created Resource instance



733
734
735
# File 'lib/dm-core/collection.rb', line 733

def create!(attributes = {})
  _create(false, attributes)
end

#delete(resource) ⇒ Resource?

Remove Resource from the Collection

This should remove an included Resource from the Collection and orphan it from the Collection. If the Resource is not within the Collection, it should return nil.

Parameters:

  • resource (Resource)

    the Resource to remove from the Collection

Returns:

  • (Resource)

    If resource is within the Collection

  • (nil)

    If resource is not within the Collection



570
571
572
573
574
# File 'lib/dm-core/collection.rb', line 570

def delete(resource)
  if resource = super
    resource_removed(resource)
  end
end

#delete_at(offset) ⇒ Resource?

Remove Resource from the Collection by offset

This should remove the Resource from the Collection at a given offset and orphan it from the Collection. If the offset is out of range return nil.

Parameters:

  • offset (Integer)

    the offset of the Resource to remove from the Collection

Returns:

  • (Resource)

    If offset is within the Collection

  • (nil)

    If offset is not within the Collection



591
592
593
594
595
# File 'lib/dm-core/collection.rb', line 591

def delete_at(offset)
  if resource = super
    resource_removed(resource)
  end
end

#delete_if {|Resource| ... } ⇒ self

Deletes every Resource for which block evaluates to true.

Yields:

  • (Resource)

    Each resource in the Collection

Returns:

  • (self)


604
605
606
# File 'lib/dm-core/collection.rb', line 604

def delete_if
  super { |resource| yield(resource) && resource_removed(resource) }
end

#destroyBoolean

Remove every Resource in the Collection from the repository

This performs a deletion of each Resource in the Collection from the repository and clears the Collection.

Returns:

  • (Boolean)

    true if the resources were successfully destroyed



820
821
822
823
824
825
826
# File 'lib/dm-core/collection.rb', line 820

def destroy
  if destroyed = all? { |resource| resource.destroy }
    clear
  end

  destroyed
end

#destroy!Boolean

Remove all Resources from the repository, bypassing validation

This performs a deletion of each Resource in the Collection from the repository and clears the Collection while skipping validation.

Returns:

  • (Boolean)

    true if the resources were successfully destroyed



838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
# File 'lib/dm-core/collection.rb', line 838

def destroy!
  if query.limit || query.offset > 0 || query.links.any?
    key        = model.key(repository.name)
    conditions = Query.target_conditions(self, key, key)

    unless model.all(:repository => repository, :conditions => conditions).destroy!
      return false
    end
  else
    repository.delete(self)
    mark_loaded
  end

  if loaded?
    each { |resource| resource.reset }
    clear
  end

  true
end

#dirty?Boolean

Checks if any resources have unsaved changes

Returns:

  • (Boolean)

    true if a resource may be persisted



890
891
892
# File 'lib/dm-core/collection.rb', line 890

def dirty?
  loaded_entries.any? { |resource| resource.dirty? }
end

#first(*args) ⇒ Resource, Collection

Return the first Resource or the first N Resources in the Collection with an optional query

When there are no arguments, return the first Resource in the Collection. When the first argument is an Integer, return a Collection containing the first N Resources. When the last (optional) argument is a Hash scope the results to the query.

Parameters:

  • limit (Integer)

    (optional) limit the returned Collection to a specific number of entries

  • query (Hash)

    (optional) scope the returned Resource or Collection to the supplied query

Returns:

  • (Resource, Collection)

    The first resource in the entries of this collection, or a new collection whose query has been merged



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
# File 'lib/dm-core/collection.rb', line 205

def first(*args)
  last_arg = args.last

  limit      = args.first if args.first.kind_of?(Integer)
  with_query = last_arg.respond_to?(:merge) && !last_arg.blank?

  query = with_query ? last_arg : {}
  query = self.query.slice(0, limit || 1).update(query)

  # TODO: when a query provided, and there are enough elements in head to
  # satisfy the query.limit, filter the head with the query, and make
  # sure it matches the limit exactly.  if so, use that result instead
  # of calling all()
  #   - this can probably only be done if there is no :order parameter

  collection = if !with_query && (loaded? || lazy_possible?(head, query.limit))
    new_collection(query, super(query.limit))
  else
    all(query)
  end

  if limit
    collection
  else
    collection.to_a.first
  end
end

#first_or_create(conditions = {}, attributes = {}) ⇒ Resource

Finds the first Resource by conditions, or creates a new Resource with the attributes if none found

Parameters:

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

    The conditions to be used to search

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

    The attributes to be used to create the resource with if none found

Returns:

  • (Resource)

    The instance found by query, or created with attributes if none found



692
693
694
# File 'lib/dm-core/collection.rb', line 692

def first_or_create(conditions = {}, attributes = {})
  first(conditions) || create(conditions.merge(attributes))
end

#first_or_new(conditions = {}, attributes = {}) ⇒ Resource

Finds the first Resource by conditions, or initializes a new Resource with the attributes if none found

Parameters:

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

    The conditions to be used to search

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

    The attributes to be used to initialize the resource with if none found

Returns:

  • (Resource)

    The instance found by query, or created with attributes if none found



677
678
679
# File 'lib/dm-core/collection.rb', line 677

def first_or_new(conditions = {}, attributes = {})
  first(conditions) || new(conditions.merge(attributes))
end

#get(*key) ⇒ Resource?

Lookup a Resource in the Collection by key

This looksup a Resource by key, typecasting the key to the proper object if necessary.

toyotas = Cars.all(:manufacturer => 'Toyota')
toyo = Cars.first(:manufacturer => 'Toyota')
toyotas.get(toyo.id) == toyo                  #=> true

Parameters:

  • *key (Enumerable)

    keys which uniquely identify a resource in the Collection

Returns:

  • (Resource)

    Resource which matches the supplied key

  • (nil)

    No Resource matches the supplied key



110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/dm-core/collection.rb', line 110

def get(*key)
  key = model.key(repository.name).typecast(key)

  resource = @identity_map[key] || if !loaded? && (query.limit || query.offset > 0)
    # current query is exclusive, find resource within the set

    # TODO: use a subquery to retrieve the Collection and then match
    #   it up against the key.  This will require some changes to
    #   how subqueries are generated, since the key may be a
    #   composite key.  In the case of DO adapters, it means subselects
    #   like the form "(a, b) IN(SELECT a, b FROM ...)", which will
    #   require making it so the Query condition key can be a
    #   Property or an Array of Property objects

    # use the brute force approach until subquery lookups work
    lazy_load
    @identity_map[key]
  else
    # current query is all inclusive, lookup using normal approach
    first(model.key_conditions(repository, key))
  end

  return if resource.nil?

  orphan_resource(resource)
end

#get!(*key) ⇒ Resource?

Lookup a Resource in the Collection by key, raising an exception if not found

This looksup a Resource by key, typecasting the key to the proper object if necessary.

Parameters:

  • *key (Enumerable)

    keys which uniquely identify a resource in the Collection

Returns:

  • (Resource)

    Resource which matches the supplied key

  • (nil)

    No Resource matches the supplied key

Raises:



153
154
155
# File 'lib/dm-core/collection.rb', line 153

def get!(*key)
  get(*key) || raise(ObjectNotFoundError, "Could not find #{model.name} with key #{key.inspect}")
end

#insert(offset, *resources) ⇒ self

Inserts the Resources before the Resource at the offset (which may be negative).

Parameters:

  • offset (Integer)

    The offset to insert the Resources before

  • *resources (Enumerable)

    List of Resources to insert

Returns:

  • (self)


526
527
528
529
# File 'lib/dm-core/collection.rb', line 526

def insert(offset, *resources)
  resources_added(resources)
  super
end

#inspectString

Gets a Human-readable representation of this collection, showing all elements contained in it

Returns:

  • (String)

    Human-readable representation of this collection, showing all elements



901
902
903
# File 'lib/dm-core/collection.rb', line 901

def inspect
  "[#{map { |resource| resource.inspect }.join(', ')}]"
end

#last(*args) ⇒ Resource, Collection

Return the last Resource or the last N Resources in the Collection with an optional query

When there are no arguments, return the last Resource in the Collection. When the first argument is an Integer, return a Collection containing the last N Resources. When the last (optional) argument is a Hash scope the results to the query.

Parameters:

  • limit (Integer)

    (optional) limit the returned Collection to a specific number of entries

  • query (Hash)

    (optional) scope the returned Resource or Collection to the supplied query

Returns:

  • (Resource, Collection)

    The last resource in the entries of this collection, or a new collection whose query has been merged



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
276
277
278
# File 'lib/dm-core/collection.rb', line 250

def last(*args)
  last_arg = args.last

  limit      = args.first if args.first.kind_of?(Integer)
  with_query = last_arg.respond_to?(:merge) && !last_arg.blank?

  query = with_query ? last_arg : {}
  query = self.query.slice(0, limit || 1).update(query).reverse!

  # tell the Query to prepend each result from the adapter
  query.update(:add_reversed => !query.add_reversed?)

  # TODO: when a query provided, and there are enough elements in tail to
  # satisfy the query.limit, filter the tail with the query, and make
  # sure it matches the limit exactly.  if so, use that result instead
  # of calling all()

  collection = if !with_query && (loaded? || lazy_possible?(tail, query.limit))
    new_collection(query, super(query.limit))
  else
    all(query)
  end

  if limit
    collection
  else
    collection.to_a.last
  end
end

#modelModel

Returns the Model

Returns:

  • (Model)

    the Model the Collection is associated with



49
50
51
# File 'lib/dm-core/collection.rb', line 49

def model
  query.model
end

#new(attributes = {}) ⇒ Resource

Initializes a Resource and appends it to the Collection

Parameters:

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

    Attributes with which to initialize the new resource

Returns:

  • (Resource)

    a new Resource initialized with attributes



705
706
707
708
709
# File 'lib/dm-core/collection.rb', line 705

def new(attributes = {})
  resource = repository.scope { model.new(attributes) }
  self << resource
  resource
end

#popResource

Removes and returns the last Resource in the Collection

Returns:

  • (Resource)

    the last Resource in the Collection



537
538
539
540
541
# File 'lib/dm-core/collection.rb', line 537

def pop(*)
  if removed = super
    resources_removed(removed)
  end
end

#propertiesPropertySet

Returns the PropertySet representing the fields in the Collection scope

Returns:

  • (PropertySet)

    The set of properties this Collection’s query will retrieve



911
912
913
# File 'lib/dm-core/collection.rb', line 911

def properties
  PropertySet.new(query.fields)
end

#push(*resources) ⇒ self

Append one or more Resources to the Collection

This should append one or more Resources to the Collection and relate each to the Collection.

Parameters:

  • *resources (Enumerable)

    List of Resources to append

Returns:

  • (self)


495
496
497
498
# File 'lib/dm-core/collection.rb', line 495

def push(*resources)
  resources_added(resources)
  super
end

#reject! {|Resource| ... } ⇒ Collection?

Deletes every Resource for which block evaluates to true

Yields:

  • (Resource)

    Each resource in the Collection

Returns:

  • (Collection)

    If resources were removed

  • (nil)

    If no resources were removed



618
619
620
# File 'lib/dm-core/collection.rb', line 618

def reject!
  super { |resource| yield(resource) && resource_removed(resource) }
end

#relationshipsHash

Returns the Relationships for the Collection’s Model

Returns:

  • (Hash)

    The model’s relationships, mapping the name to the Associations::Relationship object



922
923
924
# File 'lib/dm-core/collection.rb', line 922

def relationships
  model.relationships(repository.name)
end

#reload(query = nil) ⇒ self

Reloads the Collection from the repository

If query is provided, updates this Collection’s query with its conditions

cars_from_91 = Cars.all(:year_manufactured => 1991)
cars_from_91.first.year_manufactured = 2001   # note: not saved
cars_from_91.reload
cars_from_91.first.year                       #=> 1991

Parameters:

  • query (Query, Hash) (defaults to: nil)

    (optional) further restrict results with query

Returns:

  • (self)


68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/dm-core/collection.rb', line 68

def reload(query = nil)
  query = query.nil? ? self.query.dup : self.query.merge(query)

  # make sure the Identity Map contains all the existing resources
  identity_map = repository.identity_map(model)

  loaded_entries.each do |resource|
    identity_map[resource.key] = resource
  end

  properties = model.properties(repository.name)
  fields     = properties.key | query.fields

  if discriminator = properties.discriminator
    fields |= [ discriminator ]
  end

  # sort fields based on declared order, for more consistent reload queries
  fields = properties & fields

  # replace the list of resources
  replace(all(query.update(:fields => fields, :reload => true)))
end

#replace(other) ⇒ self Also known as: collection_replace

Replace the Resources within the Collection

Parameters:

  • other (Enumerable)

    List of other Resources to replace with

Returns:

  • (self)


630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
# File 'lib/dm-core/collection.rb', line 630

def replace(other)
  other = other.map do |resource|
    if resource.kind_of?(Hash)
      new(resource)
    else
      resource
    end
  end

  if loaded?
    resources_removed(self - other)
  end

  super(resources_added(other))
end

#repositoryRepository

Returns the Repository

Returns:

  • (Repository)

    the Repository this Collection is associated with



39
40
41
# File 'lib/dm-core/collection.rb', line 39

def repository
  query.repository
end

#respond_to?(method, include_private = false) ⇒ Boolean

Check to see if collection can respond to the method

Parameters:

  • method (Symbol)

    method to check in the object

  • include_private (Boolean) (defaults to: false)

    if set to true, collection will check private methods

Returns:

  • (Boolean)

    true if method can be responded to



870
871
872
# File 'lib/dm-core/collection.rb', line 870

def respond_to?(method, include_private = false)
  super || model.respond_to?(method) || relationships.key?(method)
end

#reverseCollection

Return a copy of the Collection sorted in reverse

Returns:

  • (Collection)

    Collection equal to self but ordered in reverse



418
419
420
# File 'lib/dm-core/collection.rb', line 418

def reverse
  dup.reverse!
end

#reverse!self

Return the Collection sorted in reverse

Returns:

  • (self)


427
428
429
430
431
432
433
434
435
436
437
438
439
# File 'lib/dm-core/collection.rb', line 427

def reverse!
  query.reverse!

  # reverse without kicking if possible
  if loaded?
    @array.reverse!
  else
    # reverse and swap the head and tail
    @head, @tail = tail.reverse!, head.reverse!
  end

  self
end

#saveBoolean

Save every Resource in the Collection

Returns:

  • (Boolean)

    true if the resources were successfully saved



797
798
799
# File 'lib/dm-core/collection.rb', line 797

def save
  _save(true)
end

#save!Boolean

Save every Resource in the Collection bypassing validation

Returns:

  • (Boolean)

    true if the resources were successfully saved



807
808
809
# File 'lib/dm-core/collection.rb', line 807

def save!
  _save(false)
end

#shiftResource

Removes and returns the first Resource in the Collection

Returns:

  • (Resource)

    the first Resource in the Collection



549
550
551
552
553
# File 'lib/dm-core/collection.rb', line 549

def shift(*)
  if removed = super
    resources_removed(removed)
  end
end

#slice!(*args) ⇒ Resource, ...

Deletes and Returns the Resources given by an offset or a Range

Parameters:

  • *args (Integer, Array(Integer), Range)

    the offset, offset and limit, or range indicating first and last position

Returns:

  • (Resource, Collection)

    The entry which resides at that offset and limit, or a new Collection object with the set limits and offset

  • (Resource, Collection, nil)

    The offset is out of range



361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
# File 'lib/dm-core/collection.rb', line 361

def slice!(*args)
  removed = super

  resources_removed(removed) unless removed.nil?

  # Workaround for Ruby <= 1.8.6
  compact! if RUBY_VERSION <= '1.8.6'

  unless removed.kind_of?(Enumerable)
    return removed
  end

  offset, limit = extract_slice_arguments(*args)

  query = sliced_query(offset, limit)

  new_collection(query, removed)
end

#unshift(*resources) ⇒ self

Prepend one or more Resources to the Collection

This should prepend one or more Resources to the Collection and relate each to the Collection.

Parameters:

  • *resources (Enumerable)

    The Resources to prepend

Returns:

  • (self)


511
512
513
514
# File 'lib/dm-core/collection.rb', line 511

def unshift(*resources)
  resources_added(resources)
  super
end

#update(attributes = {}) ⇒ Boolean

Update every Resource in the Collection

Person.all(:age.gte => 21).update(:allow_beer => true)

Parameters:

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

    attributes to update with

Returns:

  • (Boolean)

    true if the resources were successfully updated



748
749
750
751
752
753
# File 'lib/dm-core/collection.rb', line 748

def update(attributes = {})
  assert_update_clean_only(:update)

  dirty_attributes = model.new(attributes).dirty_attributes
  dirty_attributes.empty? || all? { |resource| resource.update(attributes) }
end

#update!(attributes = {}) ⇒ Boolean

Update every Resource in the Collection bypassing validation

Person.all(:age.gte => 21).update!(:allow_beer => true)

Parameters:

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

    attributes to update

Returns:

  • (Boolean)

    true if the resources were successfully updated



766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
# File 'lib/dm-core/collection.rb', line 766

def update!(attributes = {})
  assert_update_clean_only(:update!)

  dirty_attributes = model.new(attributes).dirty_attributes

  if dirty_attributes.empty?
    true
  elsif dirty_attributes.any? { |property, value| !property.nullable? && value.nil? }
    false
  else
    unless _update(dirty_attributes)
      return false
    end

    if loaded?
      each do |resource|
        dirty_attributes.each { |property, value| property.set!(resource, value) }
        repository.identity_map(model)[resource.key] = resource
      end
    end

    true
  end
end