lib/ecoportal/api/common/content/array_model.rb in ecoportal-api-v2-1.1.7 vs lib/ecoportal/api/common/content/array_model.rb in ecoportal-api-v2-1.1.8

- old
+ new

@@ -5,17 +5,13 @@ # Class to handle a plain Array embedded in a Hashed model. # @note # - Its purpose is to handle an Array of basic objects (i.e. `Date`, `String`, `Number`) class ArrayModel < Content::DoubleModel class TypeMismatchedComparison < StandardError - def initialize (this: nil, that: msg = "Trying to compare objects with different behavior.") - if this - msg += " From object with 'order_matters: #{this.order_matters?}' and 'uniq: #{this.uniq?}'." - end - if that - msg += " To object where 'order_matters: #{that.order_matters?}' and 'uniq: #{that.uniq?}'." - end + def initialize(this: nil, that: msg = "Trying to compare objects with different behavior.") + msg += " From object with 'order_matters: #{this.order_matters?}' and 'uniq: #{this.uniq?}'." if this + msg += " To object where 'order_matters: #{that.order_matters?}' and 'uniq: #{that.uniq?}'." if that super(msg) end end include Enumerable @@ -25,28 +21,42 @@ # @param a [ArrayModel] # @param b [ArrayModel] # @return [Boolean] `true` if both elements have same behaviour def same_type?(a, b) - raise "To use this comparison both objects should be `ArrayModel`" unless a.is_a?(ArrayModel) && b.is_a?(ArrayModel) + msg = "To use this comparison both objects should be `ArrayModel`" + raise msg unless a.is_a?(ArrayModel) && b.is_a?(ArrayModel) (a.order_matters? == b.order_matters?) && (a.uniq? == b.uniq?) end end inheritable_class_vars :order_matteres, :uniq def initialize(doc = [], parent: self, key: nil, read_only: self.class.read_only?) super(doc, parent: parent, key: key, read_only: read_only) end - def order_matters?; self.class.order_matters; end - def uniq?; self.class.uniq; end + def order_matters? + self.class.order_matters + end - def length; count; end - def empty?; count == 0; end - def present?; count > 0; end + def uniq? + self.class.uniq + end + def length + count + end + + def empty? + count&.zero? + end + + def present? + count&.positive? + end + def each(&block) return to_enum(:each) unless block _items.each(&block) end @@ -64,14 +74,14 @@ # @return [Array] a **copy** of the `Array` elements def to_a _items.slice(0..-1) end - # @param value [Object, Array<Object>, ArrayModel] the value(s) of the new object + # @param other [Object, Array<Object>, ArrayModel] the value(s) of the new object # @return [ArrayModel] a new object with the current class - def new_from(value) - self.class.new(into_a(value)) + def new_from(other) + self.class.new(into_a(other)) end # @return [ArrayModel] a copy of the current object def dup new_from(to_a) @@ -91,32 +101,32 @@ # Sets the element of a certain position # @param pos [Integer] the position of the element # @param value [String, Date, Number] the element # @return [Date, String, Number] - def []=(post, value) + def []=(pos, value) _items[pos] = value on_change self[pos] end # Compares with an `Array` or another `ArrayModel` - # @param a [ArrayModel, Array] - def ==(a) - return true if self.equal?(a) - return false unless (a.class == self.class) || a.is_a?(Array) - case a + # @param other [ArrayModel, Array] + def ==(other) + return true if equal?(other) + return false unless (other.class == self.class) || other.is_a?(Array) + + case other when Array - self == new_from(a) + self == new_from(other) when ArrayModel - return true if - raise TypeMismatchedComparison.new(this: self, that: a) unless self.class.same_type?(self, a) + raise TypeMismatchedComparison.new(this: self, that: other) unless self.class.same_type?(self, other) - if self.order_matters? - _items == a.to_a + if order_matters? + _items == other.to_a else - (_items - a.to_a).empty? && (a.to_a - _items).empty? + (_items - other.to_a).empty? && (other.to_a - _items).empty? end end end # @return [Boolean] `true` if `value` is present, `false` otherwise @@ -152,109 +162,106 @@ def concat!(values) self << values end # Resets the `Array` by keeping its reference and adds the value(s) - # @param value [Object, Array<Object>, ArrayModel] the value(s) to be added - # @param values [Array] - def <(values) + # @param other [Object, Array<Object>, ArrayModel] the value(s) to be added + def <(other) _items.clear - self << values + self << other end # Clears the `Array` keeping its reference def clear! _items.clear on_change self end # Concat to new - def +(value) - new_from(self.to_a + into_a(value)) + def +(other) + new_from(to_a + into_a(other)) end # Join - # @param value [Object, Array<Object>, ArrayModel] the value(s) to be joined + # @param other [Object, Array<Object>, ArrayModel] the value(s) to be joined # @return [ArrayModel] a new object instance with the intersection done - def |(value) - new = new_from(value) - self - new_from(to_a + new.to_a) + def |(other) + oth = new_from(other) - self + new_from(to_a + oth.to_a) end # Intersect - # @param value [Object, Array<Object>, ArrayModel] the value(s) to be deleted + # @param other [Object, Array<Object>, ArrayModel] the value(s) to be deleted # @return [ArrayModel] a new object instance with the intersection done - def &(value) - self.dup.tap do |out| - self.dup.tap do |delta| - delta.delete!(*into_a(value)) + def &(other) + dup.tap do |out| + dup.tap do |delta| + delta.delete!(*into_a(other)) out.delete!(*into_a(delta)) end end end # Subtract # @param value [Object, Array<Object>, ArrayModel] the value(s) to be deleted # @return [ArrayModel] a **copy** of the object with the elements subtracted - def -(value) - self.dup.tap do |copy| - copy.delete!(*into_a(value)) + def -(other) + dup.tap do |copy| + copy.delete!(*into_a(other)) end end # Deletes `values` from the `Array` def delete!(*values) values.map do |v| deletion!(v) - end.tap do |r| + end.tap do |_r| on_change end end # Swaps two values' positions # @note this will work with first instances when **not** `uniq?` # @param val1 [Object] the first value to swap # @param val2 [Object] the second value to swap # @return [Integer] the new of `value1`, `nil` if it wasn't moved - def swap(value1, value2) - index(value2).tap do |dest| - if dest && pos = index(value1) - _items[dest] = value1 - _items[pos] = value2 + def swap(val_1, val_2) + index(val_2).tap do |dest| + if dest && (pos = index(val_1)) + _items[dest] = val_1 + _items[pos] = val_2 end end end def insert_one(value, pos: NOT_USED, before: NOT_USED, after: NOT_USED) - i = index(value) - return i if (i && uniq?) - pos = case - when used_param?(pos) && pos - pos - when used_param?(before) && before - index(before) - when used_param?(after) && after - if i = index(after) then i + 1 end - end + idx = index(value) + return idx if idx && uniq? + pos = + if used_param?(pos) && pos + pos + elsif used_param?(before) && before + index(before) + elsif used_param?(after) && after + if (idx = index(after)) then idx + 1 end + end + + # use last position as default pos ||= length - pos.tap do |i| + pos.tap do |_i| _items.insert(pos, value) on_change end end # TODO - def move(value, pos: NOT_USED, before: NOT_USED, after: NOT_USED) - if i = index(value) - unless i == pos - - on_change - end - pos - end + def move(value, pos: NOT_USED, _before: NOT_USED, _after: NOT_USED) + return unless (idx = index(value)) + on_change unless idx == pos + pos end protected def on_change @@ -268,16 +275,12 @@ return value.to_a.slice(0..-1) if value.is_a?(Enumerable) [].push(value).compact end def deletion!(value) - if !uniq? - if i = _items.index(value) - _items.slice!(i) - end - else - _items.delete(value) - end + return _items.delete(value) if uniq? + return unless (idx = _items.index(value)) + _items.slice!(idx) end end end end end