fetching 0.6.1 → 0.7.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 +5 -5
- data/.rspec +2 -0
- data/.rubocop.yml +17 -20
- data/.travis.yml +10 -0
- data/Gemfile +1 -1
- data/Guardfile +42 -0
- data/README.md +1 -1
- data/Rakefile +6 -1
- data/fetching.gemspec +23 -20
- data/lib/fetching.rb +10 -11
- data/lib/fetching/fetching_array.rb +42 -10
- data/lib/fetching/fetching_hash.rb +3 -3
- data/lib/fetching/version.rb +1 -1
- data/spec/fetching/fetching_array_spec.rb +174 -0
- data/spec/{fetching_hash_spec.rb → fetching/fetching_hash_spec.rb} +5 -7
- data/spec/fetching_spec.rb +25 -20
- data/spec/spec_helper.rb +23 -10
- metadata +82 -27
- data/spec/fetching_array_spec.rb +0 -88
- data/spec/support/vim_formatter.rb +0 -35
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 9ac1c22b5f53d128f788bcba8e01803b17bcdc861adbe1cb545a7361b372a240
|
4
|
+
data.tar.gz: 5ed9955513c5f64df46d89a4e312343516326f2aa7094f8b6b09a30367fbab19
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 735ae911c25552e07d81264fd4d585e306e23664a5069bd9bad7557a958d4fbeae2034dde3c106e316143be704917e1eb9fa76b1f839a9335ed86e1a8477fdf7
|
7
|
+
data.tar.gz: f2a59a5c7a295729fe7e2f7b842c5c9d431c2dad03cfc1f0cee1ea7f07fdaffe5200cd050dbeef97b04057a80fcd0a9c793dbcfe2e48e3ff0bbf9ffd270a1e9e
|
data/.rspec
ADDED
data/.rubocop.yml
CHANGED
@@ -1,37 +1,34 @@
|
|
1
1
|
AllCops:
|
2
2
|
Include:
|
3
3
|
- Gemfile
|
4
|
+
- Guardfile
|
4
5
|
- Rakefile
|
6
|
+
- fetching.gemspec
|
7
|
+
- rubocop-rspec
|
5
8
|
|
6
|
-
|
7
|
-
Enabled: false
|
8
|
-
|
9
|
-
Encoding:
|
10
|
-
Enabled: false
|
11
|
-
|
12
|
-
EmptyLinesAroundBody:
|
9
|
+
Layout/EmptyLinesAroundClassBody:
|
13
10
|
Enabled: false
|
14
11
|
|
15
|
-
|
16
|
-
Max: 100
|
17
|
-
|
18
|
-
MethodDefParentheses:
|
12
|
+
Layout/EmptyLinesAroundModuleBody:
|
19
13
|
Enabled: false
|
20
14
|
|
21
|
-
|
15
|
+
Layout/EmptyLinesAroundBlockBody:
|
22
16
|
Enabled: false
|
23
17
|
|
24
|
-
|
25
|
-
MaxSlashes: 0
|
18
|
+
Layout/IndentHeredoc:
|
26
19
|
Exclude:
|
27
|
-
-
|
20
|
+
- fetching.gemspec
|
28
21
|
|
29
|
-
|
22
|
+
Metrics/BlockLength:
|
30
23
|
Exclude:
|
31
24
|
- fetching.gemspec
|
32
25
|
|
33
|
-
|
34
|
-
|
26
|
+
Metrics/LineLength:
|
27
|
+
Max: 100
|
35
28
|
|
36
|
-
|
37
|
-
|
29
|
+
Style/Documentation:
|
30
|
+
Enabled: false
|
31
|
+
|
32
|
+
Style/RegexpLiteral:
|
33
|
+
Exclude:
|
34
|
+
- Guardfile
|
data/.travis.yml
ADDED
data/Gemfile
CHANGED
data/Guardfile
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
guard :rubocop, cli: ['--display-cop-names'] do
|
2
|
+
watch(%r{.+\.rb$})
|
3
|
+
watch(%r{(?:.+/)?\.rubocop\.yml$}) { |m| File.dirname(m[0]) }
|
4
|
+
end
|
5
|
+
|
6
|
+
rspec_opts = {
|
7
|
+
cmd: 'bundle exec rspec',
|
8
|
+
all_on_start: true,
|
9
|
+
all_after_pass: true,
|
10
|
+
failed_mode: :keep
|
11
|
+
}
|
12
|
+
|
13
|
+
guard :rspec, rspec_opts do
|
14
|
+
watch(%r{^spec/.+_spec\.rb$})
|
15
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
16
|
+
watch('spec/spec_helper.rb') { 'spec' }
|
17
|
+
|
18
|
+
watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
|
19
|
+
watch(%r{^app/(.*)(\.erb|\.haml|\.slim)$}) do |m|
|
20
|
+
"spec/#{m[1]}#{m[2]}_spec.rb"
|
21
|
+
end
|
22
|
+
|
23
|
+
watch(%r{^app/controllers/(.+)_(controller)\.rb$}) do |m|
|
24
|
+
[
|
25
|
+
"spec/routing/#{m[1]}_routing_spec.rb",
|
26
|
+
"spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb",
|
27
|
+
"spec/acceptance/#{m[1]}_spec.rb"
|
28
|
+
]
|
29
|
+
end
|
30
|
+
watch(%r{^spec/support/(.+)\.rb$}) { 'spec' }
|
31
|
+
watch('config/routes.rb') { 'spec/routing' }
|
32
|
+
watch('app/controllers/application_controller.rb') { 'spec/controllers' }
|
33
|
+
|
34
|
+
watch(%r{^app/views/(.+)/.*\.(erb|haml|slim)$}) do |m|
|
35
|
+
"spec/features/#{m[1]}_spec.rb"
|
36
|
+
end
|
37
|
+
|
38
|
+
watch(%r{^spec/acceptance/(.+)\.feature$})
|
39
|
+
watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) do |m|
|
40
|
+
Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance'
|
41
|
+
end
|
42
|
+
end
|
data/README.md
CHANGED
data/Rakefile
CHANGED
data/fetching.gemspec
CHANGED
@@ -1,32 +1,35 @@
|
|
1
|
-
|
2
|
-
lib = File.expand_path("../lib", __FILE__)
|
1
|
+
lib = File.expand_path('lib', __dir__)
|
3
2
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require
|
3
|
+
require 'fetching/version'
|
5
4
|
|
6
5
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name =
|
6
|
+
spec.name = 'fetching'
|
8
7
|
spec.version = Fetching::VERSION
|
9
|
-
spec.authors = [
|
10
|
-
spec.email = [
|
11
|
-
spec.description =
|
8
|
+
spec.authors = ['Michael Gee', 'Mark Lorenz']
|
9
|
+
spec.email = ['mgee@covermymeds.com', 'mlorenz@covermymeds.com']
|
10
|
+
spec.description = "Strict wrapper for Hashes and Arrays that doesn't return nil"
|
12
11
|
|
13
12
|
spec.summary = <<-HEREDOC
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
and array bounds.}
|
18
|
-
HEREDOC
|
13
|
+
Don't de-serialize API responses in to hashes and arrays.
|
14
|
+
Use a "strict" object that inforces key presence and array bounds.
|
15
|
+
HEREDOC
|
19
16
|
|
20
|
-
spec.homepage =
|
21
|
-
spec.license =
|
17
|
+
spec.homepage = ''
|
18
|
+
spec.license = 'MIT'
|
22
19
|
|
23
|
-
spec.files = `git ls-files`.split(
|
20
|
+
spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
|
24
21
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
25
22
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
26
|
-
spec.require_paths = [
|
23
|
+
spec.require_paths = ['lib']
|
27
24
|
|
28
|
-
spec.add_development_dependency
|
29
|
-
spec.add_development_dependency
|
30
|
-
spec.add_development_dependency
|
31
|
-
spec.add_development_dependency
|
25
|
+
spec.add_development_dependency 'bundler', '~> 1.3'
|
26
|
+
spec.add_development_dependency 'rake'
|
27
|
+
spec.add_development_dependency 'rspec', '~> 3.1'
|
28
|
+
spec.add_development_dependency 'rubocop', '~> 0.58.0'
|
29
|
+
spec.add_development_dependency 'rubocop-rspec'
|
30
|
+
unless ENV['CI']
|
31
|
+
spec.add_development_dependency 'guard-rspec'
|
32
|
+
spec.add_development_dependency 'guard-rubocop'
|
33
|
+
spec.add_development_dependency 'pry'
|
34
|
+
end
|
32
35
|
end
|
data/lib/fetching.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
1
|
+
require 'json'
|
2
|
+
require 'fetching/fetching_array'
|
3
|
+
require 'fetching/fetching_hash'
|
4
4
|
|
5
5
|
module Kernel
|
6
6
|
|
@@ -14,11 +14,10 @@ class Fetching
|
|
14
14
|
|
15
15
|
WHITELIST = %w(
|
16
16
|
class object_id == equal?
|
17
|
-
define_singleton_method
|
17
|
+
define_singleton_method singleton_class
|
18
18
|
respond_to?
|
19
|
-
|
20
|
-
|
21
|
-
)
|
19
|
+
nil? tap
|
20
|
+
).freeze
|
22
21
|
|
23
22
|
all_methods = instance_methods.map(&:to_s).grep(/\A[^_]/)
|
24
23
|
(all_methods - WHITELIST).each(&method(:undef_method))
|
@@ -30,11 +29,11 @@ class Fetching
|
|
30
29
|
value
|
31
30
|
end
|
32
31
|
|
33
|
-
def self.from_json
|
34
|
-
from
|
32
|
+
def self.from_json(json)
|
33
|
+
from JSON.parse(json)
|
35
34
|
end
|
36
35
|
|
37
|
-
def initialize
|
36
|
+
def initialize(table)
|
38
37
|
@table = table
|
39
38
|
end
|
40
39
|
|
@@ -60,7 +59,7 @@ class Fetching
|
|
60
59
|
|
61
60
|
private
|
62
61
|
|
63
|
-
def respond_to_missing?
|
62
|
+
def respond_to_missing?(_method_name, _include_private = false)
|
64
63
|
false
|
65
64
|
end
|
66
65
|
|
@@ -3,8 +3,12 @@ class Fetching
|
|
3
3
|
|
4
4
|
include Enumerable
|
5
5
|
|
6
|
-
def [](
|
7
|
-
|
6
|
+
def [](*args)
|
7
|
+
if args.length == 1 && args.first.is_a?(Integer)
|
8
|
+
Fetching.from @table.fetch(args.first)
|
9
|
+
else
|
10
|
+
values_at(*args)
|
11
|
+
end
|
8
12
|
end
|
9
13
|
|
10
14
|
def each
|
@@ -13,8 +17,10 @@ class Fetching
|
|
13
17
|
end
|
14
18
|
end
|
15
19
|
|
16
|
-
def first
|
17
|
-
self[0]
|
20
|
+
def first(num = 0)
|
21
|
+
return self[0] if num.zero?
|
22
|
+
|
23
|
+
Array.new(num) { |i| self[i] }
|
18
24
|
end
|
19
25
|
|
20
26
|
module ArrayMethods
|
@@ -26,28 +32,54 @@ class Fetching
|
|
26
32
|
def length
|
27
33
|
@table.length
|
28
34
|
end
|
29
|
-
|
35
|
+
alias size length
|
30
36
|
|
31
37
|
def reverse
|
32
38
|
Fetching.from @table.reverse
|
33
39
|
end
|
34
40
|
|
35
|
-
def shuffle
|
41
|
+
def shuffle(*args)
|
36
42
|
Fetching.from @table.shuffle(*args)
|
37
43
|
end
|
38
44
|
|
39
|
-
def sort
|
45
|
+
def sort(&block)
|
40
46
|
Fetching.from @table.sort(&block)
|
41
47
|
end
|
42
48
|
|
43
|
-
def sort_by
|
49
|
+
def sort_by(&block)
|
44
50
|
Fetching.from @table.sort_by(&block)
|
45
51
|
end
|
46
52
|
|
47
|
-
def values_at
|
48
|
-
|
53
|
+
def values_at(*args)
|
54
|
+
results = args.map { |arg| result_for_argument(arg) }.flatten
|
55
|
+
|
56
|
+
Fetching.from(results)
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def result_for_argument(argument)
|
62
|
+
case argument
|
63
|
+
when Integer
|
64
|
+
values_at_integer(argument)
|
65
|
+
when Array
|
66
|
+
values_at_array(argument)
|
67
|
+
when Range
|
68
|
+
values_at_range(argument)
|
69
|
+
end
|
49
70
|
end
|
50
71
|
|
72
|
+
def values_at_integer(integer)
|
73
|
+
self[integer]
|
74
|
+
end
|
75
|
+
|
76
|
+
def values_at_array(array)
|
77
|
+
array.map { |a| values_at_integer(a) }
|
78
|
+
end
|
79
|
+
|
80
|
+
def values_at_range(range)
|
81
|
+
values_at_array(range.to_a)
|
82
|
+
end
|
51
83
|
end
|
52
84
|
|
53
85
|
include ArrayMethods
|
@@ -1,7 +1,7 @@
|
|
1
1
|
class Fetching
|
2
2
|
class FetchingHash < Fetching
|
3
3
|
|
4
|
-
def initialize
|
4
|
+
def initialize(*args)
|
5
5
|
super
|
6
6
|
make_methods
|
7
7
|
end
|
@@ -20,8 +20,8 @@ class Fetching
|
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
|
-
def method_missing
|
24
|
-
|
23
|
+
def method_missing(key, *_args, &_block)
|
24
|
+
raise NoMethodError, "#{key} not found\nyou have:\n#{@table.keys.join(', ')}"
|
25
25
|
end
|
26
26
|
|
27
27
|
end
|
data/lib/fetching/version.rb
CHANGED
@@ -0,0 +1,174 @@
|
|
1
|
+
RSpec.describe Fetching::FetchingArray do
|
2
|
+
|
3
|
+
specify 'a Fetching object as a value' do
|
4
|
+
ary = Fetching([1, 2])
|
5
|
+
hsh = Fetching(one: 1)
|
6
|
+
[ary, hsh].each do |obj|
|
7
|
+
fetching_ary = Fetching [obj]
|
8
|
+
expect(fetching_ary.first).to equal(obj)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
specify '#map' do
|
13
|
+
ary = [1, 2]
|
14
|
+
fetching_ary = Fetching(ary)
|
15
|
+
expect(fetching_ary.map(&:to_s)).to eq(%w(1 2))
|
16
|
+
end
|
17
|
+
|
18
|
+
specify 'Fetching goes deep' do
|
19
|
+
Fetching([{ one: 1 }]).each do |element|
|
20
|
+
expect(element.one).to eq(1)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe '#first' do
|
25
|
+
it 'returns the first element in the array' do
|
26
|
+
ary = []
|
27
|
+
sassy_ary = Fetching(ary)
|
28
|
+
expect { sassy_ary.first }.to raise_error(IndexError)
|
29
|
+
end
|
30
|
+
|
31
|
+
context 'when passed an amount to fetch the first of' do
|
32
|
+
it 'returns the first n elements' do
|
33
|
+
ary = [1, 2, 3]
|
34
|
+
sassy_ary = Fetching(ary)
|
35
|
+
expect(sassy_ary.first(2)).to eq([1, 2])
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe '#[]' do
|
41
|
+
let(:array) { [1, 2, 3] }
|
42
|
+
let(:fetching) { Fetching(array) }
|
43
|
+
|
44
|
+
it 'returns the specified index' do
|
45
|
+
expect(fetching[0]).to eq(1)
|
46
|
+
expect(fetching[1]).to eq(2)
|
47
|
+
expect(fetching[2]).to eq(3)
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'throws an error on an invalid index' do
|
51
|
+
expect { fetching[5] }.to raise_error(IndexError)
|
52
|
+
end
|
53
|
+
|
54
|
+
context 'with multiple values' do
|
55
|
+
it 'returns a fetching array of the results' do
|
56
|
+
expected = Fetching([1, 2])
|
57
|
+
expect(fetching[0, 1]).to eq(expected)
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'raises error on invalid index' do
|
61
|
+
expect { fetching[0, 5] }.to raise_error(IndexError)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context 'with a Range' do
|
66
|
+
it 'returns a fetching array of the results' do
|
67
|
+
expected = Fetching([1, 2])
|
68
|
+
expect(fetching[0..1]).to eq(expected)
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'raises error on invalid index' do
|
72
|
+
expect { fetching[0..5] }.to raise_error(IndexError)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
context 'with multiple ranges' do
|
77
|
+
it 'returns a fetching array of the results' do
|
78
|
+
expected = Fetching([1, 2, 3, 3])
|
79
|
+
expect(fetching[0..2, 2..2]).to eq(expected)
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'raises error on invalid index' do
|
83
|
+
expect { fetching[0..1, 5..5] }.to raise_error(IndexError)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
describe 'array methods' do
|
89
|
+
let(:array) { [1, 2, 3] }
|
90
|
+
let(:fetching) { Fetching(array) }
|
91
|
+
|
92
|
+
describe '#empty?' do
|
93
|
+
it('is false') { expect(fetching.empty?).to be_falsy }
|
94
|
+
|
95
|
+
context 'when empty' do
|
96
|
+
let(:array) { [] }
|
97
|
+
it('is true') { expect(fetching.empty?).to be_truthy }
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
specify '#length' do
|
102
|
+
expect(fetching.length).to eq(array.length)
|
103
|
+
expect(fetching.size).to eq(array.size)
|
104
|
+
end
|
105
|
+
|
106
|
+
specify '#reverse' do
|
107
|
+
reversed = Fetching(array.reverse)
|
108
|
+
expect(fetching.reverse).to eq(reversed)
|
109
|
+
end
|
110
|
+
|
111
|
+
specify '#shuffle' do
|
112
|
+
seed = 1
|
113
|
+
shuffled = Fetching(array.shuffle(random: Random.new(seed)))
|
114
|
+
expect(fetching.shuffle(random: Random.new(seed))).to eq(shuffled)
|
115
|
+
end
|
116
|
+
|
117
|
+
specify '#sort' do
|
118
|
+
sorter = ->(x, y) { y <=> x }
|
119
|
+
sorted = Fetching(array.sort(&sorter))
|
120
|
+
expect(fetching.sort(&sorter)).to eq(sorted)
|
121
|
+
end
|
122
|
+
|
123
|
+
specify '#sort_by' do
|
124
|
+
sorter = ->(i) { 1.0 / i }
|
125
|
+
sorted = Fetching(array.sort_by(&sorter))
|
126
|
+
expect(fetching.sort_by(&sorter)).to eq(sorted)
|
127
|
+
end
|
128
|
+
|
129
|
+
describe '#values_at' do
|
130
|
+
specify 'happy path' do
|
131
|
+
at = [0, 2]
|
132
|
+
values = Fetching(array.values_at(*at))
|
133
|
+
expect(fetching.values_at(*at)).to eq(values)
|
134
|
+
end
|
135
|
+
|
136
|
+
specify 'out of bounds' do
|
137
|
+
at = 5
|
138
|
+
expected_message = /\Aindex #{at} out/
|
139
|
+
expect { fetching.values_at(at) }.to raise_error(IndexError, expected_message)
|
140
|
+
end
|
141
|
+
|
142
|
+
context 'with a range' do
|
143
|
+
it 'returns the expected values' do
|
144
|
+
range = (0..2)
|
145
|
+
values = Fetching(array.values_at(range))
|
146
|
+
expect(fetching.values_at(range)).to eq(values)
|
147
|
+
end
|
148
|
+
|
149
|
+
it 'correctly throws when range exceeds array' do
|
150
|
+
range = (0..5)
|
151
|
+
expect { fetching.values_at(range) }.to raise_error(IndexError)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
context 'with multiple ranges' do
|
156
|
+
let(:array) { [1, 2, 3, 4, 5] }
|
157
|
+
|
158
|
+
it 'returns the proper values' do
|
159
|
+
range_1 = (0..2)
|
160
|
+
range_2 = (2..4)
|
161
|
+
expected = Fetching([1, 2, 3, 3, 4, 5])
|
162
|
+
values = Fetching(array.values_at(range_1, range_2))
|
163
|
+
expect(values).to eq(expected)
|
164
|
+
end
|
165
|
+
|
166
|
+
it 'correctly throws when range exceeds array' do
|
167
|
+
range_1 = (0..2)
|
168
|
+
range_2 = (2..7)
|
169
|
+
expect { fetching.values_at(range_1, range_2) }.to raise_error(IndexError)
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
@@ -1,8 +1,6 @@
|
|
1
|
-
|
1
|
+
RSpec.describe Fetching::FetchingHash do
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
specify "a Fetching object as a value" do
|
3
|
+
specify 'a Fetching object as a value' do
|
6
4
|
ary = Fetching([1, 2])
|
7
5
|
hsh = Fetching(one: 1)
|
8
6
|
[ary, hsh].each do |obj|
|
@@ -11,7 +9,7 @@ describe Fetching::FetchingHash do
|
|
11
9
|
end
|
12
10
|
end
|
13
11
|
|
14
|
-
specify
|
12
|
+
specify '#to_hash' do
|
15
13
|
hash = { one: 1, two: 2 }
|
16
14
|
fetching_hash = Fetching(hash)
|
17
15
|
expect(fetching_hash.to_hash).to eq(hash)
|
@@ -20,11 +18,11 @@ describe Fetching::FetchingHash do
|
|
20
18
|
specify "#to_hash doesn't allow you to break fetching" do
|
21
19
|
fetching_hash = Fetching(one: 1, two: 2)
|
22
20
|
hash = fetching_hash.to_hash
|
23
|
-
hash[:one] =
|
21
|
+
hash[:one] = ':)'
|
24
22
|
expect(fetching_hash.to_hash[:one]).to eq(1)
|
25
23
|
end
|
26
24
|
|
27
|
-
specify
|
25
|
+
specify '#to_hash does a deep copy' do
|
28
26
|
hash = { one: 1, two: { three: 3 } }
|
29
27
|
fetching_hash = Fetching(hash)
|
30
28
|
expect(fetching_hash.to_hash).to eq(hash)
|
data/spec/fetching_spec.rb
CHANGED
@@ -1,52 +1,57 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
describe Fetching do
|
1
|
+
RSpec.describe Fetching do
|
4
2
|
|
5
3
|
let(:input) { { one: 1, two: two, ary: ary, object_ary: object_ary } }
|
6
|
-
let(:two) { {
|
4
|
+
let(:two) { { 'two' => 2 } }
|
7
5
|
let(:ary) { [1, 2] }
|
8
6
|
let(:object_ary) { [{}, last_object] }
|
9
7
|
let(:last_object) { { three: 3 } }
|
10
8
|
|
11
9
|
subject { Fetching(input) }
|
12
|
-
specify(
|
13
|
-
specify(
|
14
|
-
specify(
|
15
|
-
specify
|
10
|
+
specify('#one') { expect(subject.one).to eq(1) }
|
11
|
+
specify('#two') { expect(subject.two).to eq(Fetching(two)) }
|
12
|
+
specify('#ary') { expect(subject.ary).to eq(Fetching(ary)) }
|
13
|
+
specify 'objects in arrays' do
|
16
14
|
expect(subject.object_ary[1].three).to eq(3)
|
17
15
|
end
|
18
16
|
|
19
|
-
describe
|
20
|
-
it
|
21
|
-
expected_message = <<-EOM.gsub(/^ +/,
|
17
|
+
describe 'an unknown hash key' do
|
18
|
+
it 'raises NoMethodError' do
|
19
|
+
expected_message = <<-EOM.gsub(/^ +/, '').strip
|
22
20
|
not_a_key not found
|
23
21
|
you have:
|
24
|
-
|
22
|
+
one, two, ary, object_ary
|
25
23
|
EOM
|
26
24
|
|
27
25
|
expect { subject.not_a_key }.to raise_error(NoMethodError, expected_message)
|
28
26
|
end
|
29
27
|
end
|
30
28
|
|
31
|
-
describe
|
32
|
-
it
|
33
|
-
expected_message =
|
29
|
+
describe 'an unknown array index' do
|
30
|
+
it 'raises NoMethodError' do
|
31
|
+
expected_message = /\Aindex 3 out/
|
34
32
|
expect { subject.ary[ary.size + 1] }.to raise_error(IndexError, expected_message)
|
35
33
|
end
|
36
34
|
end
|
37
35
|
|
38
|
-
it
|
39
|
-
|
36
|
+
it 'can be #tap()ed' do
|
37
|
+
f = Fetching(foo: 'bar')
|
38
|
+
f.tap do |fetching_obj|
|
39
|
+
expect(fetching_obj).to eq(f)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'has a nice #to_s' do
|
44
|
+
nice_to_s = '{:one=>1, :two=>{"two"=>2}, :ary=>[1, 2], :object_ary=>[{}, {:three=>3}]}'
|
40
45
|
expect(subject.to_s).to eq(nice_to_s)
|
41
46
|
end
|
42
47
|
|
43
|
-
it
|
44
|
-
table =
|
48
|
+
it 'has a nice #inspect' do
|
49
|
+
table = '{:one=>1, :two=>{"two"=>2}, :ary=>[1, 2], :object_ary=>[{}, {:three=>3}]}'
|
45
50
|
nice_inspect = "#<Fetching::FetchingHash: @table=#{table}>"
|
46
51
|
expect(subject.inspect).to eq(nice_inspect)
|
47
52
|
end
|
48
53
|
|
49
|
-
specify
|
54
|
+
specify '.from_json' do
|
50
55
|
json = '{ "some_key": 1 }'
|
51
56
|
expected = Fetching(JSON.parse(json))
|
52
57
|
expect(described_class.from_json(json)).to eq(expected)
|
data/spec/spec_helper.rb
CHANGED
@@ -1,13 +1,26 @@
|
|
1
|
-
require
|
2
|
-
require "rspec/autorun"
|
3
|
-
require "pathname"
|
4
|
-
|
5
|
-
Pathname(__FILE__).dirname.join("support").each_child { |f| require f }
|
1
|
+
require 'fetching'
|
6
2
|
|
7
3
|
RSpec.configure do |config|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
config.
|
4
|
+
config.expect_with :rspec do |expectations|
|
5
|
+
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
|
6
|
+
end
|
7
|
+
|
8
|
+
config.mock_with :rspec do |mocks|
|
9
|
+
mocks.verify_partial_doubles = true
|
10
|
+
end
|
11
|
+
|
12
|
+
if ENV['CI']
|
13
|
+
config.before(:example, :focus) { raise 'Should not commit focused specs' }
|
14
|
+
else
|
15
|
+
config.filter_run :focus
|
16
|
+
config.run_all_when_everything_filtered = true
|
17
|
+
end
|
18
|
+
|
19
|
+
config.disable_monkey_patching!
|
20
|
+
|
21
|
+
config.warnings = true
|
22
|
+
|
23
|
+
config.order = :random
|
24
|
+
|
25
|
+
Kernel.srand config.seed
|
13
26
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fetching
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Gee
|
@@ -9,65 +9,121 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2018-08-04 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
16
16
|
requirement: !ruby/object:Gem::Requirement
|
17
17
|
requirements:
|
18
|
-
- - ~>
|
18
|
+
- - "~>"
|
19
19
|
- !ruby/object:Gem::Version
|
20
20
|
version: '1.3'
|
21
21
|
type: :development
|
22
22
|
prerelease: false
|
23
23
|
version_requirements: !ruby/object:Gem::Requirement
|
24
24
|
requirements:
|
25
|
-
- - ~>
|
25
|
+
- - "~>"
|
26
26
|
- !ruby/object:Gem::Version
|
27
27
|
version: '1.3'
|
28
28
|
- !ruby/object:Gem::Dependency
|
29
29
|
name: rake
|
30
30
|
requirement: !ruby/object:Gem::Requirement
|
31
31
|
requirements:
|
32
|
-
- -
|
32
|
+
- - ">="
|
33
33
|
- !ruby/object:Gem::Version
|
34
34
|
version: '0'
|
35
35
|
type: :development
|
36
36
|
prerelease: false
|
37
37
|
version_requirements: !ruby/object:Gem::Requirement
|
38
38
|
requirements:
|
39
|
-
- -
|
39
|
+
- - ">="
|
40
40
|
- !ruby/object:Gem::Version
|
41
41
|
version: '0'
|
42
42
|
- !ruby/object:Gem::Dependency
|
43
43
|
name: rspec
|
44
44
|
requirement: !ruby/object:Gem::Requirement
|
45
45
|
requirements:
|
46
|
-
- -
|
46
|
+
- - "~>"
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '3.1'
|
49
|
+
type: :development
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - "~>"
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '3.1'
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: rubocop
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - "~>"
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: 0.58.0
|
63
|
+
type: :development
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - "~>"
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 0.58.0
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: rubocop-rspec
|
72
|
+
requirement: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - ">="
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - ">="
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '0'
|
84
|
+
- !ruby/object:Gem::Dependency
|
85
|
+
name: guard-rspec
|
86
|
+
requirement: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '0'
|
91
|
+
type: :development
|
92
|
+
prerelease: false
|
93
|
+
version_requirements: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - ">="
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '0'
|
98
|
+
- !ruby/object:Gem::Dependency
|
99
|
+
name: guard-rubocop
|
100
|
+
requirement: !ruby/object:Gem::Requirement
|
101
|
+
requirements:
|
102
|
+
- - ">="
|
47
103
|
- !ruby/object:Gem::Version
|
48
104
|
version: '0'
|
49
105
|
type: :development
|
50
106
|
prerelease: false
|
51
107
|
version_requirements: !ruby/object:Gem::Requirement
|
52
108
|
requirements:
|
53
|
-
- -
|
109
|
+
- - ">="
|
54
110
|
- !ruby/object:Gem::Version
|
55
111
|
version: '0'
|
56
112
|
- !ruby/object:Gem::Dependency
|
57
|
-
name: pry
|
113
|
+
name: pry
|
58
114
|
requirement: !ruby/object:Gem::Requirement
|
59
115
|
requirements:
|
60
|
-
- -
|
116
|
+
- - ">="
|
61
117
|
- !ruby/object:Gem::Version
|
62
118
|
version: '0'
|
63
119
|
type: :development
|
64
120
|
prerelease: false
|
65
121
|
version_requirements: !ruby/object:Gem::Requirement
|
66
122
|
requirements:
|
67
|
-
- -
|
123
|
+
- - ">="
|
68
124
|
- !ruby/object:Gem::Version
|
69
125
|
version: '0'
|
70
|
-
description:
|
126
|
+
description: Strict wrapper for Hashes and Arrays that doesn't return nil
|
71
127
|
email:
|
72
128
|
- mgee@covermymeds.com
|
73
129
|
- mlorenz@covermymeds.com
|
@@ -75,9 +131,12 @@ executables: []
|
|
75
131
|
extensions: []
|
76
132
|
extra_rdoc_files: []
|
77
133
|
files:
|
78
|
-
- .gitignore
|
79
|
-
- .
|
134
|
+
- ".gitignore"
|
135
|
+
- ".rspec"
|
136
|
+
- ".rubocop.yml"
|
137
|
+
- ".travis.yml"
|
80
138
|
- Gemfile
|
139
|
+
- Guardfile
|
81
140
|
- LICENSE.txt
|
82
141
|
- README.md
|
83
142
|
- Rakefile
|
@@ -86,11 +145,10 @@ files:
|
|
86
145
|
- lib/fetching/fetching_array.rb
|
87
146
|
- lib/fetching/fetching_hash.rb
|
88
147
|
- lib/fetching/version.rb
|
89
|
-
- spec/fetching_array_spec.rb
|
90
|
-
- spec/fetching_hash_spec.rb
|
148
|
+
- spec/fetching/fetching_array_spec.rb
|
149
|
+
- spec/fetching/fetching_hash_spec.rb
|
91
150
|
- spec/fetching_spec.rb
|
92
151
|
- spec/spec_helper.rb
|
93
|
-
- spec/support/vim_formatter.rb
|
94
152
|
homepage: ''
|
95
153
|
licenses:
|
96
154
|
- MIT
|
@@ -101,26 +159,23 @@ require_paths:
|
|
101
159
|
- lib
|
102
160
|
required_ruby_version: !ruby/object:Gem::Requirement
|
103
161
|
requirements:
|
104
|
-
- -
|
162
|
+
- - ">="
|
105
163
|
- !ruby/object:Gem::Version
|
106
164
|
version: '0'
|
107
165
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
108
166
|
requirements:
|
109
|
-
- -
|
167
|
+
- - ">="
|
110
168
|
- !ruby/object:Gem::Version
|
111
169
|
version: '0'
|
112
170
|
requirements: []
|
113
171
|
rubyforge_project:
|
114
|
-
rubygems_version: 2.
|
172
|
+
rubygems_version: 2.7.6
|
115
173
|
signing_key:
|
116
174
|
specification_version: 4
|
117
|
-
summary: '
|
118
|
-
|
119
|
-
arrays. Use a "strict" object that inforces key presence, and array bounds.}'
|
175
|
+
summary: Don't de-serialize API responses in to hashes and arrays. Use a "strict"
|
176
|
+
object that inforces key presence and array bounds.
|
120
177
|
test_files:
|
121
|
-
- spec/fetching_array_spec.rb
|
122
|
-
- spec/fetching_hash_spec.rb
|
178
|
+
- spec/fetching/fetching_array_spec.rb
|
179
|
+
- spec/fetching/fetching_hash_spec.rb
|
123
180
|
- spec/fetching_spec.rb
|
124
181
|
- spec/spec_helper.rb
|
125
|
-
- spec/support/vim_formatter.rb
|
126
|
-
has_rdoc:
|
data/spec/fetching_array_spec.rb
DELETED
@@ -1,88 +0,0 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
|
3
|
-
describe Fetching::FetchingArray do
|
4
|
-
|
5
|
-
specify "a Fetching object as a value" do
|
6
|
-
ary = Fetching([1, 2])
|
7
|
-
hsh = Fetching(one: 1)
|
8
|
-
[ary, hsh].each do |obj|
|
9
|
-
fetching_ary = Fetching [obj]
|
10
|
-
expect(fetching_ary.first).to equal(obj)
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
specify "#map" do
|
15
|
-
ary = [1, 2]
|
16
|
-
fetching_ary = Fetching(ary)
|
17
|
-
expect(fetching_ary.map(&:to_s)).to eq(%w(1 2))
|
18
|
-
end
|
19
|
-
|
20
|
-
specify "Fetching should go deep" do
|
21
|
-
Fetching([{ one: 1 }]).each do |element|
|
22
|
-
expect(element.one).to eq(1)
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
specify "#first" do
|
27
|
-
ary = []
|
28
|
-
sassy_ary = Fetching(ary)
|
29
|
-
expect { sassy_ary.first }.to raise_error(IndexError)
|
30
|
-
end
|
31
|
-
|
32
|
-
describe "array methods" do
|
33
|
-
let(:array) { [1, 2, 3] }
|
34
|
-
let(:fetching) { Fetching(array) }
|
35
|
-
|
36
|
-
describe "#empty?" do
|
37
|
-
it("should be false") { expect(fetching.empty?).to be_falsy }
|
38
|
-
|
39
|
-
context "when empty" do
|
40
|
-
let(:array) { [] }
|
41
|
-
it("should be true") { expect(fetching.empty?).to be_truthy }
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
specify "#length" do
|
46
|
-
expect(fetching.length).to eq(array.length)
|
47
|
-
expect(fetching.size).to eq(array.size)
|
48
|
-
end
|
49
|
-
|
50
|
-
specify "#reverse" do
|
51
|
-
reversed = Fetching(array.reverse)
|
52
|
-
expect(fetching.reverse).to eq(reversed)
|
53
|
-
end
|
54
|
-
|
55
|
-
specify "#shuffle" do
|
56
|
-
seed = 1
|
57
|
-
shuffled = Fetching(array.shuffle(random: Random.new(seed)))
|
58
|
-
expect(fetching.shuffle(random: Random.new(seed))).to eq(shuffled)
|
59
|
-
end
|
60
|
-
|
61
|
-
specify "#sort" do
|
62
|
-
sorter = ->(x, y) { y <=> x }
|
63
|
-
sorted = Fetching(array.sort(&sorter))
|
64
|
-
expect(fetching.sort(&sorter)).to eq(sorted)
|
65
|
-
end
|
66
|
-
|
67
|
-
specify "#sort_by" do
|
68
|
-
sorter = ->(i) { 1.0 / i }
|
69
|
-
sorted = Fetching(array.sort_by(&sorter))
|
70
|
-
expect(fetching.sort_by(&sorter)).to eq(sorted)
|
71
|
-
end
|
72
|
-
|
73
|
-
describe "#values_at" do
|
74
|
-
specify "happy path" do
|
75
|
-
at = [0, 2]
|
76
|
-
values = Fetching(array.values_at(*at))
|
77
|
-
expect(fetching.values_at(*at)).to eq(values)
|
78
|
-
end
|
79
|
-
specify "out of bounds" do
|
80
|
-
at = 5
|
81
|
-
expected_message = "index #{at} outside of array bounds: -3...3"
|
82
|
-
expect { fetching.values_at(at) }.to raise_error(IndexError, expected_message)
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
end
|
87
|
-
|
88
|
-
end
|
@@ -1,35 +0,0 @@
|
|
1
|
-
# Adapted from https://github.com/bronson/vim-runtest/blob/master/rspec_formatter.rb.
|
2
|
-
require "rspec/core/formatters/base_text_formatter"
|
3
|
-
|
4
|
-
class VimFormatter < RSpec::Core::Formatters::BaseTextFormatter
|
5
|
-
|
6
|
-
def example_failed example
|
7
|
-
exception = example.execution_result[:exception]
|
8
|
-
path = Regexp.last_match[1] if exception.backtrace.find do |frame|
|
9
|
-
frame =~ %r{\b(spec/.*_spec\.rb:\d+)(?::|\z)}
|
10
|
-
end
|
11
|
-
message = format_message exception.message
|
12
|
-
path = format_caller(path || " ")
|
13
|
-
output.puts "#{path}: #{example.example_group.description.strip} " \
|
14
|
-
"#{example.description.strip}: #{message.strip}" if path
|
15
|
-
end
|
16
|
-
|
17
|
-
def example_pending *_args; end
|
18
|
-
|
19
|
-
def dump_failures *_args; end
|
20
|
-
|
21
|
-
def dump_pending *_args; end
|
22
|
-
|
23
|
-
def message _msg; end
|
24
|
-
|
25
|
-
def dump_summary *_args; end
|
26
|
-
|
27
|
-
def seed *_args; end
|
28
|
-
|
29
|
-
private
|
30
|
-
|
31
|
-
def format_message msg
|
32
|
-
msg.gsub("\n", " ")[0, 80]
|
33
|
-
end
|
34
|
-
|
35
|
-
end
|