uber_array 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +20 -0
- data/.rspec +1 -0
- data/.rubocop.yml +57 -0
- data/CHANGELOG.md +2 -0
- data/Gemfile +2 -0
- data/LICENSE.md +13 -0
- data/README.md +71 -0
- data/Rakefile +8 -0
- data/lib/uber_array.rb +130 -0
- data/lib/uber_array/version.rb +3 -0
- data/spec/fixtures/items.yml +55 -0
- data/spec/spec_helper.rb +14 -0
- data/spec/uber_array_spec.rb +200 -0
- data/uber_array.gemspec +25 -0
- metadata +103 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 5eaa7aae77cd713169e5148fc0b5d7d4deffe6b1
|
4
|
+
data.tar.gz: 1dcb67cd4983d0fca9186a699feac341419e5d09
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: eb67ba7fd12560804a0fb645c6ca31ede7127bfbc14e47f6dc0cc7442327579c9c3035019a94924a0f453d693a6f9a63e81b33102a3ec56a32295a67ee9da87d
|
7
|
+
data.tar.gz: aef965890618882796892310279d59bab15774c8dd97a3b66ba1fb4979bc873e975cb9e58f79718a0117a0ec20e160df869c13892a4073550cb3408039bf84d6
|
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--require spec_helper
|
data/.rubocop.yml
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
AllCops:
|
2
|
+
Excludes:
|
3
|
+
- temp/*
|
4
|
+
|
5
|
+
Encoding:
|
6
|
+
Enabled: false
|
7
|
+
|
8
|
+
AmbiguousOperator:
|
9
|
+
Enabled: false
|
10
|
+
|
11
|
+
CaseIndentation:
|
12
|
+
Enabled: false
|
13
|
+
|
14
|
+
CyclomaticComplexity:
|
15
|
+
Enabled: false
|
16
|
+
Max: 10
|
17
|
+
|
18
|
+
PerceivedComplexity:
|
19
|
+
Enabled: false
|
20
|
+
Max: 10
|
21
|
+
|
22
|
+
Documentation:
|
23
|
+
Enabled: false
|
24
|
+
|
25
|
+
EmptyLinesAroundBody:
|
26
|
+
Enabled: false
|
27
|
+
|
28
|
+
HashSyntax:
|
29
|
+
Enabled: false
|
30
|
+
|
31
|
+
ClassLength:
|
32
|
+
Enabled: false
|
33
|
+
|
34
|
+
LineLength:
|
35
|
+
Enabled: true
|
36
|
+
Max: 160
|
37
|
+
|
38
|
+
MethodLength:
|
39
|
+
Enabled: false
|
40
|
+
|
41
|
+
ModuleFunction:
|
42
|
+
Enabled: false
|
43
|
+
|
44
|
+
NestedTernaryOperator:
|
45
|
+
Enabled: false
|
46
|
+
|
47
|
+
RaiseArgs:
|
48
|
+
Enabled: false
|
49
|
+
|
50
|
+
RescueModifier:
|
51
|
+
Enabled: false
|
52
|
+
|
53
|
+
SymbolProc:
|
54
|
+
Enabled: false
|
55
|
+
|
56
|
+
UnusedMethodArgument:
|
57
|
+
Enabled: false
|
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
data/LICENSE.md
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
Copyright 2015, Opower
|
2
|
+
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
you may not use this file except in compliance with the License.
|
5
|
+
You may obtain a copy of the License at
|
6
|
+
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
|
9
|
+
Unless required by applicable law or agreed to in writing, software
|
10
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
See the License for the specific language governing permissions and
|
13
|
+
limitations under the License.
|
data/README.md
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
#uber_array
|
2
|
+
|
3
|
+
`UberArray` is an `Array` based datatype that enables SQL-like `where` syntax for arrays of Hashes or Objects.
|
4
|
+
|
5
|
+
In Hash based arrays each element is a Hash with symbols or strings as keys.
|
6
|
+
In Object based arrays each element is an Object-derived instance that responds to attribute names instead of keys.
|
7
|
+
|
8
|
+
## Installation
|
9
|
+
|
10
|
+
Add this line to your application's Gemfile:
|
11
|
+
|
12
|
+
gem 'uber_array'
|
13
|
+
|
14
|
+
And then execute:
|
15
|
+
|
16
|
+
$ bundle install
|
17
|
+
|
18
|
+
Or install it yourself as:
|
19
|
+
|
20
|
+
$ gem install uber_array
|
21
|
+
|
22
|
+
## Usage
|
23
|
+
|
24
|
+
```ruby
|
25
|
+
require 'uber_array'
|
26
|
+
|
27
|
+
# Array of Hash elements with strings as keys
|
28
|
+
items = [
|
29
|
+
{ 'name' => 'Jack', 'score' => 999, 'active' => false },
|
30
|
+
{ 'name' => 'Jake', 'score' => 888, 'active' => true },
|
31
|
+
{ 'name' => 'John', 'score' => 777, 'active' => true }
|
32
|
+
]
|
33
|
+
|
34
|
+
uber_items = UberArray.new(items)
|
35
|
+
|
36
|
+
uber_items.where('name' => 'John')
|
37
|
+
uber_items.where('name' => /Ja/i)
|
38
|
+
uber_items.like('ja')
|
39
|
+
uber_items.where('name' => %w(Dave John Tom))
|
40
|
+
uber_items.where('score' => 999)
|
41
|
+
uber_items.where('score' => ->(s){s > 900})
|
42
|
+
uber_items.where('active' => true, 'score' => 800..900)
|
43
|
+
uber_items.map_by('name')
|
44
|
+
|
45
|
+
Player = Struct.new(:name, :score, :active)
|
46
|
+
|
47
|
+
# Array of Object-like Struct elements with attributes
|
48
|
+
objs = [
|
49
|
+
Player.new('Jack', 999, false),
|
50
|
+
Player.new('Jake', 888, true),
|
51
|
+
Player.new('John', 777, true)
|
52
|
+
]
|
53
|
+
|
54
|
+
uber_objs = UberArray.new(objs, :primary_key => :__name__)
|
55
|
+
|
56
|
+
uber_objs.where(:__name__ => 'John')
|
57
|
+
uber_objs.where(:__name__ => /Ja/i)
|
58
|
+
uber_objs.like('ja')
|
59
|
+
uber_objs.where(:__name__ => %w(Dave John Tom))
|
60
|
+
uber_objs.where(:__score__ => 999)
|
61
|
+
uber_objs.where(:__score__ => ->(s){s > 900})
|
62
|
+
uber_objs.where(:__active__ => true, :__score__ => 800..900)
|
63
|
+
```
|
64
|
+
|
65
|
+
### Contributing
|
66
|
+
|
67
|
+
1. Fork it
|
68
|
+
2. Create your feature branch (git checkout -b my-new-feature)
|
69
|
+
3. Commit your changes (git commit -am 'Add some feature')
|
70
|
+
4. Push to the branch (git push origin my-new-feature)
|
71
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
data/lib/uber_array.rb
ADDED
@@ -0,0 +1,130 @@
|
|
1
|
+
class UberArray
|
2
|
+
attr_accessor :array, :primary_key
|
3
|
+
|
4
|
+
# @param array [Array<Hash|Object>] underlying array
|
5
|
+
# @param options [Hash] init options
|
6
|
+
# @option options [String|Symbol] :primary_key Name of primary key or attribute
|
7
|
+
# attribute/method names are specified as symbols like :__name__
|
8
|
+
def initialize(array = [], options = {})
|
9
|
+
@array = array || []
|
10
|
+
@primary_key = options[:primary_key] || 'name'
|
11
|
+
end
|
12
|
+
|
13
|
+
# get current config options
|
14
|
+
def uberopts
|
15
|
+
{ primary_key: primary_key }
|
16
|
+
end
|
17
|
+
|
18
|
+
# delegate all methods to the inner @array,
|
19
|
+
# if the result is an Array with elements of the same type as @array - convert it to UberArray
|
20
|
+
def method_missing(method, *args, &block)
|
21
|
+
klass = @array.first.class
|
22
|
+
result = @array.send(method, *args, &block)
|
23
|
+
if result.is_a?(Array)
|
24
|
+
@array.empty? || result.empty? || result.first.class == klass ? UberArray.new(result, uberopts) : result
|
25
|
+
else
|
26
|
+
result
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# @param key [String|Symbol] key name to map by
|
31
|
+
def map_by(key)
|
32
|
+
@array.map { |i| i[key] }
|
33
|
+
end
|
34
|
+
|
35
|
+
# build a Proc by which to filter items in @array
|
36
|
+
# @params opts [Hash] filter options
|
37
|
+
def filter_proc(opts = {})
|
38
|
+
fail ArgumentError, 'Hash argument expected' unless opts.is_a?(Hash)
|
39
|
+
|
40
|
+
if opts.empty?
|
41
|
+
-> { false }
|
42
|
+
else
|
43
|
+
lambda do |item|
|
44
|
+
opts.map do |key, val|
|
45
|
+
can_respond, ival = item_send_if_respond_to?(item, key)
|
46
|
+
can_respond &&
|
47
|
+
case val
|
48
|
+
# :key => ->(v){v > 12}
|
49
|
+
when Proc
|
50
|
+
val.call(ival)
|
51
|
+
# :key => /text/
|
52
|
+
when Regexp
|
53
|
+
ival =~ val
|
54
|
+
# :key => 1..4, :key => [1,2,3,4]
|
55
|
+
when Array, Range
|
56
|
+
val.to_a.include?(ival)
|
57
|
+
# :key => false|true, :key => 'text', :key => 10
|
58
|
+
else
|
59
|
+
ival == val
|
60
|
+
end
|
61
|
+
end.all?
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# check if key represents a method/attribute name and return it if so
|
67
|
+
# @param key [String|Symbol] key name
|
68
|
+
def method_name?(key)
|
69
|
+
key.is_a?(Symbol) && /^__(?<name>.+)__$/ =~ key ? name.to_sym : nil
|
70
|
+
end
|
71
|
+
|
72
|
+
# check if item responds to a given key/attribute name
|
73
|
+
def item_respond_to?(item, key)
|
74
|
+
method = method_name?(key) || :[]
|
75
|
+
item.respond_to?(method)
|
76
|
+
end
|
77
|
+
|
78
|
+
# invoke the given key/attribute name as a method on item
|
79
|
+
def item_send(item, key)
|
80
|
+
method = method_name?(key)
|
81
|
+
method ? item.send(method) : item[key]
|
82
|
+
end
|
83
|
+
|
84
|
+
# send a key/method name to an item if the item responds to it
|
85
|
+
# @param item [Hash|Object] item of @array
|
86
|
+
# @param key [String|Symbol] key name
|
87
|
+
def item_send_if_respond_to?(item, key)
|
88
|
+
can_respond, result = nil, nil
|
89
|
+
method = method_name?(key)
|
90
|
+
if method
|
91
|
+
can_respond = item.respond_to?(method)
|
92
|
+
result = item.send(method) if can_respond
|
93
|
+
else
|
94
|
+
can_respond = item.respond_to?(:[])
|
95
|
+
result = item[key] if can_respond
|
96
|
+
end
|
97
|
+
[can_respond, result]
|
98
|
+
end
|
99
|
+
|
100
|
+
# filter items in @array
|
101
|
+
# @params opts [Hash] filter options
|
102
|
+
# Keys are key names (e.g. :name, 'name') for Hash-based elements
|
103
|
+
# or attribute names (e.g. :__name__) for Object-based elements
|
104
|
+
def where(opts = {})
|
105
|
+
return UberArray.new([], uberopts) if opts.empty?
|
106
|
+
result = @array.select(&filter_proc(opts))
|
107
|
+
UberArray.new(result, uberopts)
|
108
|
+
end
|
109
|
+
alias_method :filter, :where
|
110
|
+
|
111
|
+
# filter items by regex matching on @primary_key
|
112
|
+
def like(regex)
|
113
|
+
exp = regex.is_a?(String) ? Regexp.new(regex, true) : regex
|
114
|
+
where(primary_key => exp)
|
115
|
+
end
|
116
|
+
|
117
|
+
# use a non-number as access key into @array
|
118
|
+
# with elements responding to a key or attribute name specified by @primary_key
|
119
|
+
def [](key)
|
120
|
+
return @array[key] if key.is_a?(Fixnum)
|
121
|
+
method = method_name?(primary_key)
|
122
|
+
@array.find do |item|
|
123
|
+
if method
|
124
|
+
item.respond_to?(method) && item.send(method) == key
|
125
|
+
else
|
126
|
+
item.respond_to?(:[]) && item[primary_key] == key
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
---
|
2
|
+
- id: 0a
|
3
|
+
name: John Doe
|
4
|
+
team: ninjas
|
5
|
+
score: 800
|
6
|
+
email: john.doe@test.com
|
7
|
+
phone:
|
8
|
+
voice: 1234
|
9
|
+
sms: 6789
|
10
|
+
admin: false
|
11
|
+
active: true
|
12
|
+
|
13
|
+
- id: 1b
|
14
|
+
name: Jim Black
|
15
|
+
team: punks
|
16
|
+
score: 900
|
17
|
+
email: jim.black@ping.me
|
18
|
+
phone:
|
19
|
+
voice: 2345
|
20
|
+
sms: 5678
|
21
|
+
admin: false
|
22
|
+
active: false
|
23
|
+
|
24
|
+
- id: 2c
|
25
|
+
name: Anne Kim
|
26
|
+
team: sisters
|
27
|
+
score: 678
|
28
|
+
email: anne@sista.net
|
29
|
+
phone:
|
30
|
+
voice:
|
31
|
+
sms:
|
32
|
+
admin: false
|
33
|
+
active: true
|
34
|
+
|
35
|
+
- id: 3d
|
36
|
+
name: Sandi
|
37
|
+
team: sisters
|
38
|
+
score: 555
|
39
|
+
email: sandi@sista.net
|
40
|
+
phone:
|
41
|
+
voice: 2222
|
42
|
+
sms:
|
43
|
+
admin: false
|
44
|
+
active: false
|
45
|
+
|
46
|
+
- id: 4e
|
47
|
+
name: Zak
|
48
|
+
team: ninjas
|
49
|
+
score: 999
|
50
|
+
email: captain@test.me
|
51
|
+
phone:
|
52
|
+
voice: 7777
|
53
|
+
sms:
|
54
|
+
admin: true
|
55
|
+
active: true
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
require 'yaml'
|
3
|
+
require 'uber_array'
|
4
|
+
|
5
|
+
RSpec.configure do |config|
|
6
|
+
config.expect_with :rspec do |c|
|
7
|
+
c.syntax = :expect
|
8
|
+
end
|
9
|
+
|
10
|
+
def load_fixtures
|
11
|
+
file = '../fixtures/items.yml'
|
12
|
+
YAML.load_file(File.expand_path(file, __FILE__))
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,200 @@
|
|
1
|
+
module UberArraySpec
|
2
|
+
|
3
|
+
class Item
|
4
|
+
def initialize(options = {})
|
5
|
+
options.each do |key, val|
|
6
|
+
instance_variable_set("@#{key}", val)
|
7
|
+
self.class.send(:attr_reader, key.to_sym)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
describe UberArray do
|
13
|
+
# each array element is a Hash with string key names
|
14
|
+
let(:items_str) { load_fixtures }
|
15
|
+
# each array element is a Hash with symbolized key names
|
16
|
+
let(:items_sym) { items_str.map { |i| Hash[i.map { |(k, v)| [k.to_sym, v] }] } }
|
17
|
+
# each array element is an Item object with attributes instead of key names
|
18
|
+
let(:items_obj) { items_str.map { |i| Item.new(i) } }
|
19
|
+
|
20
|
+
# UberArray instances
|
21
|
+
subject(:array_sym) { UberArray.new(items_sym) }
|
22
|
+
subject(:array_str) { UberArray.new(items_str) }
|
23
|
+
subject(:array_obj) { UberArray.new(items_obj) }
|
24
|
+
|
25
|
+
let(:names) { items_sym.map { |i| i[:name] } }
|
26
|
+
let(:name) { 'Sandi' }
|
27
|
+
|
28
|
+
it 'delegates to the inner Array' do
|
29
|
+
expect(array_sym.respond_to?(:size)).to be false
|
30
|
+
expect(array_sym.size).to eq(5)
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'returns an UberArray when resulting elements are of the same type' do
|
34
|
+
expect(array_str.reverse).to be_a UberArray
|
35
|
+
expect(array_sym.sample(2)).to be_a UberArray
|
36
|
+
expect(array_sym.select { |i| i[:active] }).to be_a UberArray
|
37
|
+
expect(array_obj.select { |i| i.active }).to be_a UberArray
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'returns a regular Array when resulting elements are of a different type' do
|
41
|
+
expect(array_str.map { |i| Item.new(i) }).not_to be_a UberArray
|
42
|
+
end
|
43
|
+
|
44
|
+
describe '#method_name?' do
|
45
|
+
it 'extracts method name' do
|
46
|
+
[
|
47
|
+
# input_key => result
|
48
|
+
[:__name__, :name],
|
49
|
+
[:___name___, :_name_],
|
50
|
+
[:_name_, nil],
|
51
|
+
['__name__', nil]
|
52
|
+
].each { |key, rez| expect(array_sym.method_name?(key)).to eq rez }
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe '#map_by' do
|
57
|
+
it 'maps by string' do
|
58
|
+
expect(array_str.map_by('name')).to eq names
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'maps by symbol' do
|
62
|
+
expect(array_sym.map_by(:name)).to eq names
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'maps by attribute name' do
|
66
|
+
expect(array_obj.map(&:name)).to eq names
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe '#where' do
|
71
|
+
it 'filters by {string => String}' do
|
72
|
+
# where item['name'] equals name
|
73
|
+
expect(array_str.where('name' => name).array).to eq items_str.values_at(3)
|
74
|
+
expect(array_sym.where('name' => name).array).to be_empty
|
75
|
+
expect(array_obj.where('name' => name).array).to be_empty
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'filters by {:symbol => String}' do
|
79
|
+
# where item['name'] equals name
|
80
|
+
expect(array_str.where(:name => name).array).to be_empty
|
81
|
+
expect(array_sym.where(:name => name).array).to eq items_sym.values_at(3)
|
82
|
+
expect(array_obj.where(:name => name).array).to be_empty
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'filters by {:__symbol__ => String}' do
|
86
|
+
# where item.name equals name
|
87
|
+
expect(array_str.where(:__name__ => name).array).to be_empty
|
88
|
+
expect(array_sym.where(:__name__ => name).array).to be_empty
|
89
|
+
expect(array_obj.where(:__name__ => name).array).to eq items_obj.values_at(3)
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'filters by {key => Regexp}' do
|
93
|
+
regex = /test/
|
94
|
+
# where item['email'] is like regex
|
95
|
+
expect(array_str.where('email' => regex).array).to eq items_str.values_at(0, 4)
|
96
|
+
expect(array_sym.where(:email => regex).array).to eq items_sym.values_at(0, 4)
|
97
|
+
expect(array_obj.where(:__email__ => regex).array).to eq items_obj.values_at(0, 4)
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'filters by {key => Boolean}' do
|
101
|
+
# where item['admin'] is true
|
102
|
+
expect(array_str.where('admin' => true).array).to eq items_str.values_at(4)
|
103
|
+
expect(array_sym.where(:admin => true).array).to eq items_sym.values_at(4)
|
104
|
+
expect(array_obj.where(:__admin__ => true).array).to eq items_obj.values_at(4)
|
105
|
+
# where item['active'] is false
|
106
|
+
expect(array_str.where('active' => false).array).to eq items_str.values_at(1, 3)
|
107
|
+
expect(array_sym.where(:active => false).array).to eq items_sym.values_at(1, 3)
|
108
|
+
expect(array_obj.where(:__active__ => false).array).to eq items_obj.values_at(1, 3)
|
109
|
+
end
|
110
|
+
|
111
|
+
it 'filters by {key => Proc}' do
|
112
|
+
prok = ->(score) { score > 900 }
|
113
|
+
# where item['score'] < 900
|
114
|
+
expect(array_str.where('score' => prok).array).to eq items_str.values_at(4)
|
115
|
+
expect(array_sym.where(:score => prok).array).to eq items_sym.values_at(4)
|
116
|
+
expect(array_obj.where(:__score__ => prok).array).to eq items_obj.values_at(4)
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'filters by {key => Range}' do
|
120
|
+
range = 500..700
|
121
|
+
# where item['score'] is in range
|
122
|
+
expect(array_str.where('score' => range).array).to eq items_str.values_at(2, 3)
|
123
|
+
expect(array_sym.where(:score => range).array).to eq items_sym.values_at(2, 3)
|
124
|
+
expect(array_obj.where(:__score__ => range).array).to eq items_obj.values_at(2, 3)
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'filters by {key => Array}' do
|
128
|
+
teams = %w(bots ninjas)
|
129
|
+
# where item['team'] is a member of teams
|
130
|
+
expect(array_str.where('team' => teams).array).to eq items_str.values_at(0, 4)
|
131
|
+
expect(array_sym.where(:team => teams).array).to eq items_sym.values_at(0, 4)
|
132
|
+
expect(array_obj.where(:__team__ => teams).array).to eq items_obj.values_at(0, 4)
|
133
|
+
end
|
134
|
+
|
135
|
+
it 'filters by multiple criteria' do
|
136
|
+
# where item['active'] is true AND item['score'] < 700
|
137
|
+
filter = { 'active' => true, 'score' => ->(s) { s < 700 } }
|
138
|
+
expect(array_str.where(filter).array).to eq items_str.values_at(2)
|
139
|
+
# where item[:team] equals team AND item[:admin] is true
|
140
|
+
filter = { :team => 'ninjas', :admin => true }
|
141
|
+
expect(array_sym.where(filter).array).to eq items_sym.values_at(4)
|
142
|
+
# where item.email is like regex AND item.phone['sms'] is not nil
|
143
|
+
filter = { :__email__ => /test/, :__phone__ => ->p { p['sms'] } }
|
144
|
+
expect(array_obj.where(filter).array).to eq items_obj.values_at(0)
|
145
|
+
end
|
146
|
+
|
147
|
+
it 'supports chaining' do
|
148
|
+
team = 'ninjas'
|
149
|
+
expect(array_sym.where(active: true).where(team: team).array).to eq items_sym.values_at(0, 4)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
describe '#like' do
|
154
|
+
it 'filters by regex matching on primary_key' do
|
155
|
+
['an', /an/i].each do |regex|
|
156
|
+
# where item['name'] =~ regex
|
157
|
+
expect(array_str.like(regex).array).to eq items_str.values_at(2, 3)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
describe '#[]' do
|
163
|
+
it 'references elements by index' do
|
164
|
+
expect(array_str[1]).to eq items_str[1]
|
165
|
+
end
|
166
|
+
|
167
|
+
it "references items by the value of primary_key 'name'" do
|
168
|
+
# primary_key is a string key 'name' by default
|
169
|
+
expect(array_str[name]).to eq array_str[3]
|
170
|
+
expect(array_sym[name]).to eq nil
|
171
|
+
expect(array_obj[name]).to eq nil
|
172
|
+
end
|
173
|
+
|
174
|
+
it 'references items by the value of primary_key :name' do
|
175
|
+
# primary_key is a symbol key :name
|
176
|
+
[array_str, array_sym, array_obj].each { |a| a.primary_key = :name }
|
177
|
+
expect(array_str[name]).to eq nil
|
178
|
+
expect(array_sym[name]).to eq array_sym[3]
|
179
|
+
expect(array_obj[name]).to eq nil
|
180
|
+
end
|
181
|
+
|
182
|
+
it 'references items by the value of primary_key :__name__' do
|
183
|
+
# primary_key is an attribute :__name__
|
184
|
+
[array_str, array_sym, array_obj].each { |a| a.primary_key = :__name__ }
|
185
|
+
expect(array_str[name]).to eq nil
|
186
|
+
expect(array_sym[name]).to eq nil
|
187
|
+
expect(array_obj[name]).to eq array_obj[3]
|
188
|
+
end
|
189
|
+
|
190
|
+
it 'references items by the value of primary_key :id' do
|
191
|
+
id = '3d'
|
192
|
+
# primary_key is a symbol key :id
|
193
|
+
[array_str, array_sym, array_obj].each { |a| a.primary_key = :id }
|
194
|
+
expect(array_str[id]).to eq nil
|
195
|
+
expect(array_sym[id]).to eq array_sym[3]
|
196
|
+
expect(array_obj[id]).to eq nil
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
data/uber_array.gemspec
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/uber_array/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |spec|
|
5
|
+
spec.name = 'uber_array'
|
6
|
+
spec.version = UberArray::VERSION
|
7
|
+
spec.summary = 'Array based datatype with SQL-like syntax'
|
8
|
+
spec.description = "Enables SQL-like 'where' syntax for arrays of Hashes or Objects"
|
9
|
+
spec.homepage = 'https://github.com/alpinweis/uber_array'
|
10
|
+
|
11
|
+
spec.authors = ['Adrian Kazaku']
|
12
|
+
spec.email = ['alpinweis@gmail.com']
|
13
|
+
|
14
|
+
spec.license = 'Apache-2.0'
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($OUTPUT_RECORD_SEPARATOR)
|
17
|
+
spec.executables = spec.files.grep(/^bin\//) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(/^(test|spec|features)\//)
|
19
|
+
spec.require_paths = ['lib']
|
20
|
+
|
21
|
+
spec.add_development_dependency 'pry', '~> 0.10'
|
22
|
+
spec.add_development_dependency 'rake', '~> 10.1'
|
23
|
+
spec.add_development_dependency 'rspec', '~> 3.1'
|
24
|
+
# spec.add_development_dependency 'rubocop', '= 0.26.1'
|
25
|
+
end
|
metadata
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: uber_array
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Adrian Kazaku
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-11-13 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: pry
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.10'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.10'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.1'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.1'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.1'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.1'
|
55
|
+
description: Enables SQL-like 'where' syntax for arrays of Hashes or Objects
|
56
|
+
email:
|
57
|
+
- alpinweis@gmail.com
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- ".gitignore"
|
63
|
+
- ".rspec"
|
64
|
+
- ".rubocop.yml"
|
65
|
+
- CHANGELOG.md
|
66
|
+
- Gemfile
|
67
|
+
- LICENSE.md
|
68
|
+
- README.md
|
69
|
+
- Rakefile
|
70
|
+
- lib/uber_array.rb
|
71
|
+
- lib/uber_array/version.rb
|
72
|
+
- spec/fixtures/items.yml
|
73
|
+
- spec/spec_helper.rb
|
74
|
+
- spec/uber_array_spec.rb
|
75
|
+
- uber_array.gemspec
|
76
|
+
homepage: https://github.com/alpinweis/uber_array
|
77
|
+
licenses:
|
78
|
+
- Apache-2.0
|
79
|
+
metadata: {}
|
80
|
+
post_install_message:
|
81
|
+
rdoc_options: []
|
82
|
+
require_paths:
|
83
|
+
- lib
|
84
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0'
|
89
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
90
|
+
requirements:
|
91
|
+
- - ">="
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
requirements: []
|
95
|
+
rubyforge_project:
|
96
|
+
rubygems_version: 2.5.1
|
97
|
+
signing_key:
|
98
|
+
specification_version: 4
|
99
|
+
summary: Array based datatype with SQL-like syntax
|
100
|
+
test_files:
|
101
|
+
- spec/fixtures/items.yml
|
102
|
+
- spec/spec_helper.rb
|
103
|
+
- spec/uber_array_spec.rb
|