Class: Ecoportal::API::Common::Content::CollectionModel

Inherits:
DoubleModel
  • Object
show all
Includes:
Enumerable
Defined in:
lib/ecoportal/api/common/content/collection_model.rb

Constant Summary

Constants inherited from DoubleModel

DoubleModel::NOT_USED

Constants included from ClassHelpers

Ecoportal::API::Common::Content::ClassHelpers::NOT_USED

Class Attribute Summary collapse

Attributes inherited from DoubleModel

#_key, #_parent

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from DoubleModel

#as_json, #as_update, #consolidate!, #dirty?, #doc, embeds_multiple, embeds_one, #key, #key=, key?, new_uuid, #original_doc, pass_reader, pass_writer, passarray, passdate, passkey, passthrough, #pretty_print, #replace_doc, #reset!, #root, #to_json

Methods included from ClassHelpers

#instance_variable_name, #new_class, #resolve_class, #to_constant, #to_time, #used_param?

Constructor Details

#initialize(ini_doc = [], parent: self, key: nil) ⇒ CollectionModel

Returns a new instance of CollectionModel.



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/ecoportal/api/common/content/collection_model.rb', line 87

def initialize(ini_doc = [], parent: self, key: nil)
  unless self.class.klass?
    raise "Undefined base 'klass' or 'new_item' callback for #{self.class}"
  end

  ini_doc = case ini_doc
            when Array
              ini_doc
            when Enumerable
              ini_doc.to_a
            else
              []
            end

  super(ini_doc, parent: parent, key: key)
end

Class Attribute Details

.klass(value = NOT_USED) {|doc| ... } ⇒ Klass

Note:
  • use block to define klass callback

Resolves to the nuclear Class of the elements

Parameters:

  • value (Hash) (defaults to: NOT_USED)

    base doc (raw object) to create the object with

Yields:

  • (doc)

    identifies the target class of the raw object

Yield Parameters:

  • doc (Hash)

Yield Returns:

  • (Klass)

    the target class

Returns:

  • (Klass)

    the target class



27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/ecoportal/api/common/content/collection_model.rb', line 27

def klass(value = NOT_USED, &block)
  if block
    @klass = block
    block.call(value) if value != NOT_USED
  elsif used_param?(value)
    if @klass.is_a?(Proc)
      @klass.call(value)
    else
      resolve_class(@klass, exception: false)
    end
  else
    resolve_class(@klass, exception: false)
  end
end

.order_keyObject

Returns the value of attribute order_key.



9
10
11
# File 'lib/ecoportal/api/common/content/collection_model.rb', line 9

def order_key
  @order_key
end

.order_mattersObject

Returns the value of attribute order_matters.



9
10
11
# File 'lib/ecoportal/api/common/content/collection_model.rb', line 9

def order_matters
  @order_matters
end

Class Method Details

.doc_class(name) ⇒ Object



76
77
78
79
80
81
# File 'lib/ecoportal/api/common/content/collection_model.rb', line 76

def doc_class(name)
  dim_class = new_class(name, inherits: Common::Content::ArrayModel) do |klass|
    klass.order_matters = order_matters
    klass.uniq          = uniq
  end
end

.items_keyObject



11
12
13
# File 'lib/ecoportal/api/common/content/collection_model.rb', line 11

def items_key
  @items_key ||= "id"
end

.items_key=(value) ⇒ Object



15
16
17
# File 'lib/ecoportal/api/common/content/collection_model.rb', line 15

def items_key=(value)
  @items_key = value && value.to_s.freeze
end

.klass?Boolean

Returns are there the factory logics to build item objects defined?.

Returns:

  • (Boolean)

    are there the factory logics to build item objects defined?



72
73
74
# File 'lib/ecoportal/api/common/content/collection_model.rb', line 72

def klass?
  @klass || @new_item
end

.new_item(doc = NOT_USED, parent: nil, key: nil) {|doc, parent, key| ... } ⇒ Klass

Note:
  • use block to define new_item callback, which will prevail over klass
  • if new_item callback was not defined, it is required to defnie klass
Note:

if block is given, it ignores doc

Generates a new object of the target class

Parameters:

  • doc (Hash) (defaults to: NOT_USED)

    doc to parse

Yields:

  • (doc, parent, key)

    creates an object instance of the target klass

Yield Parameters:

  • doc (Hash)

Yield Returns:

  • (Klass)

    instance object of the target klass

Returns:

  • (Klass)

    instance object of the target klass



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/ecoportal/api/common/content/collection_model.rb', line 52

def new_item(doc = NOT_USED, parent: nil, key: nil, &block)
  if block
    @new_item = block
  elsif used_param?(doc)
    raise "You should define either a 'klass' or a 'new_item' callback first" unless klass?
    if @new_item
      @new_item.call(doc, parent, key)
    else
      if target_class = self.klass(doc)
        doc.is_a?(target_class) ? doc : target_class.new(doc, parent: parent, key: key)
      else
        raise "Could not find a class for: #{doc}"
      end
    end
  else
    raise "To define the 'new_item' callback (factory), you need to use a block"
  end
end

Instance Method Details

#[](value) ⇒ Object

Get an element usign the key.



138
139
140
# File 'lib/ecoportal/api/common/content/collection_model.rb', line 138

def [](value)
  items_by_key[get_key(value)]
end

#_doc_key(value) ⇒ Object

Transforms value into the actual key to access the object in the doc Array



105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/ecoportal/api/common/content/collection_model.rb', line 105

def _doc_key(value)
  #print "*(#{value.class})"
  return super(value) unless value.is_a?(Hash) || value.is_a?(Content::DoubleModel)
  if id = get_key(value)
    #print "^"
    _doc_items.index {|item| get_key(item) == id}.tap do |p|
      #print "{{#{p}}}"
    end
  else
    raise UnlinkedModel.new("Can't find child: #{value}")
  end
end

#_itemsObject



127
128
129
130
131
132
133
134
135
# File 'lib/ecoportal/api/common/content/collection_model.rb', line 127

def _items
  return @_items if @_items
  [].tap do |elements|
    variable_set(:@_items, elements)
    _doc_items.each do |item_doc|
      elements << new_item(item_doc)
    end
  end
end

#delete!(value) ⇒ Object



165
166
167
168
169
170
171
172
# File 'lib/ecoportal/api/common/content/collection_model.rb', line 165

def delete!(value)
  unless value.is_a?(Hash) || value.is_a?(Content::DoubleModel)
    raise "'Content::DoubleModel' or 'Hash' doc required"
  end
  if item = self[value]
    _doc_delete(item.doc)
  end
end

#each(&block) ⇒ Object



122
123
124
125
# File 'lib/ecoportal/api/common/content/collection_model.rb', line 122

def each(&block)
  return to_enum(:each) unless block
  _items.each(&block)
end

#empty?Boolean

Returns:

  • (Boolean)


119
# File 'lib/ecoportal/api/common/content/collection_model.rb', line 119

def empty?;   count == 0; end

#lengthObject



118
# File 'lib/ecoportal/api/common/content/collection_model.rb', line 118

def length;   count;      end

#present?Boolean

Returns:

  • (Boolean)


120
# File 'lib/ecoportal/api/common/content/collection_model.rb', line 120

def present?; count > 0;  end

#upsert!(value, pos: NOT_USED, before: NOT_USED, after: NOT_USED) ⇒ Object

Tries to find the element value, if it exists, it updates it Otherwise it pushes it to the end

Returns:

  • the element



149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/ecoportal/api/common/content/collection_model.rb', line 149

def upsert!(value, pos: NOT_USED, before: NOT_USED, after: NOT_USED)
  unless value.is_a?(Hash) || value.is_a?(Content::DoubleModel)
    raise "'Content::DoubleModel' or 'Hash' doc required"
  end
  item_doc = value.is_a?(Content::DoubleModel)? value.doc : value
  item_doc = JSON.parse(item_doc.to_json)
  if item = self[value]
    item.replace_doc(item_doc)
  else
    _doc_upsert(item_doc, pos: pos, before: before, after: after)
  end
  (item || self[item_doc]).tap do |item|
    yield(item) if block_given?
  end
end

#values_at(*keys) ⇒ Object



142
143
144
# File 'lib/ecoportal/api/common/content/collection_model.rb', line 142

def values_at(*keys)
  keys.map {|key| self[key]}
end