her5 0.8.1
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 +7 -0
- data/.gitignore +4 -0
- data/.rspec +1 -0
- data/.travis.yml +17 -0
- data/.yardopts +2 -0
- data/CONTRIBUTING.md +26 -0
- data/Gemfile +10 -0
- data/LICENSE +7 -0
- data/README.md +1017 -0
- data/Rakefile +11 -0
- data/UPGRADE.md +101 -0
- data/gemfiles/Gemfile.activemodel-3.2.x +7 -0
- data/gemfiles/Gemfile.activemodel-4.0 +7 -0
- data/gemfiles/Gemfile.activemodel-4.1 +7 -0
- data/gemfiles/Gemfile.activemodel-4.2 +7 -0
- data/gemfiles/Gemfile.activemodel-5.0.x +7 -0
- data/her5.gemspec +30 -0
- data/lib/her.rb +19 -0
- data/lib/her/api.rb +120 -0
- data/lib/her/collection.rb +12 -0
- data/lib/her/errors.rb +104 -0
- data/lib/her/json_api/model.rb +57 -0
- data/lib/her/middleware.rb +12 -0
- data/lib/her/middleware/accept_json.rb +17 -0
- data/lib/her/middleware/first_level_parse_json.rb +36 -0
- data/lib/her/middleware/json_api_parser.rb +68 -0
- data/lib/her/middleware/parse_json.rb +28 -0
- data/lib/her/middleware/second_level_parse_json.rb +36 -0
- data/lib/her/model.rb +75 -0
- data/lib/her/model/associations.rb +141 -0
- data/lib/her/model/associations/association.rb +107 -0
- data/lib/her/model/associations/association_proxy.rb +45 -0
- data/lib/her/model/associations/belongs_to_association.rb +101 -0
- data/lib/her/model/associations/has_many_association.rb +101 -0
- data/lib/her/model/associations/has_one_association.rb +80 -0
- data/lib/her/model/attributes.rb +297 -0
- data/lib/her/model/base.rb +33 -0
- data/lib/her/model/deprecated_methods.rb +61 -0
- data/lib/her/model/http.rb +113 -0
- data/lib/her/model/introspection.rb +65 -0
- data/lib/her/model/nested_attributes.rb +84 -0
- data/lib/her/model/orm.rb +207 -0
- data/lib/her/model/parse.rb +221 -0
- data/lib/her/model/paths.rb +126 -0
- data/lib/her/model/relation.rb +164 -0
- data/lib/her/version.rb +3 -0
- data/spec/api_spec.rb +114 -0
- data/spec/collection_spec.rb +26 -0
- data/spec/json_api/model_spec.rb +305 -0
- data/spec/middleware/accept_json_spec.rb +10 -0
- data/spec/middleware/first_level_parse_json_spec.rb +62 -0
- data/spec/middleware/json_api_parser_spec.rb +32 -0
- data/spec/middleware/second_level_parse_json_spec.rb +35 -0
- data/spec/model/associations/association_proxy_spec.rb +31 -0
- data/spec/model/associations_spec.rb +504 -0
- data/spec/model/attributes_spec.rb +389 -0
- data/spec/model/callbacks_spec.rb +145 -0
- data/spec/model/dirty_spec.rb +91 -0
- data/spec/model/http_spec.rb +158 -0
- data/spec/model/introspection_spec.rb +76 -0
- data/spec/model/nested_attributes_spec.rb +134 -0
- data/spec/model/orm_spec.rb +506 -0
- data/spec/model/parse_spec.rb +345 -0
- data/spec/model/paths_spec.rb +347 -0
- data/spec/model/relation_spec.rb +226 -0
- data/spec/model/validations_spec.rb +42 -0
- data/spec/model_spec.rb +44 -0
- data/spec/spec_helper.rb +26 -0
- data/spec/support/extensions/array.rb +5 -0
- data/spec/support/extensions/hash.rb +5 -0
- data/spec/support/macros/her_macros.rb +17 -0
- data/spec/support/macros/model_macros.rb +36 -0
- data/spec/support/macros/request_macros.rb +27 -0
- metadata +289 -0
@@ -0,0 +1,345 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require File.join(File.dirname(__FILE__), "../spec_helper.rb")
|
3
|
+
|
4
|
+
describe Her::Model::Parse do
|
5
|
+
context "when include_root_in_json is set" do
|
6
|
+
before do
|
7
|
+
Her::API.setup :url => "https://api.example.com" do |builder|
|
8
|
+
builder.use Her::Middleware::FirstLevelParseJSON
|
9
|
+
builder.use Faraday::Request::UrlEncoded
|
10
|
+
end
|
11
|
+
|
12
|
+
Her::API.default_api.connection.adapter :test do |stub|
|
13
|
+
stub.post("/users") { |env| [200, {}, { :user => { :id => 1, :fullname => params(env)[:user][:fullname] } }.to_json] }
|
14
|
+
stub.post("/users/admins") { |env| [200, {}, { :user => { :id => 1, :fullname => params(env)[:user][:fullname] } }.to_json] }
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
context "to true" do
|
19
|
+
before do
|
20
|
+
spawn_model "Foo::User" do
|
21
|
+
include_root_in_json true
|
22
|
+
parse_root_in_json true
|
23
|
+
custom_post :admins
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
it "wraps params in the element name in `to_params`" do
|
28
|
+
@new_user = Foo::User.new(:fullname => "Tobias Fünke")
|
29
|
+
@new_user.to_params.should == { :user => { :fullname => "Tobias Fünke" } }
|
30
|
+
end
|
31
|
+
|
32
|
+
it "wraps params in the element name in `.create`" do
|
33
|
+
@new_user = Foo::User.admins(:fullname => "Tobias Fünke")
|
34
|
+
@new_user.fullname.should == "Tobias Fünke"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context "to a symbol" do
|
39
|
+
before do
|
40
|
+
spawn_model "Foo::User" do
|
41
|
+
include_root_in_json :person
|
42
|
+
parse_root_in_json :person
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
it "wraps params in the specified value" do
|
47
|
+
@new_user = Foo::User.new(:fullname => "Tobias Fünke")
|
48
|
+
@new_user.to_params.should == { :person => { :fullname => "Tobias Fünke" } }
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context "in the parent class" do
|
53
|
+
before do
|
54
|
+
spawn_model("Foo::Model") { include_root_in_json true }
|
55
|
+
|
56
|
+
class User < Foo::Model; end
|
57
|
+
@spawned_models << :User
|
58
|
+
end
|
59
|
+
|
60
|
+
it "wraps params with the class name" do
|
61
|
+
@new_user = User.new(:fullname => "Tobias Fünke")
|
62
|
+
@new_user.to_params.should == { :user => { :fullname => "Tobias Fünke" } }
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
context "when parse_root_in_json is set" do
|
68
|
+
before do
|
69
|
+
Her::API.setup :url => "https://api.example.com" do |builder|
|
70
|
+
builder.use Her::Middleware::FirstLevelParseJSON
|
71
|
+
builder.use Faraday::Request::UrlEncoded
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
context "to true" do
|
76
|
+
before do
|
77
|
+
Her::API.default_api.connection.adapter :test do |stub|
|
78
|
+
stub.post("/users") { |env| [200, {}, { :user => { :id => 1, :fullname => "Lindsay Fünke" } }.to_json] }
|
79
|
+
stub.get("/users") { |env| [200, {}, [{ :user => { :id => 1, :fullname => "Lindsay Fünke" } }].to_json] }
|
80
|
+
stub.get("/users/admins") { |env| [200, {}, [{ :user => { :id => 1, :fullname => "Lindsay Fünke" } }].to_json] }
|
81
|
+
stub.get("/users/1") { |env| [200, {}, { :user => { :id => 1, :fullname => "Lindsay Fünke" } }.to_json] }
|
82
|
+
stub.put("/users/1") { |env| [200, {}, { :user => { :id => 1, :fullname => "Tobias Fünke Jr." } }.to_json] }
|
83
|
+
end
|
84
|
+
|
85
|
+
spawn_model("Foo::User") do
|
86
|
+
parse_root_in_json true
|
87
|
+
custom_get :admins
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
it "parse the data from the JSON root element after .create" do
|
92
|
+
@new_user = Foo::User.create(:fullname => "Lindsay Fünke")
|
93
|
+
@new_user.fullname.should == "Lindsay Fünke"
|
94
|
+
end
|
95
|
+
|
96
|
+
it "parse the data from the JSON root element after an arbitrary HTTP request" do
|
97
|
+
@new_user = Foo::User.admins
|
98
|
+
@new_user.first.fullname.should == "Lindsay Fünke"
|
99
|
+
end
|
100
|
+
|
101
|
+
it "parse the data from the JSON root element after .all" do
|
102
|
+
@users = Foo::User.all
|
103
|
+
@users.first.fullname.should == "Lindsay Fünke"
|
104
|
+
end
|
105
|
+
|
106
|
+
it "parse the data from the JSON root element after .find" do
|
107
|
+
@user = Foo::User.find(1)
|
108
|
+
@user.fullname.should == "Lindsay Fünke"
|
109
|
+
end
|
110
|
+
|
111
|
+
it "parse the data from the JSON root element after .save" do
|
112
|
+
@user = Foo::User.find(1)
|
113
|
+
@user.fullname = "Tobias Fünke"
|
114
|
+
@user.save
|
115
|
+
@user.fullname.should == "Tobias Fünke Jr."
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
context "to a symbol" do
|
120
|
+
before do
|
121
|
+
Her::API.default_api.connection.adapter :test do |stub|
|
122
|
+
stub.post("/users") { |env| [200, {}, { :person => { :id => 1, :fullname => "Lindsay Fünke" } }.to_json] }
|
123
|
+
end
|
124
|
+
|
125
|
+
spawn_model("Foo::User") { parse_root_in_json :person }
|
126
|
+
end
|
127
|
+
|
128
|
+
it "parse the data with the symbol" do
|
129
|
+
@new_user = Foo::User.create(:fullname => "Lindsay Fünke")
|
130
|
+
@new_user.fullname.should == "Lindsay Fünke"
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
context "in the parent class" do
|
135
|
+
before do
|
136
|
+
Her::API.default_api.connection.adapter :test do |stub|
|
137
|
+
stub.post("/users") { |env| [200, {}, { :user => { :id => 1, :fullname => "Lindsay Fünke" } }.to_json] }
|
138
|
+
stub.get("/users") { |env| [200, {}, { :users => [ { :id => 1, :fullname => "Lindsay Fünke" } ] }.to_json] }
|
139
|
+
end
|
140
|
+
|
141
|
+
spawn_model("Foo::Model") { parse_root_in_json true, format: :active_model_serializers }
|
142
|
+
class User < Foo::Model
|
143
|
+
collection_path "/users"
|
144
|
+
end
|
145
|
+
|
146
|
+
@spawned_models << :User
|
147
|
+
end
|
148
|
+
|
149
|
+
it "parse the data with the symbol" do
|
150
|
+
@new_user = User.create(:fullname => "Lindsay Fünke")
|
151
|
+
@new_user.fullname.should == "Lindsay Fünke"
|
152
|
+
end
|
153
|
+
|
154
|
+
it "parses the collection of data" do
|
155
|
+
@users = User.all
|
156
|
+
@users.first.fullname.should == "Lindsay Fünke"
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
context "to true with :format => :active_model_serializers" do
|
161
|
+
before do
|
162
|
+
Her::API.default_api.connection.adapter :test do |stub|
|
163
|
+
stub.post("/users") { |env| [200, {}, { :user => { :id => 1, :fullname => "Lindsay Fünke" } }.to_json] }
|
164
|
+
stub.get("/users") { |env| [200, {}, { :users => [ { :id => 1, :fullname => "Lindsay Fünke" } ] }.to_json] }
|
165
|
+
stub.get("/users/admins") { |env| [200, {}, { :users => [ { :id => 1, :fullname => "Lindsay Fünke" } ] }.to_json] }
|
166
|
+
stub.get("/users/1") { |env| [200, {}, { :user => { :id => 1, :fullname => "Lindsay Fünke" } }.to_json] }
|
167
|
+
stub.put("/users/1") { |env| [200, {}, { :user => { :id => 1, :fullname => "Tobias Fünke Jr." } }.to_json] }
|
168
|
+
end
|
169
|
+
|
170
|
+
spawn_model("Foo::User") do
|
171
|
+
parse_root_in_json true, :format => :active_model_serializers
|
172
|
+
custom_get :admins
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
it "parse the data from the JSON root element after .create" do
|
177
|
+
@new_user = Foo::User.create(:fullname => "Lindsay Fünke")
|
178
|
+
@new_user.fullname.should == "Lindsay Fünke"
|
179
|
+
end
|
180
|
+
|
181
|
+
it "parse the data from the JSON root element after an arbitrary HTTP request" do
|
182
|
+
@users = Foo::User.admins
|
183
|
+
@users.first.fullname.should == "Lindsay Fünke"
|
184
|
+
end
|
185
|
+
|
186
|
+
it "parse the data from the JSON root element after .all" do
|
187
|
+
@users = Foo::User.all
|
188
|
+
@users.first.fullname.should == "Lindsay Fünke"
|
189
|
+
end
|
190
|
+
|
191
|
+
it "parse the data from the JSON root element after .find" do
|
192
|
+
@user = Foo::User.find(1)
|
193
|
+
@user.fullname.should == "Lindsay Fünke"
|
194
|
+
end
|
195
|
+
|
196
|
+
it "parse the data from the JSON root element after .save" do
|
197
|
+
@user = Foo::User.find(1)
|
198
|
+
@user.fullname = "Tobias Fünke"
|
199
|
+
@user.save
|
200
|
+
@user.fullname.should == "Tobias Fünke Jr."
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
context "when to_params is set" do
|
206
|
+
before do
|
207
|
+
Her::API.setup :url => "https://api.example.com" do |builder|
|
208
|
+
builder.use Her::Middleware::FirstLevelParseJSON
|
209
|
+
builder.use Faraday::Request::UrlEncoded
|
210
|
+
builder.adapter :test do |stub|
|
211
|
+
stub.post("/users") { |env| ok! :id => 1, :fullname => params(env)['fullname'] }
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
spawn_model "Foo::User" do
|
216
|
+
def to_params
|
217
|
+
{ :fullname => "Lindsay Fünke" }
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
it "changes the request parameters for one-line resource creation" do
|
223
|
+
@user = Foo::User.create(:fullname => "Tobias Fünke")
|
224
|
+
@user.fullname.should == "Lindsay Fünke"
|
225
|
+
end
|
226
|
+
|
227
|
+
it "changes the request parameters for Model.new + #save" do
|
228
|
+
@user = Foo::User.new(:fullname => "Tobias Fünke")
|
229
|
+
@user.save
|
230
|
+
@user.fullname.should == "Lindsay Fünke"
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
context "when parse_root_in_json set json_api to true" do
|
235
|
+
before do
|
236
|
+
Her::API.setup :url => "https://api.example.com" do |builder|
|
237
|
+
builder.use Her::Middleware::FirstLevelParseJSON
|
238
|
+
builder.use Faraday::Request::UrlEncoded
|
239
|
+
builder.adapter :test do |stub|
|
240
|
+
stub.get("/users") { |env| [200, {}, { :users => [{ :id => 1, :fullname => "Lindsay Fünke" }] }.to_json] }
|
241
|
+
stub.get("/users/admins") { |env| [200, {}, { :users => [{ :id => 1, :fullname => "Lindsay Fünke" }] }.to_json] }
|
242
|
+
stub.get("/users/1") { |env| [200, {}, { :users => [{ :id => 1, :fullname => "Lindsay Fünke" }] }.to_json] }
|
243
|
+
stub.post("/users") { |env| [200, {}, { :users => [{ :fullname => "Lindsay Fünke" }] }.to_json] }
|
244
|
+
stub.put("/users/1") { |env| [200, {}, { :users => [{ :id => 1, :fullname => "Tobias Fünke Jr." }] }.to_json] }
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
spawn_model("Foo::User") do
|
249
|
+
parse_root_in_json true, :format => :json_api
|
250
|
+
include_root_in_json true
|
251
|
+
custom_get :admins
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
it "parse the data from the JSON root element after .create" do
|
256
|
+
@new_user = Foo::User.create(:fullname => "Lindsay Fünke")
|
257
|
+
@new_user.fullname.should == "Lindsay Fünke"
|
258
|
+
end
|
259
|
+
|
260
|
+
it "parse the data from the JSON root element after an arbitrary HTTP request" do
|
261
|
+
@new_user = Foo::User.admins
|
262
|
+
@new_user.first.fullname.should == "Lindsay Fünke"
|
263
|
+
end
|
264
|
+
|
265
|
+
it "parse the data from the JSON root element after .all" do
|
266
|
+
@users = Foo::User.all
|
267
|
+
@users.first.fullname.should == "Lindsay Fünke"
|
268
|
+
end
|
269
|
+
|
270
|
+
it "parse the data from the JSON root element after .find" do
|
271
|
+
@user = Foo::User.find(1)
|
272
|
+
@user.fullname.should == "Lindsay Fünke"
|
273
|
+
end
|
274
|
+
|
275
|
+
it "parse the data from the JSON root element after .save" do
|
276
|
+
@user = Foo::User.find(1)
|
277
|
+
@user.fullname = "Tobias Fünke"
|
278
|
+
@user.save
|
279
|
+
@user.fullname.should == "Tobias Fünke Jr."
|
280
|
+
end
|
281
|
+
|
282
|
+
it "parse the data from the JSON root element after new/save" do
|
283
|
+
@user = Foo::User.new
|
284
|
+
@user.fullname = "Lindsay Fünke (before save)"
|
285
|
+
@user.save
|
286
|
+
@user.fullname.should == "Lindsay Fünke"
|
287
|
+
end
|
288
|
+
end
|
289
|
+
|
290
|
+
context "when include_root_in_json set json_api" do
|
291
|
+
before do
|
292
|
+
Her::API.setup :url => "https://api.example.com" do |builder|
|
293
|
+
builder.use Her::Middleware::FirstLevelParseJSON
|
294
|
+
builder.use Faraday::Request::UrlEncoded
|
295
|
+
end
|
296
|
+
|
297
|
+
Her::API.default_api.connection.adapter :test do |stub|
|
298
|
+
stub.post("/users") { |env| [200, {}, { :users => [{ :id => 1, :fullname => params(env)[:users][:fullname] }] }.to_json] }
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
context "to true" do
|
303
|
+
before do
|
304
|
+
spawn_model "Foo::User" do
|
305
|
+
include_root_in_json true
|
306
|
+
parse_root_in_json true, format: :json_api
|
307
|
+
custom_post :admins
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
it "wraps params in the element name in `to_params`" do
|
312
|
+
@new_user = Foo::User.new(:fullname => "Tobias Fünke")
|
313
|
+
@new_user.to_params.should == { :users => [{ :fullname => "Tobias Fünke" }] }
|
314
|
+
end
|
315
|
+
|
316
|
+
it "wraps params in the element name in `.where`" do
|
317
|
+
@new_user = Foo::User.where(:fullname => "Tobias Fünke").build
|
318
|
+
@new_user.fullname.should == "Tobias Fünke"
|
319
|
+
end
|
320
|
+
end
|
321
|
+
end
|
322
|
+
|
323
|
+
context 'when send_only_modified_attributes is set' do
|
324
|
+
before do
|
325
|
+
Her::API.setup :url => "https://api.example.com", :send_only_modified_attributes => true do |builder|
|
326
|
+
builder.use Her::Middleware::FirstLevelParseJSON
|
327
|
+
builder.use Faraday::Request::UrlEncoded
|
328
|
+
end
|
329
|
+
|
330
|
+
Her::API.default_api.connection.adapter :test do |stub|
|
331
|
+
stub.get("/users/1") { |env| [200, {}, { :id => 1, :first_name => "Gooby", :last_name => "Pls" }.to_json] }
|
332
|
+
end
|
333
|
+
|
334
|
+
spawn_model "Foo::User" do
|
335
|
+
include_root_in_json true
|
336
|
+
end
|
337
|
+
end
|
338
|
+
|
339
|
+
it 'only sends the attributes that were modified' do
|
340
|
+
user = Foo::User.find 1
|
341
|
+
user.first_name = 'Someone'
|
342
|
+
expect(user.to_params).to eql(:user => {:first_name => 'Someone'})
|
343
|
+
end
|
344
|
+
end
|
345
|
+
end
|
@@ -0,0 +1,347 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require File.join(File.dirname(__FILE__), "../spec_helper.rb")
|
3
|
+
|
4
|
+
describe Her::Model::Paths do
|
5
|
+
context "building request paths" do
|
6
|
+
context "simple model" do
|
7
|
+
before do
|
8
|
+
spawn_model "Foo::User"
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "#request_path" do
|
12
|
+
it "builds paths with defaults" do
|
13
|
+
Foo::User.new(:id => "foo").request_path.should == "users/foo"
|
14
|
+
Foo::User.new(:id => nil).request_path.should == "users"
|
15
|
+
Foo::User.new().request_path.should == "users"
|
16
|
+
end
|
17
|
+
|
18
|
+
it "builds paths with custom collection path" do
|
19
|
+
Foo::User.collection_path "/utilisateurs"
|
20
|
+
Foo::User.new(:id => "foo").request_path.should == "/utilisateurs/foo"
|
21
|
+
Foo::User.new().request_path.should == "/utilisateurs"
|
22
|
+
end
|
23
|
+
|
24
|
+
it "builds paths with custom relative collection path" do
|
25
|
+
Foo::User.collection_path "utilisateurs"
|
26
|
+
Foo::User.new(:id => "foo").request_path.should == "utilisateurs/foo"
|
27
|
+
Foo::User.new().request_path.should == "utilisateurs"
|
28
|
+
end
|
29
|
+
|
30
|
+
it "builds paths with custom collection path with multiple variables" do
|
31
|
+
Foo::User.collection_path "/organizations/:organization_id/utilisateurs"
|
32
|
+
|
33
|
+
Foo::User.new(:id => "foo").request_path(:_organization_id => "acme").should == "/organizations/acme/utilisateurs/foo"
|
34
|
+
Foo::User.new().request_path(:_organization_id => "acme").should == "/organizations/acme/utilisateurs"
|
35
|
+
|
36
|
+
Foo::User.new(:id => "foo", :organization_id => "acme").request_path.should == "/organizations/acme/utilisateurs/foo"
|
37
|
+
Foo::User.new(:organization_id => "acme").request_path.should == "/organizations/acme/utilisateurs"
|
38
|
+
end
|
39
|
+
|
40
|
+
it "builds paths with custom relative collection path with multiple variables" do
|
41
|
+
Foo::User.collection_path "organizations/:organization_id/utilisateurs"
|
42
|
+
|
43
|
+
Foo::User.new(:id => "foo").request_path(:_organization_id => "acme").should == "organizations/acme/utilisateurs/foo"
|
44
|
+
Foo::User.new().request_path(:_organization_id => "acme").should == "organizations/acme/utilisateurs"
|
45
|
+
|
46
|
+
Foo::User.new(:id => "foo", :organization_id => "acme").request_path.should == "organizations/acme/utilisateurs/foo"
|
47
|
+
Foo::User.new(:organization_id => "acme").request_path.should == "organizations/acme/utilisateurs"
|
48
|
+
end
|
49
|
+
|
50
|
+
it "builds paths with custom item path" do
|
51
|
+
Foo::User.resource_path "/utilisateurs/:id"
|
52
|
+
Foo::User.new(:id => "foo").request_path.should == "/utilisateurs/foo"
|
53
|
+
Foo::User.new().request_path.should == "users"
|
54
|
+
end
|
55
|
+
|
56
|
+
it "builds paths with custom relative item path" do
|
57
|
+
Foo::User.resource_path "utilisateurs/:id"
|
58
|
+
Foo::User.new(:id => "foo").request_path.should == "utilisateurs/foo"
|
59
|
+
Foo::User.new().request_path.should == "users"
|
60
|
+
end
|
61
|
+
|
62
|
+
it "raises exceptions when building a path without required custom variables" do
|
63
|
+
Foo::User.collection_path "/organizations/:organization_id/utilisateurs"
|
64
|
+
expect { Foo::User.new(:id => "foo").request_path }.to raise_error(Her::Errors::PathError, "Missing :_organization_id parameter to build the request path. Path is `/organizations/:organization_id/utilisateurs/:id`. Parameters are `{:id=>\"foo\"}`.")
|
65
|
+
end
|
66
|
+
|
67
|
+
it "escapes the variable values" do
|
68
|
+
Foo::User.collection_path "organizations/:organization_id/utilisateurs"
|
69
|
+
Foo::User.new(:id => "Привет").request_path(:_organization_id => 'лол').should == "organizations/%D0%BB%D0%BE%D0%BB/utilisateurs/%D0%9F%D1%80%D0%B8%D0%B2%D0%B5%D1%82"
|
70
|
+
Foo::User.new(:organization_id => 'лол', :id => "Привет").request_path.should == "organizations/%D0%BB%D0%BE%D0%BB/utilisateurs/%D0%9F%D1%80%D0%B8%D0%B2%D0%B5%D1%82"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
context "simple model with multiple words" do
|
76
|
+
before do
|
77
|
+
spawn_model "Foo::AdminUser"
|
78
|
+
end
|
79
|
+
|
80
|
+
describe "#request_path" do
|
81
|
+
it "builds paths with defaults" do
|
82
|
+
Foo::AdminUser.new(:id => "foo").request_path.should == "admin_users/foo"
|
83
|
+
Foo::AdminUser.new().request_path.should == "admin_users"
|
84
|
+
end
|
85
|
+
|
86
|
+
it "builds paths with custom collection path" do
|
87
|
+
Foo::AdminUser.collection_path "/users"
|
88
|
+
Foo::AdminUser.new(:id => "foo").request_path.should == "/users/foo"
|
89
|
+
Foo::AdminUser.new().request_path.should == "/users"
|
90
|
+
end
|
91
|
+
|
92
|
+
it "builds paths with custom relative collection path" do
|
93
|
+
Foo::AdminUser.collection_path "users"
|
94
|
+
Foo::AdminUser.new(:id => "foo").request_path.should == "users/foo"
|
95
|
+
Foo::AdminUser.new().request_path.should == "users"
|
96
|
+
end
|
97
|
+
|
98
|
+
it "builds paths with custom collection path with multiple variables" do
|
99
|
+
Foo::AdminUser.collection_path "/organizations/:organization_id/users"
|
100
|
+
Foo::AdminUser.new(:id => "foo").request_path(:_organization_id => "acme").should == "/organizations/acme/users/foo"
|
101
|
+
Foo::AdminUser.new().request_path(:_organization_id => "acme").should == "/organizations/acme/users"
|
102
|
+
end
|
103
|
+
|
104
|
+
it "builds paths with custom relative collection path with multiple variables" do
|
105
|
+
Foo::AdminUser.collection_path "organizations/:organization_id/users"
|
106
|
+
Foo::AdminUser.new(:id => "foo").request_path(:_organization_id => "acme").should == "organizations/acme/users/foo"
|
107
|
+
Foo::AdminUser.new().request_path(:_organization_id => "acme").should == "organizations/acme/users"
|
108
|
+
end
|
109
|
+
|
110
|
+
it "builds paths with custom item path" do
|
111
|
+
Foo::AdminUser.resource_path "/users/:id"
|
112
|
+
Foo::AdminUser.new(:id => "foo").request_path.should == "/users/foo"
|
113
|
+
Foo::AdminUser.new().request_path.should == "admin_users"
|
114
|
+
end
|
115
|
+
|
116
|
+
it "builds paths with custom relative item path" do
|
117
|
+
Foo::AdminUser.resource_path "users/:id"
|
118
|
+
Foo::AdminUser.new(:id => "foo").request_path.should == "users/foo"
|
119
|
+
Foo::AdminUser.new().request_path.should == "admin_users"
|
120
|
+
end
|
121
|
+
|
122
|
+
it "raises exceptions when building a path without required custom variables" do
|
123
|
+
Foo::AdminUser.collection_path "/organizations/:organization_id/users"
|
124
|
+
expect { Foo::AdminUser.new(:id => "foo").request_path }.to raise_error(Her::Errors::PathError, "Missing :_organization_id parameter to build the request path. Path is `/organizations/:organization_id/users/:id`. Parameters are `{:id=>\"foo\"}`.")
|
125
|
+
end
|
126
|
+
|
127
|
+
it "raises exceptions when building a relative path without required custom variables" do
|
128
|
+
Foo::AdminUser.collection_path "organizations/:organization_id/users"
|
129
|
+
expect { Foo::AdminUser.new(:id => "foo").request_path }.to raise_error(Her::Errors::PathError, "Missing :_organization_id parameter to build the request path. Path is `organizations/:organization_id/users/:id`. Parameters are `{:id=>\"foo\"}`.")
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
context "children model" do
|
135
|
+
before do
|
136
|
+
Her::API.setup :url => "https://api.example.com" do |builder|
|
137
|
+
builder.use Her::Middleware::FirstLevelParseJSON
|
138
|
+
builder.use Faraday::Request::UrlEncoded
|
139
|
+
builder.adapter :test do |stub|
|
140
|
+
stub.get("/users/foo") { |env| [200, {}, { :id => 'foo' }.to_json] }
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
spawn_model("Foo::Model") { include_root_in_json true }
|
145
|
+
|
146
|
+
class User < Foo::Model; end
|
147
|
+
@spawned_models << :User
|
148
|
+
end
|
149
|
+
|
150
|
+
it "builds path using the children model name" do
|
151
|
+
User.find('foo').id.should == 'foo'
|
152
|
+
User.find('foo').id.should == 'foo'
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
context "nested model" do
|
157
|
+
before do
|
158
|
+
spawn_model "Foo::User"
|
159
|
+
end
|
160
|
+
|
161
|
+
describe "#request_path" do
|
162
|
+
it "builds paths with defaults" do
|
163
|
+
Foo::User.new(:id => "foo").request_path.should == "users/foo"
|
164
|
+
Foo::User.new.request_path.should == "users"
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
context 'custom primary key' do
|
170
|
+
before do
|
171
|
+
spawn_model 'User' do
|
172
|
+
primary_key 'UserId'
|
173
|
+
resource_path 'users/:UserId'
|
174
|
+
end
|
175
|
+
|
176
|
+
spawn_model 'Customer' do
|
177
|
+
primary_key :customer_id
|
178
|
+
resource_path 'customers/:id'
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
describe '#request_path' do
|
183
|
+
it 'uses the correct primary key attribute' do
|
184
|
+
User.new(:UserId => 'foo').request_path.should == 'users/foo'
|
185
|
+
User.new(:id => 'foo').request_path.should == 'users'
|
186
|
+
end
|
187
|
+
|
188
|
+
it 'replaces :id with the appropriate primary key' do
|
189
|
+
Customer.new(:customer_id => 'joe').request_path.should == 'customers/joe'
|
190
|
+
Customer.new(:id => 'joe').request_path.should == 'customers'
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
context "making subdomain HTTP requests" do
|
197
|
+
before do
|
198
|
+
Her::API.setup :url => "https://api.example.com/" do |builder|
|
199
|
+
builder.use Her::Middleware::FirstLevelParseJSON
|
200
|
+
builder.use Faraday::Request::UrlEncoded
|
201
|
+
builder.adapter :test do |stub|
|
202
|
+
stub.get("organizations/2/users") { |env| [200, {}, [{ :id => 1, :fullname => "Tobias Fünke", :organization_id => 2 }, { :id => 2, :fullname => "Lindsay Fünke", :organization_id => 2 }].to_json] }
|
203
|
+
stub.post("organizations/2/users") { |env| [200, {}, { :id => 1, :fullname => "Tobias Fünke", :organization_id => 2 }.to_json] }
|
204
|
+
stub.put("organizations/2/users/1") { |env| [200, {}, { :id => 1, :fullname => "Lindsay Fünke", :organization_id => 2 }.to_json] }
|
205
|
+
stub.get("organizations/2/users/1") { |env| [200, {}, { :id => 1, :fullname => "Tobias Fünke", :organization_id => 2, :active => true }.to_json] }
|
206
|
+
stub.delete("organizations/2/users/1") { |env| [200, {}, { :id => 1, :fullname => "Lindsay Fünke", :organization_id => 2, :active => false }.to_json] }
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
spawn_model "Foo::User" do
|
211
|
+
collection_path "organizations/:organization_id/users"
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
describe "fetching a resource" do
|
216
|
+
it "maps a single resource to a Ruby object" do
|
217
|
+
@user = Foo::User.find(1, :_organization_id => 2)
|
218
|
+
@user.id.should == 1
|
219
|
+
@user.fullname.should == "Tobias Fünke"
|
220
|
+
end
|
221
|
+
|
222
|
+
it "maps a single resource using a scope to a Ruby object" do
|
223
|
+
Foo::User.scope :for_organization, lambda { |o| where(:organization_id => o) }
|
224
|
+
@user = Foo::User.for_organization(2).find(1)
|
225
|
+
@user.id.should == 1
|
226
|
+
@user.fullname.should == "Tobias Fünke"
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
describe "fetching a collection" do
|
231
|
+
it "maps a collection of resources to an array of Ruby objects" do
|
232
|
+
@users = Foo::User.where(:_organization_id => 2).all
|
233
|
+
@users.length.should == 2
|
234
|
+
@users.first.fullname.should == "Tobias Fünke"
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
describe "handling new resource" do
|
239
|
+
it "handles new resource" do
|
240
|
+
@new_user = Foo::User.new(:fullname => "Tobias Fünke", :organization_id => 2)
|
241
|
+
@new_user.new?.should be_truthy
|
242
|
+
|
243
|
+
@existing_user = Foo::User.find(1, :_organization_id => 2)
|
244
|
+
@existing_user.new?.should be_falsey
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
describe "creating resources" do
|
249
|
+
it "handle one-line resource creation" do
|
250
|
+
@user = Foo::User.create(:fullname => "Tobias Fünke", :organization_id => 2)
|
251
|
+
@user.id.should == 1
|
252
|
+
@user.fullname.should == "Tobias Fünke"
|
253
|
+
end
|
254
|
+
|
255
|
+
it "handle resource creation through Model.new + #save" do
|
256
|
+
@user = Foo::User.new(:fullname => "Tobias Fünke", :organization_id => 2)
|
257
|
+
@user.save
|
258
|
+
@user.fullname.should == "Tobias Fünke"
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
context "updating resources" do
|
263
|
+
it "handle resource data update without saving it" do
|
264
|
+
@user = Foo::User.find(1, :_organization_id => 2)
|
265
|
+
@user.fullname.should == "Tobias Fünke"
|
266
|
+
@user.fullname = "Kittie Sanchez"
|
267
|
+
@user.fullname.should == "Kittie Sanchez"
|
268
|
+
end
|
269
|
+
|
270
|
+
it "handle resource update through the .update class method" do
|
271
|
+
@user = Foo::User.save_existing(1, { :fullname => "Lindsay Fünke", :organization_id => 2 })
|
272
|
+
@user.fullname.should == "Lindsay Fünke"
|
273
|
+
end
|
274
|
+
|
275
|
+
it "handle resource update through #save on an existing resource" do
|
276
|
+
@user = Foo::User.find(1, :_organization_id => 2)
|
277
|
+
@user.fullname = "Lindsay Fünke"
|
278
|
+
@user.save
|
279
|
+
@user.fullname.should == "Lindsay Fünke"
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
context "deleting resources" do
|
284
|
+
it "handle resource deletion through the .destroy class method" do
|
285
|
+
@user = Foo::User.destroy_existing(1, :_organization_id => 2)
|
286
|
+
@user.active.should be_falsey
|
287
|
+
end
|
288
|
+
|
289
|
+
it "handle resource deletion through #destroy on an existing resource" do
|
290
|
+
@user = Foo::User.find(1, :_organization_id => 2)
|
291
|
+
@user.destroy
|
292
|
+
@user.active.should be_falsey
|
293
|
+
end
|
294
|
+
end
|
295
|
+
end
|
296
|
+
|
297
|
+
context "making path HTTP requests" do
|
298
|
+
before do
|
299
|
+
Her::API.setup :url => "https://example.com/api/" do |builder|
|
300
|
+
builder.use Her::Middleware::FirstLevelParseJSON
|
301
|
+
builder.use Faraday::Request::UrlEncoded
|
302
|
+
builder.adapter :test do |stub|
|
303
|
+
stub.get("/api/organizations/2/users") { |env| [200, {}, [{ :id => 1, :fullname => "Tobias Fünke", :organization_id => 2 }, { :id => 2, :fullname => "Lindsay Fünke", :organization_id => 2 }].to_json] }
|
304
|
+
stub.get("/api/organizations/2/users/1") { |env| [200, {}, { :id => 1, :fullname => "Tobias Fünke", :organization_id => 2, :active => true }.to_json] }
|
305
|
+
end
|
306
|
+
end
|
307
|
+
|
308
|
+
spawn_model "Foo::User" do
|
309
|
+
collection_path "organizations/:organization_id/users"
|
310
|
+
end
|
311
|
+
end
|
312
|
+
|
313
|
+
describe "fetching a resource" do
|
314
|
+
it "maps a single resource to a Ruby object" do
|
315
|
+
@user = Foo::User.find(1, :_organization_id => 2)
|
316
|
+
@user.id.should == 1
|
317
|
+
@user.fullname.should == "Tobias Fünke"
|
318
|
+
end
|
319
|
+
end
|
320
|
+
|
321
|
+
describe "fetching a collection" do
|
322
|
+
it "maps a collection of resources to an array of Ruby objects" do
|
323
|
+
@users = Foo::User.where(:_organization_id => 2).all
|
324
|
+
@users.length.should == 2
|
325
|
+
@users.first.fullname.should == "Tobias Fünke"
|
326
|
+
end
|
327
|
+
end
|
328
|
+
|
329
|
+
describe "fetching a resource with absolute path" do
|
330
|
+
it "maps a single resource to a Ruby object" do
|
331
|
+
Foo::User.resource_path '/api/' + Foo::User.resource_path
|
332
|
+
@user = Foo::User.find(1, :_organization_id => 2)
|
333
|
+
@user.id.should == 1
|
334
|
+
@user.fullname.should == "Tobias Fünke"
|
335
|
+
end
|
336
|
+
end
|
337
|
+
|
338
|
+
describe "fetching a collection with absolute path" do
|
339
|
+
it "maps a collection of resources to an array of Ruby objects" do
|
340
|
+
Foo::User.collection_path '/api/' + Foo::User.collection_path
|
341
|
+
@users = Foo::User.where(:_organization_id => 2).all
|
342
|
+
@users.length.should == 2
|
343
|
+
@users.first.fullname.should == "Tobias Fünke"
|
344
|
+
end
|
345
|
+
end
|
346
|
+
end
|
347
|
+
end
|