Class: Ecoportal::API::Common::Content::CollectionModel
- Inherits:
-
DoubleModel
- Object
- BaseModel
- DoubleModel
- Ecoportal::API::Common::Content::CollectionModel
- Includes:
- Enumerable
- Defined in:
- lib/ecoportal/api/common/content/collection_model.rb
Overview
to be able to refer to the correct element of the Collection,
it is required that those elements have a unique key
that allows to identify them
CollectionModel aims to deal with Arrays of actual objects.
Direct Known Subclasses
V2::Page::Component::SelectionOptions, V2::Page::Components, V2::Page::Force::Bindings, V2::Page::Forces, V2::Page::Sections, V2::Page::Stages, V2::Pages::PageStage::Tasks
Constant Summary
Constants inherited from DoubleModel
Constants included from ClassHelpers
Ecoportal::API::Common::Content::ClassHelpers::NOT_USED
Class Attribute Summary collapse
-
.klass(value = NOT_USED) {|doc| ... } ⇒ Class, ...
Resolves to the nuclear
Class
of the elements. -
.order_key ⇒ Object
Returns the value of attribute order_key.
-
.order_matters ⇒ Object
Returns the value of attribute order_matters.
Attributes inherited from DoubleModel
Class Method Summary collapse
-
.items_key ⇒ Object
The attr that has been defined as
passkey
in the item class. - .items_key=(value) ⇒ Object
-
.klass? ⇒ Boolean
Are there the factory logics to build item objects defined?.
-
.new_item(doc = NOT_USED, parent: nil, key: nil, read_only: false) {|doc, parent, key| ... } ⇒ Klass
Generates a new object of the target class.
-
.new_item_class_based? ⇒ Boolean
Optimization.
Instance Method Summary collapse
-
#[](value) ⇒ Object
Get an element usign the
key
. -
#_doc_key(value) ⇒ Object
Transforms
value
into the actualkey
to access the object in the docArray
. - #_doc_pos(value) ⇒ Object
- #_items ⇒ Object
-
#clear ⇒ Object
Deletes all the elements of this
CollectionModel
instance. -
#delete!(value) ⇒ Object
Deletes
value
from thisCollectionModel
instance. - #each(&block) ⇒ Object
- #empty? ⇒ Boolean
-
#include?(value) ⇒ Boolean
Checks if an element exists in the collection.
-
#initialize(ini_doc = [], parent: self, key: nil, read_only: false) ⇒ CollectionModel
constructor
A new instance of CollectionModel.
-
#items_class ⇒ Class
The class of the elements of the Collection.
- #length ⇒ Object
- #present? ⇒ Boolean
-
#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. -
#values_at(*keys) ⇒ Array<Object>
The
items_class
element object.
Methods inherited from DoubleModel
#as_json, #as_update, #consolidate!, #dirty?, #doc, embeds_many, embeds_one, enforce!, #key, #key=, key?, new_uuid, #original_doc, pass_reader, pass_writer, passarray, passboolean, passdate, passforced, passkey, passthrough, #print_pretty, read_only!, read_only?, #read_only?, #replace_doc, #reset!, #resolved_doc_key, #root, #to_json
Methods included from ClassHelpers
#inheritable_attrs, #inheritable_class_vars, #inherited, #instance_variable_name, #new_class, #resolve_class, #to_constant, #to_time, #uid, #used_param?
Constructor Details
#initialize(ini_doc = [], parent: self, key: nil, read_only: false) ⇒ CollectionModel
Returns a new instance of CollectionModel.
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
# File 'lib/ecoportal/api/common/content/collection_model.rb', line 106 def initialize(ini_doc = [], parent: self, key: nil, read_only: false) msg = "Undefined base 'klass' or 'new_item' callback for #{self.class}" raise msg unless self.class.klass? ini_doc = case ini_doc when Array ini_doc when Enumerable ini_doc.to_a else [] end super(ini_doc, parent: parent, key: key, read_only: read_only) end |
Class Attribute Details
.klass(value = NOT_USED) {|doc| ... } ⇒ Class, ...
- use block to define
klass
callback
When klass
is resolved, if the items are of type
DoubleModel
, it sets on the collection class the items_key
when klass
is directly resolved (not via doc) only once
it will set @klass as resolved and will use this class from now on.
This is an optimization to cut class lookups
Resolves to the nuclear Class
of the elements
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/ecoportal/api/common/content/collection_model.rb', line 39 def klass(value = NOT_USED, &block) @klass = block if block_given? if @klass.is_a?(Proc) && used_param?(value) @klass.call(value) elsif @klass && !@klass.is_a?(Proc) && !@klass.is_a?(Class) @klass = resolve_class(@klass, exception: false) @klass else @klass end.tap do |result| next unless result.is_a?(Class) next unless result < Ecoportal::API::Common::Content::DoubleModel self.items_key = result.key end end |
.order_key ⇒ Object
Returns the value of attribute order_key.
11 12 13 |
# File 'lib/ecoportal/api/common/content/collection_model.rb', line 11 def order_key @order_key end |
.order_matters ⇒ Object
Returns the value of attribute order_matters.
11 12 13 |
# File 'lib/ecoportal/api/common/content/collection_model.rb', line 11 def order_matters @order_matters end |
Class Method Details
.items_key ⇒ Object
The attr that has been defined as passkey
in the item class
15 16 17 |
# File 'lib/ecoportal/api/common/content/collection_model.rb', line 15 def items_key @items_key ||= "id" end |
.items_key=(value) ⇒ Object
19 20 21 |
# File 'lib/ecoportal/api/common/content/collection_model.rb', line 19 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?.
57 58 59 |
# File 'lib/ecoportal/api/common/content/collection_model.rb', line 57 def klass? @klass || @new_item end |
.new_item(doc = NOT_USED, parent: nil, key: nil, read_only: false) {|doc, parent, key| ... } ⇒ Klass
- use block to define
new_item
callback, which will prevail overklass
- if
new_item
callback was not defined, it is required to defnieklass
if block is given, it ignores doc
Generates a new object of the target class
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
# File 'lib/ecoportal/api/common/content/collection_model.rb', line 83 def new_item(doc = NOT_USED, parent: nil, key: nil, read_only: false, &block) if block_given? @new_item = block return end msg = "To define the 'new_item' callback (factory), you need to use a block" raise msg unless used_param?(doc) msg = "You should define either a 'klass' or a 'new_item' callback first" raise msg unless klass? return @new_item.call(doc, parent, key) if @new_item.is_a?(Proc) raise "Could not find a class for: #{doc}" unless (target_class = klass(doc)) return doc if doc.is_a?(target_class) target_class.new(doc, parent: parent, key: key, read_only: read_only) end |
.new_item_class_based? ⇒ Boolean
Optimization
62 63 64 65 66 67 |
# File 'lib/ecoportal/api/common/content/collection_model.rb', line 62 def new_item_class_based? return false if @new_item.is_a?(Proc) return false if klass.is_a?(Proc) return true if klass.is_a?(Class) false end |
Instance Method Details
#[](value) ⇒ Object
Get an element usign the key
.
190 191 192 |
# File 'lib/ecoportal/api/common/content/collection_model.rb', line 190 def [](value) items_by_key[get_key(value)] end |
#_doc_key(value) ⇒ Object
- The name of the method is after the paren't class method
- This method would have been better called
_doc_pos
:)
Transforms value
into the actual key
to access the object in the doc Array
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 |
# File 'lib/ecoportal/api/common/content/collection_model.rb', line 136 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 show_str = case value when Hash value.pretty_inspect when Content::DoubleModel "#{value} with key: #{value.class.key} (items_key: #{self.class.items_key})" else value end raise UnlinkedModel, "Can't find child: #{show_str}" end end |
#_doc_pos(value) ⇒ Object
128 129 130 |
# File 'lib/ecoportal/api/common/content/collection_model.rb', line 128 def _doc_pos(value) _doc_key(value) end |
#_items ⇒ Object
176 177 178 179 180 181 182 183 184 185 |
# File 'lib/ecoportal/api/common/content/collection_model.rb', line 176 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 @_items = elements if read_only? end end |
#clear ⇒ Object
Deletes all the elements of this CollectionModel
instance
230 231 232 |
# File 'lib/ecoportal/api/common/content/collection_model.rb', line 230 def clear to_a.each {|item| delete!(item)} end |
#delete!(value) ⇒ Object
Deletes value
from this CollectionModel
instance
239 240 241 242 243 244 245 246 247 |
# File 'lib/ecoportal/api/common/content/collection_model.rb', line 239 def delete!(value) unless value.is_a?(Hash) || value.is_a?(Content::DoubleModel) || value.is_a?(String) raise "'Content::DoubleModel' or 'Hash' doc required" end return unless (item = self[value]) _doc_delete(item.doc) @indexed = false _items.delete(item) end |
#each(&block) ⇒ Object
171 172 173 174 |
# File 'lib/ecoportal/api/common/content/collection_model.rb', line 171 def each(&block) return to_enum(:each) unless block _items.each(&block) end |
#empty? ⇒ Boolean
163 164 165 |
# File 'lib/ecoportal/api/common/content/collection_model.rb', line 163 def empty? count&.zero? end |
#include?(value) ⇒ Boolean
Checks if an element exists in the collection
197 198 199 |
# File 'lib/ecoportal/api/common/content/collection_model.rb', line 197 def include?(value) items_by_key.key?(get_key(value)) end |
#items_class ⇒ Class
Returns the class of the elements of the Collection.
124 125 126 |
# File 'lib/ecoportal/api/common/content/collection_model.rb', line 124 def items_class self.class.klass end |
#length ⇒ Object
159 160 161 |
# File 'lib/ecoportal/api/common/content/collection_model.rb', line 159 def length count end |
#present? ⇒ Boolean
167 168 169 |
# File 'lib/ecoportal/api/common/content/collection_model.rb', line 167 def present? count&.positive? 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
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 |
# File 'lib/ecoportal/api/common/content/collection_model.rb', line 210 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. Given #{value.class}" 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).tap do |pos_idx| _items.insert(pos_idx, new_item(item_doc)) @indexed = false end end (item || self[item_doc]).tap do |itm| yield(itm) if block_given? end end |
#values_at(*keys) ⇒ Array<Object>
Returns the items_class
element object.
202 203 204 |
# File 'lib/ecoportal/api/common/content/collection_model.rb', line 202 def values_at(*keys) keys.map {|key| self[key]} end |