her 0.1.7 → 0.1.8
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/LICENSE +7 -3
- data/README.md +82 -40
- data/Rakefile +1 -1
- data/her.gemspec +2 -2
- data/lib/her.rb +1 -1
- data/lib/her/api.rb +48 -32
- data/lib/her/middleware/default_parse_json.rb +18 -8
- data/lib/her/model.rb +3 -1
- data/lib/her/model/hooks.rb +52 -12
- data/lib/her/model/http.rb +142 -0
- data/lib/her/model/introspection.rb +32 -0
- data/lib/her/model/orm.rb +46 -20
- data/lib/her/model/relationships.rb +51 -16
- data/lib/her/version.rb +1 -1
- data/spec/api_spec.rb +25 -4
- data/spec/middleware/default_parse_json_spec.rb +24 -0
- data/spec/model/hooks_spec.rb +80 -80
- data/spec/model/http_spec.rb +58 -0
- data/spec/model/introspection_spec.rb +27 -0
- data/spec/model/orm_spec.rb +8 -0
- metadata +15 -10
data/lib/her/version.rb
CHANGED
data/spec/api_spec.rb
CHANGED
@@ -17,7 +17,20 @@ describe Her::API do
|
|
17
17
|
@api.base_uri.should == "https://api.example.com"
|
18
18
|
end # }}}
|
19
19
|
|
20
|
-
it "sets middleware" do # {{{
|
20
|
+
it "sets additional middleware" do # {{{
|
21
|
+
class Foo < Faraday::Response::Middleware; end;
|
22
|
+
class Bar < Faraday::Response::Middleware; end;
|
23
|
+
|
24
|
+
@api = Her::API.new
|
25
|
+
@api.setup :base_uri => "https://api.example.com", :add_middleware => [Foo, Bar]
|
26
|
+
@api.middleware.should == [Foo, Bar, Her::Middleware::DefaultParseJSON, Faraday::Request::UrlEncoded, Faraday::Adapter::NetHttp]
|
27
|
+
|
28
|
+
@api = Her::API.new
|
29
|
+
@api.setup :base_uri => "https://api.example.com", :add_middleware => Foo
|
30
|
+
@api.middleware.should == [Foo, Her::Middleware::DefaultParseJSON, Faraday::Request::UrlEncoded, Faraday::Adapter::NetHttp]
|
31
|
+
end # }}}
|
32
|
+
|
33
|
+
it "overrides middleware" do # {{{
|
21
34
|
class Foo < Faraday::Response::Middleware; end;
|
22
35
|
class Bar < Faraday::Response::Middleware; end;
|
23
36
|
|
@@ -25,6 +38,14 @@ describe Her::API do
|
|
25
38
|
@api.setup :base_uri => "https://api.example.com", :middleware => [Foo, Bar]
|
26
39
|
@api.middleware.should == [Foo, Bar]
|
27
40
|
end # }}}
|
41
|
+
|
42
|
+
it "sets a parse middleware" do # {{{
|
43
|
+
class Foo < Faraday::Response::Middleware; end;
|
44
|
+
|
45
|
+
@api = Her::API.new
|
46
|
+
@api.setup :base_uri => "https://api.example.com", :parse_middleware => Foo
|
47
|
+
@api.middleware.should == [Foo, Faraday::Request::UrlEncoded, Faraday::Adapter::NetHttp]
|
48
|
+
end # }}}
|
28
49
|
end
|
29
50
|
|
30
51
|
describe "#request" do
|
@@ -45,7 +66,7 @@ describe Her::API do
|
|
45
66
|
end # }}}
|
46
67
|
|
47
68
|
it "parses a request with the default parser" do # {{{
|
48
|
-
FakeWeb.register_uri(:get, "https://api.example.com/users/1", :body =>
|
69
|
+
FakeWeb.register_uri(:get, "https://api.example.com/users/1", :body => MultiJson.dump(:data => { :id => 1, :name => "George Michael Bluth" }, :errors => ["This is a single error"], :metadata => { :page => 1, :per_page => 10 }))
|
49
70
|
|
50
71
|
@api = Her::API.new
|
51
72
|
@api.setup :base_uri => "https://api.example.com"
|
@@ -57,7 +78,7 @@ describe Her::API do
|
|
57
78
|
end # }}}
|
58
79
|
|
59
80
|
it "parses a request with a custom parser" do # {{{
|
60
|
-
FakeWeb.register_uri(:get, "https://api.example.com/users/1", :body =>
|
81
|
+
FakeWeb.register_uri(:get, "https://api.example.com/users/1", :body => MultiJson.dump(:id => 1, :name => "George Michael Bluth"))
|
61
82
|
|
62
83
|
class CustomParser < Faraday::Response::Middleware
|
63
84
|
def on_complete(env)
|
@@ -73,7 +94,7 @@ describe Her::API do
|
|
73
94
|
end
|
74
95
|
|
75
96
|
@api = Her::API.new
|
76
|
-
@api.setup :base_uri => "https://api.example.com", :
|
97
|
+
@api.setup :base_uri => "https://api.example.com", :parse_middleware => CustomParser
|
77
98
|
@api.request(:_method => :get, :_path => "users/1") do |parsed_data|
|
78
99
|
parsed_data[:data].should == { :id => 1, :name => "George Michael Bluth" }
|
79
100
|
parsed_data[:errors].should == []
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Her::Middleware::DefaultParseJSON do
|
4
|
+
subject { described_class.new }
|
5
|
+
let(:body) { "{\"data\": 1, \"errors\": 2, \"metadata\": 3}" }
|
6
|
+
|
7
|
+
it "parses body as json" do
|
8
|
+
subject.parse(body).tap do |json|
|
9
|
+
json[:data].should == 1
|
10
|
+
json[:errors].should == 2
|
11
|
+
json[:metadata].should == 3
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
it "parses :body key as json in the env hash" do
|
16
|
+
env = { :body => body }
|
17
|
+
subject.on_complete(env)
|
18
|
+
env[:body].tap do |json|
|
19
|
+
json[:data].should == 1
|
20
|
+
json[:errors].should == 2
|
21
|
+
json[:metadata].should == 3
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/spec/model/hooks_spec.rb
CHANGED
@@ -11,103 +11,103 @@ describe Her::Model::Hooks do
|
|
11
11
|
end # }}}
|
12
12
|
|
13
13
|
describe "method hooks" do
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
14
|
+
it "handles “before save” method hooks" do # {{{
|
15
|
+
User.before_save :set_internal_id
|
16
|
+
User.send(:hooks)[:before_save].length.should == 1
|
17
|
+
User.send(:hooks)[:before_save].first.class.should == Symbol
|
18
|
+
end # }}}
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
20
|
+
it "handles “before create” method hooks" do # {{{
|
21
|
+
User.before_create :set_internal_id
|
22
|
+
User.send(:hooks)[:before_create].length.should == 1
|
23
|
+
User.send(:hooks)[:before_create].first.class.should == Symbol
|
24
|
+
end # }}}
|
25
25
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
26
|
+
it "handles “before update” method hooks" do # {{{
|
27
|
+
User.before_update :set_internal_id
|
28
|
+
User.send(:hooks)[:before_update].length.should == 1
|
29
|
+
User.send(:hooks)[:before_update].first.class.should == Symbol
|
30
|
+
end # }}}
|
31
31
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
32
|
+
it "handles “before destroy” method hooks" do # {{{
|
33
|
+
User.before_destroy :set_internal_id
|
34
|
+
User.send(:hooks)[:before_destroy].length.should == 1
|
35
|
+
User.send(:hooks)[:before_destroy].first.class.should == Symbol
|
36
|
+
end # }}}
|
37
37
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
38
|
+
it "handles “after save” method hooks" do # {{{
|
39
|
+
User.after_save :set_internal_id
|
40
|
+
User.send(:hooks)[:after_save].length.should == 1
|
41
|
+
User.send(:hooks)[:after_save].first.class.should == Symbol
|
42
|
+
end # }}}
|
43
43
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
44
|
+
it "handles “after create” method hooks" do # {{{
|
45
|
+
User.after_create :set_internal_id
|
46
|
+
User.send(:hooks)[:after_create].length.should == 1
|
47
|
+
User.send(:hooks)[:after_create].first.class.should == Symbol
|
48
|
+
end # }}}
|
49
49
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
50
|
+
it "handles “after update” method hooks" do # {{{
|
51
|
+
User.after_update :set_internal_id
|
52
|
+
User.send(:hooks)[:after_update].length.should == 1
|
53
|
+
User.send(:hooks)[:after_update].first.class.should == Symbol
|
54
|
+
end # }}}
|
55
55
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
56
|
+
it "handles “after destroy” method hooks" do # {{{
|
57
|
+
User.after_destroy :set_internal_id
|
58
|
+
User.send(:hooks)[:after_destroy].length.should == 1
|
59
|
+
User.send(:hooks)[:after_destroy].first.class.should == Symbol
|
60
|
+
end # }}}
|
61
61
|
end
|
62
62
|
|
63
63
|
describe "block hooks" do
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
64
|
+
it "handles “before save” block hooks" do # {{{
|
65
|
+
User.before_save { |record| record.internal_id = 42 }
|
66
|
+
User.send(:hooks)[:before_save].length.should == 1
|
67
|
+
User.send(:hooks)[:before_save].first.class.should == Proc
|
68
|
+
end # }}}
|
69
69
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
70
|
+
it "handles “before create” block hooks" do # {{{
|
71
|
+
User.before_create { |record| record.internal_id = 42 }
|
72
|
+
User.send(:hooks)[:before_create].length.should == 1
|
73
|
+
User.send(:hooks)[:before_create].first.class.should == Proc
|
74
|
+
end # }}}
|
75
75
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
76
|
+
it "handles “before update” block hooks" do # {{{
|
77
|
+
User.before_update { |record| record.internal_id = 42 }
|
78
|
+
User.send(:hooks)[:before_update].length.should == 1
|
79
|
+
User.send(:hooks)[:before_update].first.class.should == Proc
|
80
|
+
end # }}}
|
81
81
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
82
|
+
it "handles “before destroy” block hooks" do # {{{
|
83
|
+
User.before_destroy { |record| record.internal_id = 42 }
|
84
|
+
User.send(:hooks)[:before_destroy].length.should == 1
|
85
|
+
User.send(:hooks)[:before_destroy].first.class.should == Proc
|
86
|
+
end # }}}
|
87
87
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
88
|
+
it "handles “after save” block hooks" do # {{{
|
89
|
+
User.after_save { |record| record.internal_id = 42 }
|
90
|
+
User.send(:hooks)[:after_save].length.should == 1
|
91
|
+
User.send(:hooks)[:after_save].first.class.should == Proc
|
92
|
+
end # }}}
|
93
93
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
94
|
+
it "handles “after create” block hooks" do # {{{
|
95
|
+
User.after_create { |record| record.internal_id = 42 }
|
96
|
+
User.send(:hooks)[:after_create].length.should == 1
|
97
|
+
User.send(:hooks)[:after_create].first.class.should == Proc
|
98
|
+
end # }}}
|
99
99
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
100
|
+
it "handles “after update” block hooks" do # {{{
|
101
|
+
User.after_update { |record| record.internal_id = 42 }
|
102
|
+
User.send(:hooks)[:after_update].length.should == 1
|
103
|
+
User.send(:hooks)[:after_update].first.class.should == Proc
|
104
|
+
end # }}}
|
105
105
|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
106
|
+
it "handles “after destroy” block hooks" do # {{{
|
107
|
+
User.after_destroy { |record| record.internal_id = 42 }
|
108
|
+
User.send(:hooks)[:after_destroy].length.should == 1
|
109
|
+
User.send(:hooks)[:after_destroy].first.class.should == Proc
|
110
|
+
end # }}}
|
111
111
|
end
|
112
112
|
end
|
113
113
|
|
data/spec/model/http_spec.rb
CHANGED
@@ -99,6 +99,15 @@ describe Her::Model::HTTP do
|
|
99
99
|
User.uses_api @api
|
100
100
|
end # }}}
|
101
101
|
|
102
|
+
it "handle GET wrapper method" do # {{{
|
103
|
+
@users = User.get(:popular)
|
104
|
+
@users.length.should == 2
|
105
|
+
@users.first.id.should == 1
|
106
|
+
|
107
|
+
@user = User.get(:"1")
|
108
|
+
@user.id.should == 1
|
109
|
+
end # }}}
|
110
|
+
|
102
111
|
it "handle raw GET" do # {{{
|
103
112
|
User.get_raw("/users") do |parsed_data|
|
104
113
|
parsed_data[:data].should == [{ :id => 1 }]
|
@@ -145,5 +154,54 @@ describe Her::Model::HTTP do
|
|
145
154
|
@user = User.get_resource("/users/1")
|
146
155
|
@user.id.should == 1
|
147
156
|
end # }}}
|
157
|
+
|
158
|
+
it "handle GET collection through a symbol" do # {{{
|
159
|
+
@users = User.get_collection(:popular)
|
160
|
+
@users.length.should == 2
|
161
|
+
@users.first.id.should == 1
|
162
|
+
end # }}}
|
163
|
+
|
164
|
+
it "handle GET resource through a symbol" do # {{{
|
165
|
+
@user = User.get_resource(:"1")
|
166
|
+
@user.id.should == 1
|
167
|
+
end # }}}
|
168
|
+
|
169
|
+
it "handle raw GET through a symbol" do # {{{
|
170
|
+
User.get_raw(:popular) do |parsed_data|
|
171
|
+
parsed_data[:data].should == [{ :id => 1 }, { :id => 2 }]
|
172
|
+
end
|
173
|
+
end # }}}
|
174
|
+
end
|
175
|
+
|
176
|
+
context "setting custom requests" do
|
177
|
+
before do # {{{
|
178
|
+
@api = Her::API.new
|
179
|
+
@api.setup :base_uri => "https://api.example.com"
|
180
|
+
FakeWeb.register_uri(:get, "https://api.example.com/users/popular", :body => { :data => [{ :id => 1 }, { :id => 2 }] }.to_json)
|
181
|
+
FakeWeb.register_uri(:post, "https://api.example.com/users/from_default", :body => { :data => { :id => 4 } }.to_json)
|
182
|
+
|
183
|
+
class User
|
184
|
+
include Her::Model
|
185
|
+
end
|
186
|
+
User.custom_get :popular, :foobar
|
187
|
+
User.custom_post :from_default
|
188
|
+
end # }}}
|
189
|
+
|
190
|
+
it "handles custom methods" do # {{{
|
191
|
+
User.respond_to?(:popular).should be_true
|
192
|
+
User.respond_to?(:foobar).should be_true
|
193
|
+
User.respond_to?(:from_default).should be_true
|
194
|
+
end # }}}
|
195
|
+
|
196
|
+
it "handles custom GET requests" do # {{{
|
197
|
+
@users = User.popular
|
198
|
+
@users.length.should == 2
|
199
|
+
@users.first.id.should == 1
|
200
|
+
end # }}}
|
201
|
+
|
202
|
+
it "handles custom POST requests" do # {{{
|
203
|
+
@user = User.from_default(:name => "Tobias Fünke")
|
204
|
+
@user.id.should be_true
|
205
|
+
end # }}}
|
148
206
|
end
|
149
207
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require File.join(File.dirname(__FILE__), "../spec_helper.rb")
|
3
|
+
|
4
|
+
describe Her::Model::Introspection do
|
5
|
+
context "introspecting a resource" do
|
6
|
+
before do # {{{
|
7
|
+
Her::API.setup :base_uri => "https://api.example.com"
|
8
|
+
FakeWeb.register_uri(:get, "https://api.example.com/users/1", :body => { :data => { :id => 1, :name => "Tobias Fünke" } }.to_json)
|
9
|
+
Object.instance_eval { remove_const :User } if Object.const_defined?(:User)
|
10
|
+
class User
|
11
|
+
include Her::Model
|
12
|
+
end
|
13
|
+
end # }}}
|
14
|
+
|
15
|
+
describe "#inspect" do
|
16
|
+
it "outputs resource attributs for an existing resource" do # {{{
|
17
|
+
@user = User.find(1)
|
18
|
+
@user.inspect.should == "#<User(users/1) id=1 name=\"Tobias Fünke\">"
|
19
|
+
end # }}}
|
20
|
+
|
21
|
+
it "outputs resource attributs for an not-saved-yet resource" do # {{{
|
22
|
+
@user = User.new(:name => "Tobias Fünke")
|
23
|
+
@user.inspect.should == "#<User(users) name=\"Tobias Fünke\">"
|
24
|
+
end # }}}
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/spec/model/orm_spec.rb
CHANGED
@@ -27,6 +27,14 @@ describe Her::Model::ORM do
|
|
27
27
|
@users.length.should == 2
|
28
28
|
@users.first.name.should == "Tobias Fünke"
|
29
29
|
end # }}}
|
30
|
+
|
31
|
+
it "handles new resource" do # {{{
|
32
|
+
@new_user = User.new(:fullname => "Tobias Fünke")
|
33
|
+
@new_user.new?.should be_true
|
34
|
+
|
35
|
+
@existing_user = User.find(1)
|
36
|
+
@existing_user.new?.should be_false
|
37
|
+
end # }}}
|
30
38
|
end
|
31
39
|
|
32
40
|
context "creating resources" do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: her
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.8
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-04-
|
12
|
+
date: 2012-04-24 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
@@ -60,21 +60,21 @@ dependencies:
|
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '0'
|
62
62
|
- !ruby/object:Gem::Dependency
|
63
|
-
name:
|
63
|
+
name: redcarpet
|
64
64
|
requirement: !ruby/object:Gem::Requirement
|
65
65
|
none: false
|
66
66
|
requirements:
|
67
|
-
- -
|
67
|
+
- - '='
|
68
68
|
- !ruby/object:Gem::Version
|
69
|
-
version:
|
69
|
+
version: 1.17.2
|
70
70
|
type: :development
|
71
71
|
prerelease: false
|
72
72
|
version_requirements: !ruby/object:Gem::Requirement
|
73
73
|
none: false
|
74
74
|
requirements:
|
75
|
-
- -
|
75
|
+
- - '='
|
76
76
|
- !ruby/object:Gem::Version
|
77
|
-
version:
|
77
|
+
version: 1.17.2
|
78
78
|
- !ruby/object:Gem::Dependency
|
79
79
|
name: mocha
|
80
80
|
requirement: !ruby/object:Gem::Requirement
|
@@ -140,7 +140,7 @@ dependencies:
|
|
140
140
|
- !ruby/object:Gem::Version
|
141
141
|
version: '0'
|
142
142
|
- !ruby/object:Gem::Dependency
|
143
|
-
name:
|
143
|
+
name: multi_json
|
144
144
|
requirement: !ruby/object:Gem::Requirement
|
145
145
|
none: false
|
146
146
|
requirements:
|
@@ -177,12 +177,15 @@ files:
|
|
177
177
|
- lib/her/model/base.rb
|
178
178
|
- lib/her/model/hooks.rb
|
179
179
|
- lib/her/model/http.rb
|
180
|
+
- lib/her/model/introspection.rb
|
180
181
|
- lib/her/model/orm.rb
|
181
182
|
- lib/her/model/relationships.rb
|
182
183
|
- lib/her/version.rb
|
183
184
|
- spec/api_spec.rb
|
185
|
+
- spec/middleware/default_parse_json_spec.rb
|
184
186
|
- spec/model/hooks_spec.rb
|
185
187
|
- spec/model/http_spec.rb
|
188
|
+
- spec/model/introspection_spec.rb
|
186
189
|
- spec/model/orm_spec.rb
|
187
190
|
- spec/model/relationships_spec.rb
|
188
191
|
- spec/spec_helper.rb
|
@@ -200,7 +203,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
200
203
|
version: '0'
|
201
204
|
segments:
|
202
205
|
- 0
|
203
|
-
hash: -
|
206
|
+
hash: -3580311510675037650
|
204
207
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
205
208
|
none: false
|
206
209
|
requirements:
|
@@ -209,7 +212,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
209
212
|
version: '0'
|
210
213
|
segments:
|
211
214
|
- 0
|
212
|
-
hash: -
|
215
|
+
hash: -3580311510675037650
|
213
216
|
requirements: []
|
214
217
|
rubyforge_project:
|
215
218
|
rubygems_version: 1.8.18
|
@@ -219,8 +222,10 @@ summary: A simple Representational State Transfer-based Hypertext Transfer Proto
|
|
219
222
|
Object Relational Mapper. Her?
|
220
223
|
test_files:
|
221
224
|
- spec/api_spec.rb
|
225
|
+
- spec/middleware/default_parse_json_spec.rb
|
222
226
|
- spec/model/hooks_spec.rb
|
223
227
|
- spec/model/http_spec.rb
|
228
|
+
- spec/model/introspection_spec.rb
|
224
229
|
- spec/model/orm_spec.rb
|
225
230
|
- spec/model/relationships_spec.rb
|
226
231
|
- spec/spec_helper.rb
|