api_bee 0.0.1 → 0.0.2
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.mkd +22 -0
- data/examples/github_api.rb +104 -0
- data/examples/yaml_catalog.rb +8 -0
- data/lib/api_bee/adapters/hash.rb +5 -1
- data/lib/api_bee/node.rb +36 -16
- data/lib/api_bee/proxy.rb +32 -3
- data/lib/api_bee/version.rb +1 -1
- data/spec/hash_adapter_spec.rb +36 -14
- data/spec/node_spec.rb +93 -5
- metadata +3 -2
data/README.mkd
CHANGED
@@ -61,6 +61,24 @@ api.get('/my/resources').each do |r|
|
|
61
61
|
end
|
62
62
|
```
|
63
63
|
|
64
|
+
## finding a single resource
|
65
|
+
|
66
|
+
There's a special find_one method that you can call on lists. It delegates to the adapter and it's useful for finding a single resource in the context of a paginated list.
|
67
|
+
|
68
|
+
resources = api.get('/my/resources')
|
69
|
+
resource = resources.find_one('foobar')
|
70
|
+
|
71
|
+
That delegates to Adapter#find_one passing 2 arguments: the list's href and the passed name or identifier, so:
|
72
|
+
|
73
|
+
```ruby
|
74
|
+
class ApiBee::Adapters::Special
|
75
|
+
# ...
|
76
|
+
def find_one(href, id)
|
77
|
+
get "#{href}/#{id}"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
```
|
81
|
+
|
64
82
|
## Lazy loading
|
65
83
|
|
66
84
|
ApiBee wraps your adapters in lazy-loading objects. API calls will only be issued when accessing or iterating data.
|
@@ -117,3 +135,7 @@ products.has_prev_page? # => true
|
|
117
135
|
|
118
136
|
products.prev_page # => 1
|
119
137
|
```
|
138
|
+
|
139
|
+
## Examples
|
140
|
+
|
141
|
+
See examples/github_api.rb for an adapter that paginates Github's API by decorating it's results with ApiBee's required pagination properties
|
@@ -0,0 +1,104 @@
|
|
1
|
+
$LOAD_PATH.unshift '../lib'
|
2
|
+
require 'api_bee'
|
3
|
+
#require 'net/http'
|
4
|
+
require 'net/https'
|
5
|
+
require 'uri'
|
6
|
+
require 'json'
|
7
|
+
|
8
|
+
class GithubAdapter
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
ApiBee.config.uri_property_name = :url
|
12
|
+
@url = URI.parse('https://api.github.com')
|
13
|
+
@http = Net::HTTP.new(@url.host, @url.port)
|
14
|
+
@http.use_ssl = true
|
15
|
+
@http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
16
|
+
end
|
17
|
+
|
18
|
+
def get(path, options = {})
|
19
|
+
per_page = (options[:per_page] || 20).to_i
|
20
|
+
page = (options[:page] || 1).to_i
|
21
|
+
|
22
|
+
q = options.map{|k,v| "#{k}=#{v}"}.join('&')
|
23
|
+
|
24
|
+
fullpath = "#{path}?#{q}"
|
25
|
+
|
26
|
+
request = Net::HTTP::Get.new(fullpath)
|
27
|
+
response = @http.request(request)
|
28
|
+
|
29
|
+
if response.kind_of?(Net::HTTPOK)
|
30
|
+
results = JSON.parse response.body
|
31
|
+
if results.is_a?(Array)
|
32
|
+
# decorate returned array so it complies with APiBee's pagination params
|
33
|
+
results = {
|
34
|
+
:entries => results,
|
35
|
+
:page => page,
|
36
|
+
:per_page => per_page,
|
37
|
+
:url => path
|
38
|
+
}
|
39
|
+
# Extract last page number and entries count. Github uses a 'Link' header
|
40
|
+
if link = response["link"]
|
41
|
+
last_page = extract_last_page(link) || page # if no 'last' link, we're on the last page
|
42
|
+
results.update(
|
43
|
+
:total_entries => last_page.to_i * per_page
|
44
|
+
)
|
45
|
+
end
|
46
|
+
else
|
47
|
+
results
|
48
|
+
end
|
49
|
+
|
50
|
+
results
|
51
|
+
else
|
52
|
+
nil
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
def find_one(href, id)
|
58
|
+
get id
|
59
|
+
end
|
60
|
+
|
61
|
+
protected
|
62
|
+
|
63
|
+
def extract_last_page(link)
|
64
|
+
aa = link.split('<https')
|
65
|
+
last_link = aa.find{|e| e=~ /rel="last"/}
|
66
|
+
last_link.to_s =~ /\?page=(\d+)/
|
67
|
+
$1
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
## Instantiate your wrapped API
|
73
|
+
|
74
|
+
api = ApiBee.setup(GithubAdapter)
|
75
|
+
|
76
|
+
repos = api.get('/users/ismasan/repos')
|
77
|
+
|
78
|
+
def show(data, c)
|
79
|
+
puts "+++++++++++++++ Page #{data.current_page} of #{data.total_pages} (#{data.total_entries} entries). #{data.size} now. ++++++++"
|
80
|
+
puts
|
81
|
+
data.each do |pp|
|
82
|
+
puts "#{c}.- #{pp[:id]}: #{pp[:name]}. Forks: #{pp[:forks]}. URL: #{pp[:url]}"
|
83
|
+
c += 1
|
84
|
+
end
|
85
|
+
puts
|
86
|
+
p [:next, data.next_page, data.total_entries]
|
87
|
+
if data.has_next_page? # recurse
|
88
|
+
show data.paginate(:page => data.next_page, :per_page => 20), c
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
## Auto paginate over all the repos
|
93
|
+
|
94
|
+
show repos, 1
|
95
|
+
|
96
|
+
|
97
|
+
puts "First created at is: #{repos.first[:created_at]}"
|
98
|
+
|
99
|
+
# Fetch a single node
|
100
|
+
one = repos.find_one('https://api.github.com/repos/ismasan/websockets_examples')
|
101
|
+
|
102
|
+
# one[:owner][:public_repos] will trigger a new request to the resource URL because that property is not available in the excerpt
|
103
|
+
#
|
104
|
+
puts "An owner is #{one[:owner][:login]}, who has #{one[:owner][:public_repos]} public repos"
|
data/examples/yaml_catalog.rb
CHANGED
@@ -4,9 +4,17 @@ require 'api_bee'
|
|
4
4
|
|
5
5
|
api = ApiBee.setup(:hash, YAML.load_file('./catalog.yml'))
|
6
6
|
|
7
|
+
collections = api.get('/collections')
|
8
|
+
|
9
|
+
#p collections
|
10
|
+
|
11
|
+
p collections.current_page
|
12
|
+
# p collections.size
|
13
|
+
|
7
14
|
collection = api.get('/collections/c1')
|
8
15
|
|
9
16
|
p collection[:title]
|
17
|
+
p collection[:id]
|
10
18
|
|
11
19
|
products = collection[:products]
|
12
20
|
|
@@ -25,6 +25,10 @@ module ApiBee
|
|
25
25
|
found
|
26
26
|
end
|
27
27
|
|
28
|
+
def find_one(href, id)
|
29
|
+
get("#{href}/#{id}")
|
30
|
+
end
|
31
|
+
|
28
32
|
protected
|
29
33
|
|
30
34
|
def parse_href(href)
|
@@ -60,7 +64,7 @@ module ApiBee
|
|
60
64
|
from = page * per_page - per_page
|
61
65
|
to = page * per_page
|
62
66
|
list[:entries] = list[:entries].to_a[from...to]
|
63
|
-
list[:
|
67
|
+
list[:page] = page
|
64
68
|
list[:per_page] = per_page
|
65
69
|
list
|
66
70
|
end
|
data/lib/api_bee/node.rb
CHANGED
@@ -2,25 +2,40 @@ module ApiBee
|
|
2
2
|
|
3
3
|
class Node
|
4
4
|
|
5
|
-
def self.
|
5
|
+
def self.simbolized(hash)
|
6
|
+
hash.inject({}) do |options, (key, value)|
|
7
|
+
options[(key.to_sym rescue key) || key] = value
|
8
|
+
options
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.resolve(adapter, attrs, href = nil)
|
13
|
+
attrs = simbolized(attrs)
|
6
14
|
keys = attrs.keys.map{|k| k.to_sym}
|
7
|
-
if keys.include?(:total_entries) && keys.include?(ApiBee.config.uri_property_name) # is a paginator
|
8
|
-
List.new adapter, attrs
|
15
|
+
if keys.include?(:total_entries) && keys.include?(ApiBee.config.uri_property_name.to_sym) # is a paginator
|
16
|
+
List.new adapter, attrs, href
|
9
17
|
else
|
10
|
-
Single.new adapter, attrs
|
18
|
+
Single.new adapter, attrs, href
|
11
19
|
end
|
12
20
|
end
|
13
21
|
|
14
22
|
attr_reader :adapter
|
15
23
|
|
16
|
-
def initialize(adapter, attrs)
|
24
|
+
def initialize(adapter, attrs, href)
|
17
25
|
@adapter = adapter
|
18
26
|
@attributes = {}
|
27
|
+
@href = href
|
19
28
|
update_attributes attrs
|
20
29
|
end
|
21
30
|
|
31
|
+
def to_data
|
32
|
+
@attributes
|
33
|
+
end
|
34
|
+
|
22
35
|
def [](attribute_name)
|
23
|
-
if
|
36
|
+
if respond_to?(attribute_name)
|
37
|
+
send attribute_name
|
38
|
+
elsif value = @attributes[attribute_name]
|
24
39
|
resolve_values_to_nodes value
|
25
40
|
elsif has_more? # check whether there's more info in API
|
26
41
|
load_more!
|
@@ -53,7 +68,7 @@ module ApiBee
|
|
53
68
|
|
54
69
|
def load_more!
|
55
70
|
more_data = @adapter.get(@attributes[ApiBee.config.uri_property_name])
|
56
|
-
update_attributes more_data if more_data
|
71
|
+
update_attributes Node.simbolized(more_data) if more_data
|
57
72
|
@complete = true
|
58
73
|
end
|
59
74
|
|
@@ -65,16 +80,21 @@ module ApiBee
|
|
65
80
|
|
66
81
|
DEFAULT_PER_PAGE = 100
|
67
82
|
|
83
|
+
def find_one(id)
|
84
|
+
data = @adapter.find_one(@href, id)
|
85
|
+
data.nil? ? nil : Node.resolve(@adapter, data, @href)
|
86
|
+
end
|
87
|
+
|
68
88
|
def total_entries
|
69
89
|
@attributes[:total_entries].to_i
|
70
90
|
end
|
71
91
|
|
72
92
|
def size
|
73
|
-
|
93
|
+
__entries.size
|
74
94
|
end
|
75
95
|
|
76
96
|
def current_page
|
77
|
-
(@attributes[:
|
97
|
+
(@attributes[:page] || 1).to_i
|
78
98
|
end
|
79
99
|
|
80
100
|
def per_page
|
@@ -82,7 +102,7 @@ module ApiBee
|
|
82
102
|
end
|
83
103
|
|
84
104
|
def total_pages
|
85
|
-
div = total_entries / per_page
|
105
|
+
div = (total_entries.to_f / per_page.to_f).ceil
|
86
106
|
div < 1 ? 1 : div
|
87
107
|
end
|
88
108
|
|
@@ -107,29 +127,29 @@ module ApiBee
|
|
107
127
|
end
|
108
128
|
|
109
129
|
def first
|
110
|
-
|
130
|
+
__entries.first
|
111
131
|
end
|
112
132
|
|
113
133
|
def last
|
114
|
-
|
134
|
+
__entries.last
|
115
135
|
end
|
116
136
|
|
117
137
|
def each(&block)
|
118
|
-
|
138
|
+
__entries.each(&block)
|
119
139
|
end
|
120
140
|
|
121
141
|
def each_with_index(&block)
|
122
|
-
|
142
|
+
__entries.each_with_index(&block)
|
123
143
|
end
|
124
144
|
|
125
145
|
def paginate(options = {})
|
126
146
|
data = @adapter.get(@attributes[ApiBee.config.uri_property_name], options)
|
127
|
-
Node.resolve @adapter, data
|
147
|
+
Node.resolve @adapter, data, @href
|
128
148
|
end
|
129
149
|
|
130
150
|
protected
|
131
151
|
|
132
|
-
def
|
152
|
+
def __entries
|
133
153
|
@entries ||= (self[:entries] || [])
|
134
154
|
end
|
135
155
|
|
data/lib/api_bee/proxy.rb
CHANGED
@@ -4,12 +4,41 @@ module ApiBee
|
|
4
4
|
|
5
5
|
attr_reader :adapter
|
6
6
|
|
7
|
-
def initialize(adapter)
|
7
|
+
def initialize(adapter, href = nil, opts = nil)
|
8
8
|
@adapter = adapter
|
9
|
+
@href = href
|
10
|
+
@opts = opts
|
9
11
|
end
|
10
12
|
|
11
|
-
def get(href)
|
12
|
-
|
13
|
+
def get(href, opts = {})
|
14
|
+
# Just delegate. No API calls at this point. We only load data when we need it.
|
15
|
+
Proxy.new @adapter, href, opts
|
16
|
+
end
|
17
|
+
|
18
|
+
def [](key)
|
19
|
+
_node[key]
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_data
|
23
|
+
_node.to_data
|
24
|
+
end
|
25
|
+
|
26
|
+
def paginate(*args)
|
27
|
+
@list ||= Node::List.new(@adapter, {ApiBee.config.uri_property_name => @href}, @href)
|
28
|
+
@list.paginate *args
|
29
|
+
end
|
30
|
+
|
31
|
+
protected
|
32
|
+
|
33
|
+
def method_missing(method_name, *args, &block)
|
34
|
+
_node.send(method_name, *args, &block)
|
35
|
+
end
|
36
|
+
|
37
|
+
def _node
|
38
|
+
@node ||= (
|
39
|
+
data = @adapter.get(@href, @opts)
|
40
|
+
Node.resolve @adapter, data, @href
|
41
|
+
)
|
13
42
|
end
|
14
43
|
|
15
44
|
end
|
data/lib/api_bee/version.rb
CHANGED
data/spec/hash_adapter_spec.rb
CHANGED
@@ -12,8 +12,8 @@ describe ApiBee::Adapters::Hash do
|
|
12
12
|
:id => 'catalog',
|
13
13
|
:foos => [1,2,3,4],
|
14
14
|
:products => {
|
15
|
-
:total_entries =>
|
16
|
-
:
|
15
|
+
:total_entries => 5,
|
16
|
+
:page => 1,
|
17
17
|
:per_page => 4,
|
18
18
|
:href => '/collections/catalog/products',
|
19
19
|
:entries => [
|
@@ -35,7 +35,12 @@ describe ApiBee::Adapters::Hash do
|
|
35
35
|
:id => 'foo-4',
|
36
36
|
:title => 'Foo 4',
|
37
37
|
:href => '/products/foo-4'
|
38
|
-
}
|
38
|
+
},
|
39
|
+
{
|
40
|
+
:id => 'foo-5',
|
41
|
+
:title => 'Foo 5',
|
42
|
+
:href => '/products/foo-5'
|
43
|
+
}
|
39
44
|
]
|
40
45
|
}
|
41
46
|
}
|
@@ -45,6 +50,12 @@ describe ApiBee::Adapters::Hash do
|
|
45
50
|
@adapter = ApiBee::Adapters::Hash.new(@data)
|
46
51
|
end
|
47
52
|
|
53
|
+
context 'non-existing data' do
|
54
|
+
it 'should return nil' do
|
55
|
+
@adapter.get('/foo/lolz').should be_nil
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
48
59
|
context 'accessing single nodes' do
|
49
60
|
|
50
61
|
before do
|
@@ -64,20 +75,31 @@ describe ApiBee::Adapters::Hash do
|
|
64
75
|
it 'should return whole collection if no pagination' do
|
65
76
|
products = @adapter.get('/collections/catalog/products')
|
66
77
|
# products.should == 1
|
67
|
-
products[:
|
68
|
-
products[:total_entries].should ==
|
78
|
+
products[:page].should == 1
|
79
|
+
products[:total_entries].should == 5
|
69
80
|
products[:per_page].should == 4
|
70
|
-
products[:entries].size.should ==
|
81
|
+
products[:entries].size.should == 5
|
71
82
|
end
|
72
83
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
84
|
+
describe 'paginating' do
|
85
|
+
it 'should paginate paginated collections' do
|
86
|
+
products = @adapter.get('/collections/catalog/products', :page => 2, :per_page => 2)
|
87
|
+
products[:page].should == 2
|
88
|
+
products[:total_entries].should == 5
|
89
|
+
products[:per_page].should == 2
|
90
|
+
products[:entries].size.should == 2
|
91
|
+
products[:entries][0][:title].should == 'Foo 3'
|
92
|
+
products[:entries][1][:title].should == 'Foo 4'
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'should paginate last page correctly' do
|
96
|
+
products = @adapter.get('/collections/catalog/products', :page => 3, :per_page => 2)
|
97
|
+
products[:page].should == 3
|
98
|
+
products[:total_entries].should == 5
|
99
|
+
products[:per_page].should == 2
|
100
|
+
products[:entries].size.should == 1
|
101
|
+
products[:entries][0][:title].should == 'Foo 5'
|
102
|
+
end
|
81
103
|
end
|
82
104
|
end
|
83
105
|
|
data/spec/node_spec.rb
CHANGED
@@ -7,7 +7,7 @@ describe ApiBee do
|
|
7
7
|
# Products
|
8
8
|
:products => {
|
9
9
|
:href => '/products',
|
10
|
-
:total_entries =>
|
10
|
+
:total_entries => 7,
|
11
11
|
:entries => [
|
12
12
|
{
|
13
13
|
:title => 'Foo 1',
|
@@ -44,6 +44,12 @@ describe ApiBee do
|
|
44
44
|
:id => 'foo-6',
|
45
45
|
:price => 600,
|
46
46
|
:description => 'Foo 6 desc'
|
47
|
+
},
|
48
|
+
{
|
49
|
+
:title => 'Foo 7',
|
50
|
+
:id => 'foo-7',
|
51
|
+
:price => 700,
|
52
|
+
:description => 'Foo 7 desc'
|
47
53
|
}
|
48
54
|
]
|
49
55
|
},
|
@@ -55,7 +61,7 @@ describe ApiBee do
|
|
55
61
|
:products => {
|
56
62
|
:href => '/products',
|
57
63
|
:total_entries => 4,
|
58
|
-
:
|
64
|
+
:page => 1,
|
59
65
|
:per_page => 2,
|
60
66
|
:href => '/products',
|
61
67
|
:entries => [
|
@@ -89,6 +95,19 @@ describe ApiBee do
|
|
89
95
|
node.should be_kind_of(ApiBee::Node::Single)
|
90
96
|
end
|
91
97
|
|
98
|
+
it 'should symbolize hash keys' do
|
99
|
+
node = ApiBee::Node.resolve(@adapter, {
|
100
|
+
'title' => 'Blah',
|
101
|
+
'total_entries' => 4,
|
102
|
+
'href' => '/products',
|
103
|
+
'foos' => [1,2,3,4]
|
104
|
+
})
|
105
|
+
node.total_entries.should == 4
|
106
|
+
node[:foos].should == [1,2,3,4]
|
107
|
+
node.adapter.should == @adapter
|
108
|
+
node.should be_kind_of(ApiBee::Node::List)
|
109
|
+
end
|
110
|
+
|
92
111
|
it 'should resolve paginated lists' do
|
93
112
|
node = ApiBee::Node.resolve(@adapter, {:title => 'Blah', :total_entries => 4, :href => '/products'})
|
94
113
|
node.total_entries.should == 4
|
@@ -112,14 +131,83 @@ describe ApiBee do
|
|
112
131
|
describe 'single nodes' do
|
113
132
|
it 'should call adapter only when accessing needed attributes' do
|
114
133
|
hash = @data[:collections].last
|
115
|
-
@adapter.should_receive(:get).exactly(1).times.with('/collections/catalog').and_return hash
|
134
|
+
@adapter.should_receive(:get).exactly(1).times.with('/collections/catalog', {}).and_return hash
|
116
135
|
node = @api.get('/collections/catalog')
|
117
136
|
node[:title].should == 'Catalog'
|
118
137
|
node[:id].should == 'catalog'
|
119
138
|
end
|
120
139
|
end
|
121
140
|
|
122
|
-
describe '
|
141
|
+
describe '#find_one' do
|
142
|
+
|
143
|
+
before do
|
144
|
+
@products = @api.get('/products', :page => 1, :per_page => 2)
|
145
|
+
end
|
146
|
+
|
147
|
+
it 'should delegate to adapter. It knows how to find individual resoruces' do
|
148
|
+
@adapter.should_receive(:find_one).with('/products', 'foo-1')
|
149
|
+
@products.find_one('foo-1')
|
150
|
+
end
|
151
|
+
|
152
|
+
it 'should return a Node::Single' do
|
153
|
+
node = @products.find_one('foo-1')
|
154
|
+
node.should be_kind_of(ApiBee::Node::Single)
|
155
|
+
node[:title].should == 'Foo 1'
|
156
|
+
end
|
157
|
+
|
158
|
+
it 'should return nil if not found' do
|
159
|
+
@products.find_one('foo-1000').should be_nil
|
160
|
+
end
|
161
|
+
|
162
|
+
end
|
163
|
+
|
164
|
+
end
|
165
|
+
|
166
|
+
context 'navigating data' do
|
167
|
+
|
168
|
+
before do
|
169
|
+
@api = ApiBee.setup(:hash, @data)
|
170
|
+
end
|
171
|
+
|
172
|
+
describe '#to_data' do
|
173
|
+
it 'should return raw data' do
|
174
|
+
d = @api.get('/collections/catalog').to_data
|
175
|
+
d.should be_kind_of(::Hash)
|
176
|
+
d.should == @data[:collections].first
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
describe 'paginated root level lists' do
|
181
|
+
|
182
|
+
before do
|
183
|
+
@products = @api.get('/products', :page => 1, :per_page => 2)
|
184
|
+
end
|
185
|
+
|
186
|
+
it 'should have a paginator interface' do
|
187
|
+
|
188
|
+
@products.total_entries.should == 7
|
189
|
+
@products.size.should == 2
|
190
|
+
@products.total_pages.should == 4
|
191
|
+
@products.current_page.should == 1
|
192
|
+
@products.pages.should == [1,2,3,4]
|
193
|
+
@products.has_next_page?.should be_true
|
194
|
+
@products.has_prev_page?.should be_false
|
195
|
+
end
|
196
|
+
|
197
|
+
it 'should paginate last page correctly' do
|
198
|
+
last_page = @products.paginate(:per_page => 2, :page =>4)
|
199
|
+
|
200
|
+
last_page.total_entries.should == 7
|
201
|
+
last_page.size.should == 1
|
202
|
+
last_page.total_pages.should == 4
|
203
|
+
last_page.current_page.should == 4
|
204
|
+
last_page.pages.should == [1,2,3,4]
|
205
|
+
last_page.has_next_page?.should be_false
|
206
|
+
last_page.has_prev_page?.should be_true
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
describe 'paginated nested lists' do
|
123
211
|
before do
|
124
212
|
@collection = @api.get('/collections/catalog')
|
125
213
|
@products = @collection[:products]
|
@@ -153,7 +241,7 @@ describe ApiBee do
|
|
153
241
|
@products.each {|p| titles << p[:title]}
|
154
242
|
@products.each {|p| klasses << p.class}
|
155
243
|
@products.current_page.should == 2
|
156
|
-
@products.total_entries.should ==
|
244
|
+
@products.total_entries.should == 7
|
157
245
|
@products.size.should == 2
|
158
246
|
klasses.should == [ApiBee::Node::Single, ApiBee::Node::Single]
|
159
247
|
titles.should == ['Foo 3', 'Foo 4']
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: api_bee
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.0.
|
5
|
+
version: 0.0.2
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Ismael Celis
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2011-09-
|
13
|
+
date: 2011-09-21 00:00:00 Z
|
14
14
|
dependencies: []
|
15
15
|
|
16
16
|
description: API Bee is a small client / spec for a particular style of JSON API. USe Hash adapter for local data access.
|
@@ -30,6 +30,7 @@ files:
|
|
30
30
|
- Rakefile
|
31
31
|
- api_bee.gemspec
|
32
32
|
- examples/catalog.yml
|
33
|
+
- examples/github_api.rb
|
33
34
|
- examples/yaml_catalog.rb
|
34
35
|
- lib/api_bee.rb
|
35
36
|
- lib/api_bee/adapters/hash.rb
|