lib/eco/language/models/collection.rb in eco-helpers-1.5.1 vs lib/eco/language/models/collection.rb in eco-helpers-1.5.2
- old
+ new
@@ -2,23 +2,23 @@
module Language
module Models
class Collection
include Enumerable
- ATTR_PRESENCE_METHODS = ["present", "empty", "present_all?", "present_some?"]
- ATTR_COLLECTION_METHODS = ["exclude", "remove", "attr", "attr?", "attrs", "unique_attrs", "contains"] + ATTR_PRESENCE_METHODS
+ BASIC_METHODS = ["present", "empty", "present_all?", "present_some?"]
+ EXTENDED_METHODS = BASIC_METHODS + ["exclude", "remove", "attr", "attr?", "attrs", "unique_attrs", "contains"]
class << self
- def attr_collection (*attrs)
+ def attr_presence(*attrs)
block = ->(method) { attrs_create_method(attrs, method) }
- ATTR_COLLECTION_METHODS.each(&block)
+ BASIC_METHODS.each(&block)
end
- def attr_presence (*attrs)
+ def attr_collection(*attrs)
block = ->(method) { attrs_create_method(attrs, method) }
- ATTR_PRESENCE_METHODS.each(&block)
+ EXTENDED_METHODS.each(&block)
end
def attrs_create_method(attrs, method)
attrs.each do |attr|
attr = attr.to_s
@@ -33,46 +33,45 @@
end
end
end
- #attr_reader :items
-
def initialize(data = [], klass:, factory: nil, handy: Eco::Assets::Language.new)
raise "Raise klass required, given: #{klass}" if !klass
@klass = klass
@factory = factory
@handy = handy
@items = to_klass(data)
end
+ # @!group pure collection methods
+ def to_c
+ Collection.new(self, klass: @klass, factory: @factory)
+ end
+
+ def new
+ newFrom to_a
+ end
+
def newFrom(data)
self.class.new(data, klass: @klass, factory: @factory)
end
def merge(data)
data = data.to_a unless data.is_a?(Array)
newFrom to_a + data
end
- def to_c
- Collection.new(self, klass: @klass, factory: @factory)
- end
-
- def new
- self.class.new(to_a, klass: @klass, factory: @factory)
- end
-
def length
count
end
def empty?
count == 0
end
- def each(params: {}, &block)
+ def each(&block)
return to_enum(:each) unless block
@items.each(&block)
end
def <(value)
@@ -91,51 +90,61 @@
end
def delete!(value)
self < @items - into_a(value)
end
+ # @!endgroup
- # attr dependant methods
- def exclude(attr, value, modifier = Language::MatchModifier.new)
+ # @!group `attr` dependant methods
+ def exclude(attr, value, modifier = default_modifier)
newFrom @items - self.attr(attr, value, modifier)
end
- def remove(attr, value, modifier = Language::MatchModifier.new)
+ def remove(attr, value, modifier = default_modifier)
self < exclude(attr, value, modifier)
end
- def attr(attr, value = true, modifier = Language::MatchModifier.new)
- if !!value == value # boolean?
- present(attr, value)
- else
- return newFrom select { |object|
- attr_val = fetch_attr(object, attr)
- match?(attr_val, value, modifier)
- }
+ def attr(attr, value = true, modifier = default_modifier)
+ return present(attr, value) if boolean?(value)
+ select do |object|
+ match?(attr_value(object, attr), value, modifier)
+ end.yield_self do |matching|
+ newFrom matching
end
end
- def attr?(attr, value = true, modifier = Language::MatchModifier.new)
- modifier = modifier.new.reverse
- if !!value == value # boolean?
- present(attr, value).length == length
- else
- obj_vals = attrs(attr)
- return match?(obj_vals, value, modifier)
- end
+ def attr?(attr, value = true, modifier = default_modifier)
+ return present(attr, value).length == length if boolean?(value)
+ match?(attrs(attr), value, modifier.new.reverse)
end
+ def contains(attr, value, modifier = default_modifier)
+ self.attr(attr, value, modifier.new.pattern)
+ end
+
def attrs(attr)
- map { |object| fetch_attr(object, attr) }
+ map { |object| attr_value(object, attr) }
end
def unique_attrs(attr)
to_h(attr).keys
end
+ def group_by(attr = nil, &block)
+ return to_h(attr) if attr
+ to_a.group_by(&block) if block
+ end
+
+ def to_h(attr)
+ return {} if !attr
+ to_a.group_by { |object| object.method(attr).call }
+ end
+ # @!endgroup
+
+ # @!group `attr` presence methods
def present(attr, flag = true)
- block = ->(o) { !!fetch_attr(o, attr) == !!flag }
+ block = ->(o) { attr_value_present?(o, attr) == !!flag }
newFrom select(&block)
end
def empty(attr, flag = true)
present(attr, !flag)
@@ -146,50 +155,62 @@
end
def present_some?(attr, flag = true)
present(attr, flag).length > 0
end
+ # @!endgroup
- def contains(attr, value, modifier = Language::MatchModifier.new)
- modifier = modifier.new.pattern
- self.attr(attr, value, modifier)
- end
-
- def group_by(attr = nil, &block)
- return to_h(attr) if attr
- to_a.group_by(&block) if block
- end
-
- def to_h(attr)
- return {} if !attr
- to_a.group_by { |object| object.method(attr).call }
- end
-
protected
def on_change
# function to be overriden by children classes
end
def into_a(value)
- value = [].push(value) unless value.is_a?(Enumerable)
+ value = [].push(value) if value.is_a?(Hash) || !value.is_a?(Enumerable)
value.to_a
end
private
+ def attr_value(obj, attr)
+ return nil unless obj && attr
+ case
+ when obj.is_a?(Hash)
+ obj[attr]
+ when obj.respond_to?(attr.to_sym)
+ obj.send(attr)
+ end
+ end
+
+ def attr_value_present?(obj, attr)
+ return false unless value = attr_value(obj, attr)
+ case
+ when value.is_a?(Enumerable)
+ value.count > 1
+ when value.is_a?(String)
+ !value.strip.empty?
+ else
+ !!value
+ end
+ end
+
def match?(*args)
@handy.match?(*args)
end
def to_klass(list)
into_a(list).map do |v|
v.is_a?(@klass) ? v : @factory&.new(v) || @klass.new(v)
end
end
- def fetch_attr(object,attr)
- object.method(attr).call
+ def default_modifier
+ Language::MatchModifier.new
+ end
+
+ def boolean?(value)
+ value == !!value
end
end
end
end