Class: UberArray

Inherits:
Object
  • Object
show all
Defined in:
lib/uber_array.rb,
lib/uber_array/version.rb

Constant Summary collapse

VERSION =
'0.1.0'

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(array = [], options = {}) ⇒ UberArray

Returns a new instance of UberArray.

Parameters:

  • array (Array<Hash|Object>) (defaults to: [])

    underlying array

  • options (Hash) (defaults to: {})

    init options

Options Hash (options):

  • :primary_key (String|Symbol)

    Name of primary key or attribute attribute/method names are specified as symbols like :__name__



8
9
10
11
# File 'lib/uber_array.rb', line 8

def initialize(array = [], options = {})
  @array = array || []
  @primary_key = options[:primary_key] || 'name'
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *args, &block) ⇒ Object

delegate all methods to the inner @array, if the result is an Array with elements of the same type as @array - convert it to UberArray



20
21
22
23
24
25
26
27
28
# File 'lib/uber_array.rb', line 20

def method_missing(method, *args, &block)
  klass = @array.first.class
  result = @array.send(method, *args, &block)
  if result.is_a?(Array)
    @array.empty? || result.empty? || result.first.class == klass ? UberArray.new(result, uberopts) : result
  else
    result
  end
end

Instance Attribute Details

#arrayObject

Returns the value of attribute array.



2
3
4
# File 'lib/uber_array.rb', line 2

def array
  @array
end

#primary_keyObject

Returns the value of attribute primary_key.



2
3
4
# File 'lib/uber_array.rb', line 2

def primary_key
  @primary_key
end

Instance Method Details

#[](key) ⇒ Object

use a non-number as access key into @array with elements responding to a key or attribute name specified by @primary_key



119
120
121
122
123
124
125
126
127
128
129
# File 'lib/uber_array.rb', line 119

def [](key)
  return @array[key] if key.is_a?(Fixnum)
  method = method_name?(primary_key)
  @array.find do |item|
    if method
      item.respond_to?(method) && item.send(method) == key
    else
      item.respond_to?(:[]) && item[primary_key] == key
    end
  end
end

#filter_proc(opts = {}) ⇒ Object

build a Proc by which to filter items in @array



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/uber_array.rb', line 37

def filter_proc(opts = {})
  fail ArgumentError, 'Hash argument expected' unless opts.is_a?(Hash)

  if opts.empty?
    -> { false }
  else
    lambda do |item|
      opts.map do |key, val|
        can_respond, ival = item_send_if_respond_to?(item, key)
        can_respond &&
        case val
        # :key => ->(v){v > 12}
        when Proc
          val.call(ival)
        # :key => /text/
        when Regexp
          ival =~ val
        # :key => 1..4, :key => [1,2,3,4]
        when Array, Range
          val.to_a.include?(ival)
        # :key => false|true, :key => 'text', :key => 10
        else
          ival == val
        end
      end.all?
    end
  end
end

#item_respond_to?(item, key) ⇒ Boolean

check if item responds to a given key/attribute name

Returns:

  • (Boolean)


73
74
75
76
# File 'lib/uber_array.rb', line 73

def item_respond_to?(item, key)
  method = method_name?(key) || :[]
  item.respond_to?(method)
end

#item_send(item, key) ⇒ Object

invoke the given key/attribute name as a method on item



79
80
81
82
# File 'lib/uber_array.rb', line 79

def item_send(item, key)
  method = method_name?(key)
  method ? item.send(method) : item[key]
end

#item_send_if_respond_to?(item, key) ⇒ Boolean

send a key/method name to an item if the item responds to it

Parameters:

  • item (Hash|Object)

    item of @array

  • key (String|Symbol)

    key name

Returns:

  • (Boolean)


87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/uber_array.rb', line 87

def item_send_if_respond_to?(item, key)
  can_respond, result = nil, nil
  method = method_name?(key)
  if method
    can_respond = item.respond_to?(method)
    result = item.send(method) if can_respond
  else
    can_respond = item.respond_to?(:[])
    result = item[key] if can_respond
  end
  [can_respond, result]
end

#like(regex) ⇒ Object

filter items by regex matching on @primary_key



112
113
114
115
# File 'lib/uber_array.rb', line 112

def like(regex)
  exp = regex.is_a?(String) ? Regexp.new(regex, true) : regex
  where(primary_key => exp)
end

#map_by(key) ⇒ Object

Parameters:

  • key (String|Symbol)

    key name to map by



31
32
33
# File 'lib/uber_array.rb', line 31

def map_by(key)
  @array.map { |i| i[key] }
end

#method_name?(key) ⇒ Boolean

check if key represents a method/attribute name and return it if so

Parameters:

  • key (String|Symbol)

    key name

Returns:

  • (Boolean)


68
69
70
# File 'lib/uber_array.rb', line 68

def method_name?(key)
  key.is_a?(Symbol) && /^__(?<name>.+)__$/ =~ key ? name.to_sym : nil
end

#uberoptsObject

get current config options



14
15
16
# File 'lib/uber_array.rb', line 14

def uberopts
  { primary_key: primary_key }
end

#where(opts = {}) ⇒ Object Also known as: filter

filter items in @array Keys are key names (e.g. :name, ‘name’) for Hash-based elements or attribute names (e.g. :__name__) for Object-based elements



104
105
106
107
108
# File 'lib/uber_array.rb', line 104

def where(opts = {})
  return UberArray.new([], uberopts) if opts.empty?
  result = @array.select(&filter_proc(opts))
  UberArray.new(result, uberopts)
end