api_resource 0.4.3 → 0.5.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/VERSION +1 -1
- data/api_resource.gemspec +4 -74
- data/coverage/assets/0.5.3/app.js +88 -0
- data/coverage/assets/0.5.3/fancybox/blank.gif +0 -0
- data/coverage/assets/0.5.3/fancybox/fancy_close.png +0 -0
- data/coverage/assets/0.5.3/fancybox/fancy_loading.png +0 -0
- data/coverage/assets/0.5.3/fancybox/fancy_nav_left.png +0 -0
- data/coverage/assets/0.5.3/fancybox/fancy_nav_right.png +0 -0
- data/coverage/assets/0.5.3/fancybox/fancy_shadow_e.png +0 -0
- data/coverage/assets/0.5.3/fancybox/fancy_shadow_n.png +0 -0
- data/coverage/assets/0.5.3/fancybox/fancy_shadow_ne.png +0 -0
- data/coverage/assets/0.5.3/fancybox/fancy_shadow_nw.png +0 -0
- data/coverage/assets/0.5.3/fancybox/fancy_shadow_s.png +0 -0
- data/coverage/assets/0.5.3/fancybox/fancy_shadow_se.png +0 -0
- data/coverage/assets/0.5.3/fancybox/fancy_shadow_sw.png +0 -0
- data/coverage/assets/0.5.3/fancybox/fancy_shadow_w.png +0 -0
- data/coverage/assets/0.5.3/fancybox/fancy_title_left.png +0 -0
- data/coverage/assets/0.5.3/fancybox/fancy_title_main.png +0 -0
- data/coverage/assets/0.5.3/fancybox/fancy_title_over.png +0 -0
- data/coverage/assets/0.5.3/fancybox/fancy_title_right.png +0 -0
- data/coverage/assets/0.5.3/fancybox/fancybox-x.png +0 -0
- data/coverage/assets/0.5.3/fancybox/fancybox-y.png +0 -0
- data/coverage/assets/0.5.3/fancybox/fancybox.png +0 -0
- data/coverage/assets/0.5.3/fancybox/jquery.fancybox-1.3.1.css +363 -0
- data/coverage/assets/0.5.3/fancybox/jquery.fancybox-1.3.1.pack.js +44 -0
- data/coverage/assets/0.5.3/favicon_green.png +0 -0
- data/coverage/assets/0.5.3/favicon_red.png +0 -0
- data/coverage/assets/0.5.3/favicon_yellow.png +0 -0
- data/coverage/assets/0.5.3/highlight.css +129 -0
- data/coverage/assets/0.5.3/highlight.pack.js +1 -0
- data/coverage/assets/0.5.3/jquery-1.6.2.min.js +18 -0
- data/coverage/assets/0.5.3/jquery.dataTables.min.js +152 -0
- data/coverage/assets/0.5.3/jquery.timeago.js +141 -0
- data/coverage/assets/0.5.3/jquery.url.js +174 -0
- data/coverage/assets/0.5.3/loading.gif +0 -0
- data/coverage/assets/0.5.3/magnify.png +0 -0
- data/coverage/assets/0.5.3/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
- data/coverage/assets/0.5.3/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
- data/coverage/assets/0.5.3/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
- data/coverage/assets/0.5.3/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
- data/coverage/assets/0.5.3/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
- data/coverage/assets/0.5.3/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
- data/coverage/assets/0.5.3/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
- data/coverage/assets/0.5.3/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
- data/coverage/assets/0.5.3/smoothness/images/ui-icons_222222_256x240.png +0 -0
- data/coverage/assets/0.5.3/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
- data/coverage/assets/0.5.3/smoothness/images/ui-icons_454545_256x240.png +0 -0
- data/coverage/assets/0.5.3/smoothness/images/ui-icons_888888_256x240.png +0 -0
- data/coverage/assets/0.5.3/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
- data/coverage/assets/0.5.3/smoothness/jquery-ui-1.8.4.custom.css +295 -0
- data/coverage/assets/0.5.3/stylesheet.css +383 -0
- data/coverage/index.html +3573 -0
- data/lib/api_resource/associations/abstract_scope.rb +191 -0
- data/lib/api_resource/associations/association_scope.rb +47 -0
- data/lib/api_resource/associations/belongs_to_remote_object_proxy.rb +5 -6
- data/lib/api_resource/associations/has_many_remote_object_proxy.rb +5 -8
- data/lib/api_resource/associations/has_one_remote_object_proxy.rb +12 -13
- data/lib/api_resource/associations/multi_object_proxy.rb +65 -39
- data/lib/api_resource/associations/resource_scope.rb +6 -17
- data/lib/api_resource/associations/scope.rb +23 -121
- data/lib/api_resource/associations/single_object_proxy.rb +41 -50
- data/lib/api_resource/associations.rb +32 -11
- data/lib/api_resource/attributes.rb +108 -69
- data/lib/api_resource/base.rb +114 -106
- data/lib/api_resource/local.rb +1 -1
- data/lib/api_resource/model_errors.rb +9 -6
- data/lib/api_resource/scopes.rb +53 -16
- data/lib/api_resource.rb +3 -1
- data/spec/lib/api_resource_spec.rb +3 -7
- data/spec/lib/associations/association_scope_spec.rb +19 -0
- data/spec/lib/associations_spec.rb +251 -162
- data/spec/lib/attributes_spec.rb +33 -15
- data/spec/lib/base_spec.rb +302 -64
- data/spec/lib/callbacks_spec.rb +4 -2
- data/spec/lib/local_spec.rb +5 -1
- data/spec/spec_helper.rb +2 -3
- data/spec/support/mocks/association_mocks.rb +9 -1
- data/spec/support/requests/association_requests.rb +5 -5
- data/spec/support/requests/test_resource_requests.rb +16 -4
- data/spec/tmp/api_resource_test_db.sqlite +0 -0
- metadata +68 -22
- data/.document +0 -5
- data/.rspec +0 -5
- data/.travis.yml +0 -4
- data/lib/api_resource/associations/association_proxy.rb +0 -121
- data/lib/api_resource/associations/dynamic_resource_scope.rb +0 -23
- data/lib/api_resource/associations/generic_scope.rb +0 -68
- data/lib/api_resource/associations/multi_argument_resource_scope.rb +0 -15
- data/lib/api_resource/associations/relation_scope.rb +0 -25
|
@@ -8,6 +8,35 @@ describe "Associations" do
|
|
|
8
8
|
TestResource.reload_class_attributes
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
+
let(:ap) do
|
|
12
|
+
Associations::SingleObjectProxy.new(
|
|
13
|
+
"TestResource",
|
|
14
|
+
HasManyObject.new, {
|
|
15
|
+
:service_uri => '/single_object_association'
|
|
16
|
+
}
|
|
17
|
+
)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
context "Comparison" do
|
|
21
|
+
|
|
22
|
+
context "&group_by" do
|
|
23
|
+
|
|
24
|
+
it "should allow grouping by resources with the same id" do
|
|
25
|
+
|
|
26
|
+
tr1 = TestResource.find(1)
|
|
27
|
+
tr2 = TestResource.find(1)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
tr1.has_one_object
|
|
31
|
+
tr2.has_one_object
|
|
32
|
+
|
|
33
|
+
[tr1, tr2].group_by(&:has_one_object).keys.length.should be 1
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
end
|
|
39
|
+
|
|
11
40
|
context "creating and testing for associations of various types" do
|
|
12
41
|
|
|
13
42
|
it "should be able to give a list of all associations" do
|
|
@@ -200,27 +229,29 @@ describe "Associations" do
|
|
|
200
229
|
end
|
|
201
230
|
|
|
202
231
|
it "should be able to extract a service uri from the contents hash" do
|
|
203
|
-
ap = Associations::SingleObjectProxy.new(
|
|
232
|
+
ap = Associations::SingleObjectProxy.new(
|
|
233
|
+
"TestResource",
|
|
234
|
+
HasManyObject.new, {
|
|
235
|
+
:service_uri => '/path'
|
|
236
|
+
}
|
|
237
|
+
)
|
|
204
238
|
ap.remote_path.should eql("/path")
|
|
205
239
|
end
|
|
206
240
|
|
|
207
|
-
it "should be able to recognize the attributes of an object
|
|
241
|
+
it "should be able to recognize the attributes of an object
|
|
242
|
+
and not make them scopes" do
|
|
243
|
+
|
|
208
244
|
TestResource.define_attributes :test
|
|
209
|
-
ap = Associations::SingleObjectProxy.new(
|
|
245
|
+
ap = Associations::SingleObjectProxy.new(
|
|
246
|
+
"TestResource",
|
|
247
|
+
HasManyObject.new, {
|
|
248
|
+
:service_uri => '/path',
|
|
249
|
+
:test => "testval"
|
|
250
|
+
}
|
|
251
|
+
)
|
|
210
252
|
ap.scope?("test").should be_false
|
|
211
|
-
ap.
|
|
212
|
-
end
|
|
213
|
-
|
|
214
|
-
it "should make all attributes except the service uri into scopes given the scopes_only option" do
|
|
215
|
-
ap = Associations::SingleObjectProxy.new("TestResource",{:service_uri => "/path", :test_scope => {"testval" => true}, :scopes_only => true})
|
|
216
|
-
ap.scope?("test_scope").should be_true
|
|
217
|
-
ap.remote_path.should eql("/path")
|
|
218
|
-
end
|
|
253
|
+
ap.test.should eql("testval")
|
|
219
254
|
|
|
220
|
-
it "should pass the attributes that are not scopes and make them attributes of the object" do
|
|
221
|
-
TestResource.define_attributes :test
|
|
222
|
-
ap = Associations::SingleObjectProxy.new("TestResource",{:service_uri => "/path", :test => "testval"})
|
|
223
|
-
ap.internal_object.attributes.keys.should include("test")
|
|
224
255
|
end
|
|
225
256
|
end
|
|
226
257
|
|
|
@@ -239,19 +270,29 @@ describe "Associations" do
|
|
|
239
270
|
context "Loading array contents" do
|
|
240
271
|
|
|
241
272
|
it "should be able to load a blank array" do
|
|
242
|
-
ap = Associations::MultiObjectProxy.new(
|
|
273
|
+
ap = Associations::MultiObjectProxy.new(
|
|
274
|
+
"TestResource",
|
|
275
|
+
BelongsToObject.new
|
|
276
|
+
)
|
|
243
277
|
ap.remote_path.should be_nil
|
|
244
|
-
ap.scopes.keys.should eql([])
|
|
245
278
|
end
|
|
246
279
|
|
|
247
280
|
it "should be able to recognize a settings hash if it has a service_uri" do
|
|
248
|
-
ap = Associations::MultiObjectProxy.new(
|
|
281
|
+
ap = Associations::MultiObjectProxy.new(
|
|
282
|
+
"TestResource",
|
|
283
|
+
BelongsToObject.new,
|
|
284
|
+
[{:service_uri => "/route"}]
|
|
285
|
+
)
|
|
249
286
|
ap.remote_path.should eql("/route")
|
|
250
287
|
end
|
|
251
288
|
|
|
252
289
|
it "should be able to recognize a settings hash if it has a 'service_uri' with another preset name" do
|
|
253
290
|
Associations::MultiObjectProxy.remote_path_element = :the_element
|
|
254
|
-
ap = Associations::MultiObjectProxy.new(
|
|
291
|
+
ap = Associations::MultiObjectProxy.new(
|
|
292
|
+
"TestResource",
|
|
293
|
+
BelongsToObject.new,
|
|
294
|
+
[{:the_element => "/route"}]
|
|
295
|
+
)
|
|
255
296
|
ap.remote_path.should eql("/route")
|
|
256
297
|
end
|
|
257
298
|
|
|
@@ -260,38 +301,71 @@ describe "Associations" do
|
|
|
260
301
|
context "Loading hash contents" do
|
|
261
302
|
it "should not be able to load a hash without a 'service_uri'" do
|
|
262
303
|
lambda {
|
|
263
|
-
Associations::MultiObjectProxy.new(
|
|
304
|
+
Associations::MultiObjectProxy.new(
|
|
305
|
+
"TestResource",
|
|
306
|
+
BelongsToObject,
|
|
307
|
+
{:hi => 3}
|
|
308
|
+
)
|
|
264
309
|
}.should raise_error
|
|
265
310
|
end
|
|
266
311
|
|
|
267
312
|
it "should be able to recognize settings from a hash" do
|
|
268
|
-
ap = Associations::MultiObjectProxy.new(
|
|
313
|
+
ap = Associations::MultiObjectProxy.new(
|
|
314
|
+
"TestResource",
|
|
315
|
+
BelongsToObject,
|
|
316
|
+
{:service_uri => "/route"}
|
|
317
|
+
)
|
|
318
|
+
ap.remote_path.should eql("/route")
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
it "should be able to recognize settings from a hash as a string" do
|
|
322
|
+
ap = Associations::MultiObjectProxy.new(
|
|
323
|
+
"TestResource",
|
|
324
|
+
BelongsToObject,
|
|
325
|
+
{"service_uri" => "/route"}
|
|
326
|
+
)
|
|
269
327
|
ap.remote_path.should eql("/route")
|
|
270
328
|
end
|
|
271
329
|
|
|
272
330
|
it "should recognize settings with differing 'service_uri' names" do
|
|
273
331
|
Associations::MultiObjectProxy.remote_path_element = :the_element
|
|
274
|
-
ap = Associations::MultiObjectProxy.new(
|
|
332
|
+
ap = Associations::MultiObjectProxy.new(
|
|
333
|
+
"TestResource",
|
|
334
|
+
BelongsToObject,
|
|
335
|
+
{:the_element => "/route"}
|
|
336
|
+
)
|
|
275
337
|
ap.remote_path.should eql("/route")
|
|
276
338
|
end
|
|
277
339
|
end
|
|
278
340
|
|
|
279
341
|
context "Defining scopes" do
|
|
280
342
|
|
|
281
|
-
it "should
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
end
|
|
285
|
-
|
|
286
|
-
it "should identify known scopes based on the scopes defined on the object it is a proxy to" do
|
|
343
|
+
it "should identify known scopes based on the scopes defined on
|
|
344
|
+
the object it is a proxy to" do
|
|
345
|
+
|
|
287
346
|
TestResource.scope :class_scope, "class_scope" => "true"
|
|
288
|
-
|
|
289
|
-
|
|
347
|
+
|
|
348
|
+
ap = Associations::MultiObjectProxy.new(
|
|
349
|
+
"TestResource",
|
|
350
|
+
BelongsToObject.new,
|
|
351
|
+
[{:service_uri => "/route"}]
|
|
352
|
+
)
|
|
353
|
+
ap.scope?(:class_scope).should be_true
|
|
290
354
|
end
|
|
291
355
|
|
|
292
356
|
it "scopes in the response should shadow class defined scopes" do
|
|
293
|
-
TestResource.scope
|
|
294
|
-
ap = Associations::MultiObjectProxy.new(
|
|
357
|
+
TestResource.scope(:scope1, "scope1" => "true")
|
|
358
|
+
ap = Associations::MultiObjectProxy.new(
|
|
359
|
+
"TestResource",
|
|
360
|
+
BelongsToObject.new,
|
|
361
|
+
[
|
|
362
|
+
{
|
|
363
|
+
:service_uri => "/route",
|
|
364
|
+
:scope1 => {"scope1" => true},
|
|
365
|
+
:scope2 => {"scope2" => true}
|
|
366
|
+
}
|
|
367
|
+
]
|
|
368
|
+
)
|
|
295
369
|
ap.scopes[:scope1].should eql({"scope1" => true})
|
|
296
370
|
end
|
|
297
371
|
end
|
|
@@ -313,42 +387,32 @@ describe "Associations" do
|
|
|
313
387
|
end
|
|
314
388
|
|
|
315
389
|
it "should be able to query scopes on the current model" do
|
|
316
|
-
ScopeResource.no_arg.to_query.should eql
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
it "should be able to return the current query string" do
|
|
344
|
-
ap = Associations::MultiObjectProxy.new("TestResource", [{:service_uri => "/route", :scope_1 => {"scope_1" => true}, :scope_2 => {"scope_2" => true}}])
|
|
345
|
-
ap.scope_1.scope_2.to_query.should eql("scope_1=true&scope_2=true")
|
|
346
|
-
end
|
|
347
|
-
|
|
348
|
-
it "should be able to substitute values into the scope query strings by passing a hash to the methods" do
|
|
349
|
-
ap = Associations::MultiObjectProxy.new("TestResource", [{:service_uri => "/route", :scope_1 => {"scope_1" => true, :test_sub => false}, :scope_2 => {"scope_2" => true}}])
|
|
350
|
-
obj = ap.scope_1(:test_sub => true).scope_2
|
|
351
|
-
obj.to_query.should eql("scope_1=true&scope_2=true&test_sub=true")
|
|
390
|
+
ScopeResource.no_arg.to_query.should eql(
|
|
391
|
+
"no_arg=true"
|
|
392
|
+
)
|
|
393
|
+
ScopeResource.one_arg(5).to_query.should eql(
|
|
394
|
+
"one_arg[id]=5"
|
|
395
|
+
)
|
|
396
|
+
ScopeResource.one_array_arg([3, 5]).to_query.should eql(
|
|
397
|
+
"one_array_arg[ids][]=3&one_array_arg[ids][]=5"
|
|
398
|
+
)
|
|
399
|
+
ScopeResource.two_args(1, 20).to_query.should eql(
|
|
400
|
+
"two_args[page]=1&two_args[per_page]=20"
|
|
401
|
+
)
|
|
402
|
+
$DEB = true
|
|
403
|
+
ScopeResource.opt_args.to_query.should eql(
|
|
404
|
+
"opt_args=true"
|
|
405
|
+
)
|
|
406
|
+
ScopeResource.opt_args(3).to_query.should eql(
|
|
407
|
+
"opt_args[arg1]=3"
|
|
408
|
+
)
|
|
409
|
+
ScopeResource.var_args(1, 2).to_query.should eql(
|
|
410
|
+
"var_args[ids][]=1&var_args[ids][]=2"
|
|
411
|
+
)
|
|
412
|
+
args = ["a", {:opt1 => 1}, {:opt2 => 2}]
|
|
413
|
+
ScopeResource.mix_args(*args).to_query.should eql(
|
|
414
|
+
"mix_args[id]=a&mix_args[vararg][][opt1]=1&mix_args[vararg][][opt2]=2"
|
|
415
|
+
)
|
|
352
416
|
end
|
|
353
417
|
end
|
|
354
418
|
|
|
@@ -364,89 +428,96 @@ describe "Associations" do
|
|
|
364
428
|
end
|
|
365
429
|
|
|
366
430
|
it "should be able to force load an object" do
|
|
367
|
-
ap
|
|
368
|
-
ap.loaded.should be_blank
|
|
431
|
+
ap.should_not be_loaded
|
|
369
432
|
name = ap.name
|
|
370
433
|
name.should_not be_blank
|
|
371
|
-
ap.
|
|
434
|
+
ap.should be_loaded
|
|
372
435
|
# Make sure it isn't reloaded
|
|
373
436
|
ap.name.should eql(name)
|
|
374
437
|
end
|
|
375
438
|
|
|
376
|
-
it "should be able to load a scope" do
|
|
377
|
-
ap = Associations::SingleObjectProxy.new("TestResource",{:service_uri => '/single_object_association', :active => {:active => true}, :scopes_only => true})
|
|
378
|
-
ap.internal_object.active.should be_false
|
|
379
|
-
ap.times_loaded.should eql(1)
|
|
380
|
-
ap.active.should be_a Associations::RelationScope
|
|
381
|
-
ap.active.name.should_not be_blank
|
|
382
|
-
ap.times_loaded.should eql(2)
|
|
383
|
-
ap.active.internal_object.active.should be_true
|
|
384
|
-
# another check that the resource wasn't reloaded
|
|
385
|
-
ap.times_loaded.should eql(2)
|
|
386
|
-
end
|
|
387
|
-
|
|
388
|
-
it "should be able to load a chain of scopes" do
|
|
389
|
-
ap = Associations::SingleObjectProxy.new("TestResource",{:service_uri => '/single_object_association', :active => {:active => true}, :with_birthday => {:birthday => true}, :scopes_only => true})
|
|
390
|
-
first = ap.active.with_birthday.id
|
|
391
|
-
ap.with_birthday.active.id.should eql(first)
|
|
392
|
-
ap.times_loaded.should eql(1)
|
|
393
|
-
ap.active.with_birthday.birthday.should_not be_blank
|
|
394
|
-
end
|
|
395
439
|
|
|
396
440
|
it "should proxy unknown methods to the object loading if it hasn't already" do
|
|
397
|
-
ap = Associations::SingleObjectProxy.new(
|
|
398
|
-
|
|
441
|
+
ap = Associations::SingleObjectProxy.new(
|
|
442
|
+
"TestResource",
|
|
443
|
+
HasManyObject.new, {
|
|
444
|
+
:service_uri => '/single_object_association'
|
|
445
|
+
}
|
|
446
|
+
)
|
|
447
|
+
ap.should_not be_loaded
|
|
399
448
|
ap.id.should_not be_blank
|
|
400
|
-
ap.
|
|
449
|
+
ap.should be_loaded
|
|
401
450
|
end
|
|
402
451
|
|
|
403
452
|
it "should load scopes with caching" do
|
|
404
|
-
ap = Associations::SingleObjectProxy.new(
|
|
405
|
-
|
|
453
|
+
ap = Associations::SingleObjectProxy.new(
|
|
454
|
+
"TestResource",
|
|
455
|
+
HasManyObject.new, {
|
|
456
|
+
:service_uri => '/single_object_association'
|
|
457
|
+
}
|
|
458
|
+
)
|
|
459
|
+
ap.should_not be_loaded
|
|
406
460
|
ap.active.expires_in(30).internal_object
|
|
461
|
+
|
|
462
|
+
# should only be called once
|
|
463
|
+
TestResource.connection.expects(:get).never
|
|
407
464
|
ap.active.expires_in(30).internal_object
|
|
408
|
-
ap.
|
|
465
|
+
ap.should be_loaded
|
|
409
466
|
end
|
|
410
467
|
|
|
411
468
|
it "should check that ttl matches the expiration parameter" do
|
|
412
|
-
|
|
469
|
+
ap = Associations::SingleObjectProxy.new(
|
|
470
|
+
"TestResource",
|
|
471
|
+
HasManyObject.new, {
|
|
472
|
+
:service_uri => '/single_object_association'
|
|
473
|
+
}
|
|
474
|
+
)
|
|
413
475
|
ap.active.expires_in(10).ttl.should eql(10)
|
|
414
476
|
end
|
|
415
477
|
|
|
416
478
|
it "should cache scopes when caching enabled" do
|
|
417
|
-
ap = Associations::SingleObjectProxy.new(
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
ap
|
|
424
|
-
ap.times_loaded.should eql(0)
|
|
425
|
-
ap.active.with_birthday.internal_object
|
|
426
|
-
ap.active.with_birthday.internal_object
|
|
427
|
-
ap.with_birthday.active.internal_object
|
|
428
|
-
ap.times_loaded.should eql(1)
|
|
479
|
+
ap = Associations::SingleObjectProxy.new(
|
|
480
|
+
"TestResource",
|
|
481
|
+
HasManyObject.new, {
|
|
482
|
+
:service_uri => '/single_object_association'
|
|
483
|
+
}
|
|
484
|
+
)
|
|
485
|
+
ap.active(:expires_in => 10).internal_object
|
|
429
486
|
end
|
|
430
487
|
|
|
431
488
|
it "should be able to clear it's loading cache" do
|
|
432
|
-
ap = Associations::SingleObjectProxy.new(
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
489
|
+
ap = Associations::SingleObjectProxy.new(
|
|
490
|
+
"TestResource",
|
|
491
|
+
HasManyObject.new, {
|
|
492
|
+
:service_uri => '/single_object_association'
|
|
493
|
+
}
|
|
494
|
+
)
|
|
495
|
+
active = ap.active
|
|
496
|
+
|
|
497
|
+
active.internal_object
|
|
498
|
+
active.should be_loaded
|
|
499
|
+
active.reload
|
|
500
|
+
active.should_not be_loaded
|
|
501
|
+
active.internal_object
|
|
502
|
+
active.should be_loaded
|
|
438
503
|
end
|
|
439
504
|
|
|
440
505
|
end
|
|
441
506
|
|
|
442
507
|
it "should be able to reload a single-object association" do
|
|
443
|
-
ap = Associations::SingleObjectProxy.new(
|
|
508
|
+
ap = Associations::SingleObjectProxy.new(
|
|
509
|
+
"TestResource",
|
|
510
|
+
HasManyObject.new, {
|
|
511
|
+
:service_uri => '/single_object_association'
|
|
512
|
+
}
|
|
513
|
+
)
|
|
444
514
|
|
|
445
515
|
old_name = ap.name
|
|
446
516
|
|
|
447
517
|
str = "krdflkjsd"
|
|
448
518
|
|
|
449
519
|
ap.name = str
|
|
520
|
+
|
|
450
521
|
ap.name.should eql str
|
|
451
522
|
ap.reload
|
|
452
523
|
|
|
@@ -454,7 +525,13 @@ describe "Associations" do
|
|
|
454
525
|
end
|
|
455
526
|
|
|
456
527
|
it "should be able to reload a multi-object association" do
|
|
457
|
-
|
|
528
|
+
|
|
529
|
+
ap = Associations::MultiObjectProxy.new(
|
|
530
|
+
"TestResource",
|
|
531
|
+
BelongsToObject.new, {
|
|
532
|
+
:service_uri => '/multi_object_association'
|
|
533
|
+
}
|
|
534
|
+
)
|
|
458
535
|
|
|
459
536
|
old_name = ap.first.name
|
|
460
537
|
|
|
@@ -471,7 +548,10 @@ describe "Associations" do
|
|
|
471
548
|
it "should propagate the scopes from the associated class" do
|
|
472
549
|
|
|
473
550
|
ap = Associations::MultiObjectProxy.new(
|
|
474
|
-
"TestResource",
|
|
551
|
+
"TestResource",
|
|
552
|
+
BelongsToObject.new, {
|
|
553
|
+
:service_uri => '/multi_object_association'
|
|
554
|
+
}
|
|
475
555
|
)
|
|
476
556
|
ap.scopes.should eql(TestResource.scopes)
|
|
477
557
|
true
|
|
@@ -481,63 +561,68 @@ describe "Associations" do
|
|
|
481
561
|
context "Multi Object" do
|
|
482
562
|
|
|
483
563
|
it "should be able to load 'all'" do
|
|
484
|
-
ap = Associations::MultiObjectProxy.new(
|
|
564
|
+
ap = Associations::MultiObjectProxy.new(
|
|
565
|
+
"TestResource",
|
|
566
|
+
BelongsToObject.new, {
|
|
567
|
+
:service_uri => '/multi_object_association'
|
|
568
|
+
}
|
|
569
|
+
)
|
|
485
570
|
results = ap.all
|
|
486
571
|
results.size.should eql(5)
|
|
487
|
-
results.first.
|
|
572
|
+
results.first.is_active?.should be_false
|
|
488
573
|
end
|
|
489
574
|
|
|
490
575
|
it "should be able to load a scope" do
|
|
491
|
-
ap = Associations::MultiObjectProxy.new(
|
|
492
|
-
|
|
576
|
+
ap = Associations::MultiObjectProxy.new(
|
|
577
|
+
"TestResource",
|
|
578
|
+
BelongsToObject.new, {
|
|
579
|
+
:service_uri => '/multi_object_association'
|
|
580
|
+
}
|
|
581
|
+
)
|
|
582
|
+
results = ap.active
|
|
493
583
|
results.size.should eql(5)
|
|
494
|
-
results.first
|
|
584
|
+
record = results.first
|
|
585
|
+
record.is_active.should be_true
|
|
495
586
|
end
|
|
496
587
|
|
|
497
588
|
it "should be able to load a chain of scopes" do
|
|
498
|
-
ap = Associations::MultiObjectProxy.new(
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
589
|
+
ap = Associations::MultiObjectProxy.new(
|
|
590
|
+
"TestResource",
|
|
591
|
+
BelongsToObject.new, {
|
|
592
|
+
:service_uri => '/multi_object_association'
|
|
593
|
+
}
|
|
594
|
+
)
|
|
595
|
+
results = ap.active.birthday(Date.today)
|
|
596
|
+
results.first.is_active.should be_true
|
|
597
|
+
results.first.bday.should_not be_blank
|
|
502
598
|
end
|
|
503
599
|
|
|
504
|
-
it "should be able to load a chain of scopes with substitution" do
|
|
505
|
-
ap = Associations::MultiObjectProxy.new("TestResource",{:service_uri => '/multi_object_association', :active => {:active => true}, :inactive => {:active => false}, :with_birthday => {:birthday => true}})
|
|
506
|
-
results = ap.inactive(:active => true).with_birthday.internal_object
|
|
507
|
-
results.first.active.should be_true
|
|
508
|
-
results.first.birthday.should_not be_blank
|
|
509
|
-
end
|
|
510
600
|
|
|
511
|
-
it "should
|
|
512
|
-
ap = Associations::MultiObjectProxy.new("TestResource",{:service_uri => '/multi_object_association', :active => {:active => true}, :inactive => {:active => false}, :with_birthday => {:birthday => true}})
|
|
513
|
-
ap.first.should be_a TestResource
|
|
514
|
-
ap.active.first.should be_a TestResource
|
|
515
|
-
ap.times_loaded.should eql(2)
|
|
516
|
-
end
|
|
601
|
+
it "should be able to clear it's loading cache" do
|
|
517
602
|
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
ap.
|
|
525
|
-
ap.active.with_birthday.first
|
|
526
|
-
ap.with_birthday.active.first
|
|
527
|
-
ap.times_loaded.should eql(3)
|
|
528
|
-
end
|
|
603
|
+
ap = Associations::MultiObjectProxy.new(
|
|
604
|
+
"TestResource",
|
|
605
|
+
BelongsToObject.new, {
|
|
606
|
+
:service_uri => '/multi_object_association'
|
|
607
|
+
}
|
|
608
|
+
)
|
|
609
|
+
active = ap.active
|
|
529
610
|
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
ap.times_loaded.should eql(1)
|
|
611
|
+
active.internal_object
|
|
612
|
+
active.should be_loaded
|
|
613
|
+
active.reload
|
|
614
|
+
active.should_not be_loaded
|
|
615
|
+
active.internal_object
|
|
616
|
+
active.should be_loaded
|
|
537
617
|
end
|
|
538
618
|
|
|
539
619
|
it "should be enumerable" do
|
|
540
|
-
ap = Associations::MultiObjectProxy.new(
|
|
620
|
+
ap = Associations::MultiObjectProxy.new(
|
|
621
|
+
"TestResource",
|
|
622
|
+
BelongsToObject.new, {
|
|
623
|
+
:service_uri => '/multi_object_association'
|
|
624
|
+
}
|
|
625
|
+
)
|
|
541
626
|
ap.each do |tr|
|
|
542
627
|
tr.name.should_not be_blank
|
|
543
628
|
end
|
|
@@ -562,9 +647,11 @@ describe "Associations" do
|
|
|
562
647
|
end
|
|
563
648
|
|
|
564
649
|
it "should be able to chain scopes" do
|
|
565
|
-
scp = TestResource.active.paginate
|
|
566
|
-
scp.should be_a Associations::
|
|
567
|
-
scp.to_query.should eql(
|
|
650
|
+
scp = TestResource.active.paginate(20, 1)
|
|
651
|
+
scp.should be_a Associations::Scope
|
|
652
|
+
scp.to_query.should eql(
|
|
653
|
+
"active=true&paginate[current_page]=1&paginate[per_page]=20"
|
|
654
|
+
)
|
|
568
655
|
end
|
|
569
656
|
|
|
570
657
|
it "should load when calling all" do
|
|
@@ -718,7 +805,9 @@ describe "Associations" do
|
|
|
718
805
|
it "should attempt to load a single remote object for a has_one relationship" do
|
|
719
806
|
tar = TestAR.new
|
|
720
807
|
tar.stubs(:id).returns(1)
|
|
721
|
-
TestResource.connection.expects(:get)
|
|
808
|
+
TestResource.connection.expects(:get)
|
|
809
|
+
.with("/test_resources.json?test_ar_id=1")
|
|
810
|
+
.returns([{"name" => "testing"}])
|
|
722
811
|
# load the test resource
|
|
723
812
|
tar.test_resource.name.should eql "testing"
|
|
724
813
|
end
|
data/spec/lib/attributes_spec.rb
CHANGED
|
@@ -3,11 +3,39 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
|
|
3
3
|
include ApiResource
|
|
4
4
|
|
|
5
5
|
describe "Attributes" do
|
|
6
|
+
|
|
7
|
+
before(:all) do
|
|
8
|
+
TestResource.reload_class_attributes
|
|
9
|
+
end
|
|
6
10
|
|
|
7
11
|
after(:all) do
|
|
8
12
|
TestResource.reload_class_attributes
|
|
9
13
|
end
|
|
10
|
-
|
|
14
|
+
|
|
15
|
+
context "setters" do
|
|
16
|
+
|
|
17
|
+
it "should allow setting of protected attributes individually" do
|
|
18
|
+
test_resource = TestResource.new
|
|
19
|
+
test_resource.protected_attr = 100
|
|
20
|
+
test_resource.protected_attr.should eql(100)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it "should not allow mass assignment of protected attributes" do
|
|
24
|
+
test_resource = TestResource.new
|
|
25
|
+
lambda{
|
|
26
|
+
test_resource.attributes = {:protected_attr => 100}
|
|
27
|
+
}.should raise_error
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it "should not allow mass assignment in the constructor" do
|
|
31
|
+
lambda{
|
|
32
|
+
TestResource.new({:protected_attr => 100})
|
|
33
|
+
}.should raise_error
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
|
|
11
39
|
context "Defining, getting, and setting attributes" do
|
|
12
40
|
it "should be able to define known attributes" do
|
|
13
41
|
TestResource.define_attributes :attr1, :attr2
|
|
@@ -76,12 +104,12 @@ describe "Attributes" do
|
|
|
76
104
|
end
|
|
77
105
|
|
|
78
106
|
it "should create protected attributes for unknown attributes trying to be loaded" do
|
|
79
|
-
|
|
107
|
+
|
|
108
|
+
TestResource.connection.stubs(:get => {:attr1 => "attr1", :attr3 => "attr3"})
|
|
109
|
+
tst = TestResource.find(1)
|
|
110
|
+
|
|
80
111
|
tst.attr3?.should be_true
|
|
81
112
|
tst.attr3.should eql("attr3")
|
|
82
|
-
lambda {
|
|
83
|
-
tst.attr3 = "test"
|
|
84
|
-
}.should raise_error
|
|
85
113
|
end
|
|
86
114
|
end
|
|
87
115
|
|
|
@@ -116,16 +144,6 @@ describe "Attributes" do
|
|
|
116
144
|
|
|
117
145
|
end
|
|
118
146
|
|
|
119
|
-
context "Protected attributes" do
|
|
120
|
-
it "should allow protected attributes that cannot be changed" do
|
|
121
|
-
TestResource.define_protected_attributes :pattr3
|
|
122
|
-
lambda {
|
|
123
|
-
tst = TestResource.new
|
|
124
|
-
tst.pattr3 = "test"
|
|
125
|
-
}.should raise_error
|
|
126
|
-
end
|
|
127
|
-
end
|
|
128
|
-
|
|
129
147
|
context "Dirty tracking" do
|
|
130
148
|
context "Changes to attributes" do
|
|
131
149
|
it "should implement dirty tracking for attributes" do
|