fetchable 0.0.2 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Gem Version](https://badge.fury.io/rb/keyword_curry.png)](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
|