fetchable 0.0.2 → 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.
- data/README.md +37 -20
- data/lib/fetchable.rb +9 -11
- data/lib/fetchable/decorator.rb +11 -0
- data/lib/fetchable/version.rb +3 -1
- data/spec/fetchable/decorator_spec.rb +37 -0
- data/spec/{lib/fetchable_spec.rb → fetchable_spec.rb} +20 -21
- metadata +7 -4
data/README.md
CHANGED
@@ -1,16 +1,22 @@
|
|
1
1
|
# Fetchable
|
2
2
|
|
3
|
-
|
3
|
+
[](http://badge.fury.io/rb/keyword_curry)
|
4
4
|
|
5
|
-
|
6
|
-
underlying collection, the default is `[]`.
|
5
|
+
Provides a mixin and decorator to add a `Hash#fetch` like interface to any object.
|
7
6
|
|
8
|
-
|
7
|
+
You must define a `[]` subscript method for raw access to the fetchable data.
|
8
|
+
|
9
|
+
Your `[]` method must return anything but nil in order for `#fetch` to consider
|
10
|
+
a key successfully fetched. `False` is considered sucessful.
|
9
11
|
|
10
12
|
`Hash#Fetch` is one of my favourite Ruby methods and can be tricky to implement
|
11
13
|
its full behaviour so here it is extracted for you to add to whichever object
|
12
14
|
you choose.
|
13
15
|
|
16
|
+
If you're not familiar with `Hash#fetch` it's a great way to help eliminate nils
|
17
|
+
as it raises an error when the desired key is not found. For more info consult
|
18
|
+
[Ruby Hash documentation](http://www.ruby-doc.org/core-2.1.0/Hash.html#method-i-fetch).
|
19
|
+
|
14
20
|
## Installation
|
15
21
|
|
16
22
|
Add this line to your application's Gemfile:
|
@@ -27,50 +33,61 @@ Or install it yourself as:
|
|
27
33
|
|
28
34
|
## Usage
|
29
35
|
|
30
|
-
###
|
36
|
+
### Include into a object with a `[]` method
|
31
37
|
|
32
38
|
```ruby
|
33
39
|
|
34
40
|
require "fetchable"
|
35
41
|
|
36
|
-
|
37
|
-
|
38
|
-
fetchable_array = Fetchable.new(array)
|
42
|
+
things = %w(zero one two).extend(Fetchable)
|
39
43
|
|
40
|
-
|
44
|
+
things.fetch(0)
|
41
45
|
=> "zero"
|
42
46
|
|
43
|
-
|
47
|
+
things.fetch(2)
|
44
48
|
=> "two"
|
45
49
|
|
46
|
-
|
47
|
-
=> KeyError key not found 3
|
50
|
+
things.fetch(3)
|
51
|
+
=> KeyError: key not found 3
|
48
52
|
|
49
|
-
|
53
|
+
things.fetch(3, "three")
|
50
54
|
=> "three"
|
51
55
|
|
52
|
-
|
56
|
+
things.fetch(3) { "Execute a block!" }
|
53
57
|
=> "Execute a block!"
|
54
58
|
|
55
|
-
|
59
|
+
things.fetch(3) { |key| "Do something based on missing key #{key}" }
|
56
60
|
=> "Do something based on missing key 3"
|
57
61
|
|
58
62
|
```
|
59
63
|
|
60
|
-
###
|
64
|
+
### Prefer composition over inheritance?
|
61
65
|
|
62
|
-
|
66
|
+
We got you covered! Use `Fetchable::Decorator` instead.
|
63
67
|
|
64
68
|
```ruby
|
65
69
|
|
66
|
-
|
67
|
-
|
70
|
+
require "fetchable/decorator"
|
71
|
+
|
72
|
+
things = %w(zero one two)
|
73
|
+
|
74
|
+
fetchable_things = Fetchable::Decorator.new(things)
|
68
75
|
|
69
|
-
|
76
|
+
fetchable_things.fetch(1)
|
70
77
|
=> "one"
|
71
78
|
|
72
79
|
```
|
73
80
|
|
81
|
+
### For bonus points use lambdas
|
82
|
+
|
83
|
+
Lambdas, procs and method objects can also be called with `#[]`.
|
84
|
+
|
85
|
+
Why not make them fetchable?
|
86
|
+
|
87
|
+
It might be funny.
|
88
|
+
|
89
|
+
Dammit method, you better not return me a `nil`, I'll be so mad.
|
90
|
+
|
74
91
|
## Contributing
|
75
92
|
|
76
93
|
1. Fork it
|
data/lib/fetchable.rb
CHANGED
@@ -1,18 +1,16 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
class Fetchable < SimpleDelegator
|
4
|
-
def initialize(collection, args={})
|
5
|
-
@collection = collection
|
6
|
-
@finder_method_name = args.fetch(:finder_method, :[])
|
7
|
-
super(collection)
|
8
|
-
end
|
9
|
-
|
1
|
+
module Fetchable
|
10
2
|
def fetch(key, not_found_value = no_default_given, &block)
|
11
3
|
if not_found_value != no_default_given && block
|
12
4
|
raise ArgumentError.new("Cannot provide both a default arg and block to #fetch")
|
13
5
|
end
|
14
6
|
|
15
|
-
|
7
|
+
result = public_send(:[], key)
|
8
|
+
|
9
|
+
if result.nil?
|
10
|
+
default_value(key, not_found_value, &block)
|
11
|
+
else
|
12
|
+
result
|
13
|
+
end
|
16
14
|
end
|
17
15
|
|
18
16
|
private
|
@@ -26,7 +24,7 @@ class Fetchable < SimpleDelegator
|
|
26
24
|
if block
|
27
25
|
block.call(key)
|
28
26
|
else
|
29
|
-
raise KeyError.new("
|
27
|
+
raise KeyError.new("key not found #{key}")
|
30
28
|
end
|
31
29
|
else
|
32
30
|
not_found_value
|
data/lib/fetchable/version.rb
CHANGED
@@ -0,0 +1,37 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
require "fetchable/decorator"
|
4
|
+
|
5
|
+
describe Fetchable::Decorator do
|
6
|
+
subject(:fetchable) {
|
7
|
+
Fetchable::Decorator.new(collection)
|
8
|
+
}
|
9
|
+
|
10
|
+
let(:collection) { double(:collection, :[] => fetched_object) }
|
11
|
+
|
12
|
+
let(:fetched_object) { double(:fetched_object) }
|
13
|
+
let(:fetch_key) { double(:fetch_key) }
|
14
|
+
|
15
|
+
it "is a true decorator" do
|
16
|
+
expect(collection).to receive(:i_am_a_decorator_and_forward_all_messages)
|
17
|
+
.with("some", "args")
|
18
|
+
|
19
|
+
fetchable.i_am_a_decorator_and_forward_all_messages("some", "args")
|
20
|
+
end
|
21
|
+
|
22
|
+
it "is fetchable" do
|
23
|
+
expect(fetchable).to be_a(Fetchable)
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "#fetch" do
|
27
|
+
it "delegates to the collection's #[] method" do
|
28
|
+
fetchable.fetch(fetch_key)
|
29
|
+
|
30
|
+
expect(collection).to have_received(:[]).with(fetch_key)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "returns the entry from the collection" do
|
34
|
+
expect(fetchable.fetch(fetch_key)).to be fetched_object
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -3,33 +3,18 @@ require "spec_helper"
|
|
3
3
|
require "fetchable"
|
4
4
|
|
5
5
|
describe Fetchable do
|
6
|
-
subject(:fetchable) {
|
7
|
-
|
8
|
-
let(:collection) {
|
9
|
-
double(:collection, finder_method => fetched_object)
|
6
|
+
subject(:fetchable) {
|
7
|
+
double(:fetchable, :[] => fetched_object).extend(Fetchable)
|
10
8
|
}
|
11
9
|
|
12
|
-
let(:finder_method) { :[] }
|
13
10
|
let(:fetched_object) { double(:fetched_object) }
|
14
11
|
let(:fetch_key) { double(:fetch_key) }
|
15
12
|
|
16
|
-
it "is a true decorator" do
|
17
|
-
expect(collection).to receive(:arbitrary).with("an arg")
|
18
|
-
|
19
|
-
fetchable.arbitrary("an arg")
|
20
|
-
end
|
21
|
-
|
22
|
-
it "defaults the finder method to []" do
|
23
|
-
expect(
|
24
|
-
Fetchable.new(collection).fetch(fetch_key)
|
25
|
-
).to be fetched_object
|
26
|
-
end
|
27
|
-
|
28
13
|
describe "#fetch" do
|
29
|
-
it "delegates to the
|
14
|
+
it "delegates to the fetchable's finder method" do
|
30
15
|
fetchable.fetch(fetch_key)
|
31
16
|
|
32
|
-
expect(
|
17
|
+
expect(fetchable).to have_received(:[]).with(fetch_key)
|
33
18
|
end
|
34
19
|
|
35
20
|
context "when entry for key exists" do
|
@@ -39,7 +24,21 @@ describe Fetchable do
|
|
39
24
|
}.not_to raise_error
|
40
25
|
end
|
41
26
|
|
42
|
-
it "returns the entry from the
|
27
|
+
it "returns the entry from the fetchable" do
|
28
|
+
expect(fetchable.fetch(fetch_key)).to be fetched_object
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
context "when the enrty for the key comes back false" do
|
33
|
+
let(:fetched_object) { false }
|
34
|
+
|
35
|
+
it "does not execute the block" do
|
36
|
+
expect {
|
37
|
+
fetchable.fetch(fetch_key) { raise "This block must not run" }
|
38
|
+
}.not_to raise_error
|
39
|
+
end
|
40
|
+
|
41
|
+
it "returns the entry from the fetchable" do
|
43
42
|
expect(fetchable.fetch(fetch_key)).to be fetched_object
|
44
43
|
end
|
45
44
|
end
|
@@ -84,7 +83,7 @@ describe Fetchable do
|
|
84
83
|
|
85
84
|
context "no default or block given" do
|
86
85
|
it "raises record not found" do
|
87
|
-
expect{ fetchable.fetch(fetch_key) }.to raise_error(KeyError)
|
86
|
+
expect{ fetchable.fetch(fetch_key) }.to raise_error(KeyError, "key not found #{fetch_key}")
|
88
87
|
end
|
89
88
|
end
|
90
89
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fetchable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2013-10-
|
13
|
+
date: 2013-10-29 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: bundler
|
@@ -78,8 +78,10 @@ files:
|
|
78
78
|
- Rakefile
|
79
79
|
- fetchable.gemspec
|
80
80
|
- lib/fetchable.rb
|
81
|
+
- lib/fetchable/decorator.rb
|
81
82
|
- lib/fetchable/version.rb
|
82
|
-
- spec/
|
83
|
+
- spec/fetchable/decorator_spec.rb
|
84
|
+
- spec/fetchable_spec.rb
|
83
85
|
- spec/spec_helper.rb
|
84
86
|
homepage: https://github.com/bestie/fetchable
|
85
87
|
licenses:
|
@@ -107,5 +109,6 @@ signing_key:
|
|
107
109
|
specification_version: 3
|
108
110
|
summary: Provides a decorator to add a Hash#fetch style interface to any object.
|
109
111
|
test_files:
|
110
|
-
- spec/
|
112
|
+
- spec/fetchable/decorator_spec.rb
|
113
|
+
- spec/fetchable_spec.rb
|
111
114
|
- spec/spec_helper.rb
|