class Gorillib::Collection

The Collection class encapsulates the minimum functionality to let you:

A collection is best used for representing ‘plural’ properties of models; it is not intended to be some radical reimagining of a generic array or hash. We’ve found its locked-down capabilities to particularly useful for constructing DSLs (Domain-Specific Languages). Collections are not intended to be performant: its abstraction layer comes at the price of additional method calls.

### Gated admission

Collection provides a well-defended perimeter. Every item added to the collection (whether sent to the initializer, the passes through ‘add` method

### Familiarity with its contents

Typically your model will have a familiar (but not intimate) relationship with its plural property:

In the case of a ModelCollection,

### Barebones enumerable methods

The set of methods is purposefully sparse. If you want to use ‘select`, `invert`, etc, just invoke `to_hash` or `to_a` and work with the copy it gives you.

Collection responds to:

- receive!, values, to_a, each and each_value;
- length, size, empty?, blank?
- [], []=, include?, fetch, delete, each_pair, to_hash.
- `key_method`: called on items to get their key; `to_key` by default.
- `<<`: adds item under its `key_method` key
- `receive!`s an array by auto-keying the elements, or a hash by trusting what you give it

A ModelCollection adds:

- `factory`: generates new items, converts received items
- `update_or_create: if absent, creates item with given attributes and
  `key_method => key`; if present, updates with given attributes.

Attributes

belongs_to[R]

Object that owns this collection, if any

clxn[R]
{Symbol => Object}

The actual store of items – not for you to mess with

Public Class Methods

native?(obj) click to toggle source

A ‘native` object does not need any transformation; it is accepted directly. By default, an object is native if it `is_a?` this class

@param obj [Object] the object that will be received @return [true, false] true if the item does not need conversion

# File lib/gorillib/collection.rb, line 176
def self.native?(obj)
  obj.is_a?(self)
end
new(options={}) click to toggle source

include Gorillib::Model

# File lib/gorillib/collection.rb, line 77
def initialize(options={})
  @clxn       = Hash.new
  @key_method = options[:key_method] if options[:key_method]
  @belongs_to = options[:belongs_to] if options[:belongs_to]
end
receive(items, *args) click to toggle source

Create a new collection and add the given items to it (if given an existing collection, just returns it directly)

# File lib/gorillib/collection.rb, line 164
def self.receive(items, *args)
  return items if native?(items)
  coll = new(*args)
  coll.receive!(items)
  coll
end

Public Instance Methods

<<(item) click to toggle source

Adds item, returning the collection itself. @return [Gorillib::Collection] the collection

# File lib/gorillib/collection.rb, line 128
def <<(item)
  add(item)
  self
end
==(other) click to toggle source

Two collections are equal if they have the same class and their contents are equal

@param [Gorillib::Collection, Object] other The other collection to compare @return [true, false] True if attributes are equal and other is instance of the same Class

# File lib/gorillib/collection.rb, line 184
def ==(other)
  return false unless other.instance_of?(self.class)
  clxn == other.send(:clxn)
end
[]=(label, item) click to toggle source

add item with given label

# File lib/gorillib/collection.rb, line 134
def []=(label, item)
  add(item, label)
end
add(item, label=nil) click to toggle source

Adds an item in-place. Items added to the collection (via ‘add`, `[]=`, `initialize`, etc) all pass through the `add` method: you should override this in subclasses to add any gatekeeper behavior.

If no label is supplied, we use the result of invoking ‘key_method` on the item (or raise an error if no label and no key_method).

It’s up to you to ensure that labels make sense; this method doesn’t demand the item’s key_method match its label.

@return [Object] the item

# File lib/gorillib/collection.rb, line 94
def add(item, label=nil)
  label ||= label_for(item)
  @clxn[label] = item
end
each(&block) click to toggle source

iterate over each value in the collection

# File lib/gorillib/collection.rb, line 124
def each(&block); each_value(&block) ; end
inspect() click to toggle source

@return [String] string describing the collection’s array representation

# File lib/gorillib/collection.rb, line 192
def inspect
  key_width = [keys.map{|key| key.to_s.length + 1 }.max.to_i, 45].min
  guts = clxn.map{|key, val| "%-#{key_width}s %s" % ["#{key}:", val.inspect] }.join(",\n   ")
  ['c{ ', guts, ' }'].join
end
inspect_compact() click to toggle source
# File lib/gorillib/collection.rb, line 198
def inspect_compact
  ['c{ ', keys.join(", "), ' }'].join
end
label_for(item) click to toggle source
# File lib/gorillib/collection.rb, line 99
def label_for(item)
  if key_method.nil? then
    raise ArgumentError, "Can't add things to a #{self.class} without some sort of label: use foo[label] = obj, or set the collection's key_method" ;
  end
  item.public_send(key_method)
end
receive!(other) click to toggle source

Receive items in-place, replacing any existing item with that label.

Individual items are added using receive_item – if you’d like to perform any conversion or modification to items, do it there

@param other [{Symbol => Object}, Array<Object>] a hash of key=>item pairs or a list of items @return [Gorillib::Collection] the collection

# File lib/gorillib/collection.rb, line 145
def receive!(other)
  if other.respond_to?(:each_pair)
    other.each_pair{|label, item| receive_item(label, item) }
  elsif other.respond_to?(:each)
    other.each{|item|             receive_item(nil,   item) }
  else
    raise "A collection can only receive something that is enumerable: got #{other.inspect}"
  end
  self
end
receive_item(label, item) click to toggle source

items arriving from the outside world should pass through receive_item, not directly to add.

# File lib/gorillib/collection.rb, line 158
def receive_item(label, item)
  add(item, label)
end
to_a() click to toggle source

@return [Array] an array holding the items

# File lib/gorillib/collection.rb, line 119
def to_a    ; values    ; end
to_hash() click to toggle source

@return [{Symbol => Object}] a hash of key=>item pairs

# File lib/gorillib/collection.rb, line 121
def to_hash ; clxn.dup  ; end
to_s() click to toggle source

@return [String] string describing the collection’s array representation

# File lib/gorillib/collection.rb, line 190
def to_s           ; to_a.to_s           ; end