Class: DataMapper::Collection

Inherits:
LazyArray 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

Attributes inherited from LazyArray

#head, #tail

Instance Method Summary collapse

Methods included from Deprecate

deprecate

Methods inherited from LazyArray

#==, #any?, #empty?, #eql?, #fetch, #freeze, #frozen?, #include?, #index, #kind_of?, #lazy_possible?, #load_with, #loaded?, #to_a, #values_at

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



1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
# File 'lib/dm-core/collection.rb', line 1439

def method_missing(method, *args, &block)
  relationships = self.relationships

  if model.respond_to?(method)
    delegate_to_model(method, *args, &block)
  elsif relationship = relationships[method] || relationships[method.to_s.singularize.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)


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

def <<(resource)
  super(resource_added(resource))
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”



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

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



457
458
459
460
461
462
463
464
465
466
467
# File 'lib/dm-core/collection.rb', line 457

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)

  resources
end

#all(query = Undefined) ⇒ 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: Undefined)

    optional parameters to scope results with

Returns:



217
218
219
220
221
222
223
224
225
# File 'lib/dm-core/collection.rb', line 217

def all(query = Undefined)
  if query.equal?(Undefined) || (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



350
351
352
353
354
355
356
357
358
359
360
361
362
# File 'lib/dm-core/collection.rb', line 350

def at(offset)
  if loaded? || partially_loaded?(offset)
    super
  elsif offset == 0
    first
  elsif offset > 0
    first(:offset => offset)
  elsif offset == -1
    last
  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



953
954
955
# File 'lib/dm-core/collection.rb', line 953

def clean?
  !dirty?
end

#clearself

Removes all Resources from the Collection

This should remove and orphan each Resource from the Collection

Returns:

  • (self)


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

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)


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

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)


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

def concat(resources)
  super(resources_added(resources))
end

#create(attributes = {}) ⇒ Resource

Create a Resource in the Collection

Parameters:

Returns:

  • (Resource)

    the newly created Resource instance



791
792
793
# File 'lib/dm-core/collection.rb', line 791

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

#create!(attributes = {}) ⇒ Resource

Create a Resource in the Collection, bypassing hooks

Parameters:

Returns:

  • (Resource)

    the newly created Resource instance



804
805
806
# File 'lib/dm-core/collection.rb', line 804

def create!(attributes = {})
  _create(attributes, false)
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



638
639
640
641
642
# File 'lib/dm-core/collection.rb', line 638

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



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

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)


672
673
674
# File 'lib/dm-core/collection.rb', line 672

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



893
894
895
896
897
898
899
# File 'lib/dm-core/collection.rb', line 893

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



911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
# File 'lib/dm-core/collection.rb', line 911

def destroy!
  repository = self.repository
  deleted    = repository.delete(self)

  if loaded?
    unless deleted == size
      return false
    end

    each do |resource|
      resource.persisted_state = Resource::State::Immutable.new(resource)
    end

    clear
  else
    mark_loaded
  end

  true
end

#difference(other) ⇒ Collection Also known as: -

Return the difference with another collection

Parameters:

Returns:

  • (Collection)

    the difference of the collection and other



127
128
129
# File 'lib/dm-core/collection.rb', line 127

def difference(other)
  set_operation(:-, other)
end

#dirty?Boolean

Checks if any resources have unsaved changes

Returns:

  • (Boolean)

    true if the resources have unsaved changed



963
964
965
# File 'lib/dm-core/collection.rb', line 963

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

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

Iterate over each Resource

Yields:

  • (Resource)

    Each resource in the collection

Returns:

  • (self)


507
508
509
510
511
512
513
514
515
516
# File 'lib/dm-core/collection.rb', line 507

def each
  super do |resource|
    begin
      original, resource.collection = resource.collection, self
      yield resource
    ensure
      resource.collection = original
    end
  end
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



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

def first(*args)
  first_arg = args.first
  last_arg  = args.last

  limit_specified = first_arg.kind_of?(Integer)
  with_query      = (last_arg.kind_of?(Hash) && !last_arg.empty?) || last_arg.kind_of?(Query)

  limit = limit_specified ? first_arg : 1
  query = with_query      ? last_arg  : {}

  query = self.query.slice(0, limit).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

  loaded = loaded?
  head   = self.head

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

  return collection if limit_specified

  resource = collection.to_a.first

  if with_query || loaded
    resource
  elsif resource
    head[0] = resource
  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



763
764
765
# File 'lib/dm-core/collection.rb', line 763

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



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

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



151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
# File 'lib/dm-core/collection.rb', line 151

def get(*key)
  assert_valid_key_size(key)

  key   = model_key.typecast(key)
  query = self.query

  @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
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:



193
194
195
# File 'lib/dm-core/collection.rb', line 193

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

#hashObject



979
980
981
# File 'lib/dm-core/collection.rb', line 979

def hash
  query.hash
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)


595
596
597
# File 'lib/dm-core/collection.rb', line 595

def insert(offset, *resources)
  super(offset, *resources_added(resources))
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



974
975
976
# File 'lib/dm-core/collection.rb', line 974

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

#intersection(other) ⇒ Collection Also known as: &

Return the intersection with another collection

Parameters:

Returns:

  • (Collection)

    the intersection of the collection and other



112
113
114
# File 'lib/dm-core/collection.rb', line 112

def intersection(other)
  set_operation(:&, other)
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



299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
# File 'lib/dm-core/collection.rb', line 299

def last(*args)
  first_arg = args.first
  last_arg  = args.last

  limit_specified = first_arg.kind_of?(Integer)
  with_query      = (last_arg.kind_of?(Hash) && !last_arg.empty?) || last_arg.kind_of?(Query)

  limit = limit_specified ? first_arg : 1
  query = with_query      ? last_arg  : {}

  query = self.query.slice(0, limit).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()

  loaded = loaded?
  tail   = self.tail

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

  return collection if limit_specified

  resource = collection.to_a.last

  if with_query || loaded
    resource
  elsif resource
    tail[tail.empty? ? 0 : -1] = resource
  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



776
777
778
779
780
# File 'lib/dm-core/collection.rb', line 776

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



605
606
607
608
609
# File 'lib/dm-core/collection.rb', line 605

def pop(*)
  if removed = super
    resources_removed(removed)
  end
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)


566
567
568
# File 'lib/dm-core/collection.rb', line 566

def push(*resources)
  super(*resources_added(resources))
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



686
687
688
# File 'lib/dm-core/collection.rb', line 686

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

#reload(other_query = Undefined) ⇒ 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)

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

def reload(other_query = Undefined)
  query = self.query
  query = other_query.equal?(Undefined) ? query.dup : query.merge(other_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

  # sort fields based on declared order, for more consistent reload queries
  properties = self.properties
  fields     = properties & (query.fields | model_key | [ properties.discriminator ].compact)

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

#replace(other) ⇒ self

Replace the Resources within the Collection

Parameters:

  • other (Enumerable)

    List of other Resources to replace with

Returns:

  • (self)


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

def replace(other)
  other = resources_added(other)
  resources_removed(entries - other)
  super(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



943
944
945
# File 'lib/dm-core/collection.rb', line 943

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



477
478
479
# File 'lib/dm-core/collection.rb', line 477

def reverse
  dup.reverse!
end

#reverse!self

Return the Collection sorted in reverse

Returns:

  • (self)


486
487
488
489
490
491
492
493
494
495
496
497
498
# File 'lib/dm-core/collection.rb', line 486

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



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

def save
  _save
end

#save!Boolean

Save every Resource in the Collection bypassing validation

Returns:

  • (Boolean)

    true if the resources were successfully saved



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

def save!
  _save(false)
end

#set(resources) ⇒ self

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

(Private) Set the Collection

Parameters:

  • resources (Array)

    resources to add to the collection

Returns:

  • (self)


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

def set(resources)
  superclass_replace(resources_added(resources))
  self
end

#shiftResource

Removes and returns the first Resource in the Collection

Returns:

  • (Resource)

    the first Resource in the Collection



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

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



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

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

#union(other) ⇒ Collection Also known as: |, +

Return the union with another collection

Parameters:

Returns:

  • (Collection)

    the union of the collection and other



96
97
98
# File 'lib/dm-core/collection.rb', line 96

def union(other)
  set_operation(:|, other)
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)


581
582
583
# File 'lib/dm-core/collection.rb', line 581

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

#update(attributes) ⇒ Boolean

Update every Resource in the Collection

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

Parameters:

  • attributes (Hash)

    attributes to update with

Returns:

  • (Boolean)

    true if the resources were successfully updated



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

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)

    attributes to update

Returns:

  • (Boolean)

    true if the resources were successfully updated



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

def update!(attributes)
  assert_update_clean_only(:update!)

  model = self.model

  dirty_attributes = model.new(attributes).dirty_attributes

  if dirty_attributes.empty?
    true
  elsif dirty_attributes.any? { |property, value| !property.valid?(value) }
    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