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.
Files changed (89) hide show
  1. data/VERSION +1 -1
  2. data/api_resource.gemspec +4 -74
  3. data/coverage/assets/0.5.3/app.js +88 -0
  4. data/coverage/assets/0.5.3/fancybox/blank.gif +0 -0
  5. data/coverage/assets/0.5.3/fancybox/fancy_close.png +0 -0
  6. data/coverage/assets/0.5.3/fancybox/fancy_loading.png +0 -0
  7. data/coverage/assets/0.5.3/fancybox/fancy_nav_left.png +0 -0
  8. data/coverage/assets/0.5.3/fancybox/fancy_nav_right.png +0 -0
  9. data/coverage/assets/0.5.3/fancybox/fancy_shadow_e.png +0 -0
  10. data/coverage/assets/0.5.3/fancybox/fancy_shadow_n.png +0 -0
  11. data/coverage/assets/0.5.3/fancybox/fancy_shadow_ne.png +0 -0
  12. data/coverage/assets/0.5.3/fancybox/fancy_shadow_nw.png +0 -0
  13. data/coverage/assets/0.5.3/fancybox/fancy_shadow_s.png +0 -0
  14. data/coverage/assets/0.5.3/fancybox/fancy_shadow_se.png +0 -0
  15. data/coverage/assets/0.5.3/fancybox/fancy_shadow_sw.png +0 -0
  16. data/coverage/assets/0.5.3/fancybox/fancy_shadow_w.png +0 -0
  17. data/coverage/assets/0.5.3/fancybox/fancy_title_left.png +0 -0
  18. data/coverage/assets/0.5.3/fancybox/fancy_title_main.png +0 -0
  19. data/coverage/assets/0.5.3/fancybox/fancy_title_over.png +0 -0
  20. data/coverage/assets/0.5.3/fancybox/fancy_title_right.png +0 -0
  21. data/coverage/assets/0.5.3/fancybox/fancybox-x.png +0 -0
  22. data/coverage/assets/0.5.3/fancybox/fancybox-y.png +0 -0
  23. data/coverage/assets/0.5.3/fancybox/fancybox.png +0 -0
  24. data/coverage/assets/0.5.3/fancybox/jquery.fancybox-1.3.1.css +363 -0
  25. data/coverage/assets/0.5.3/fancybox/jquery.fancybox-1.3.1.pack.js +44 -0
  26. data/coverage/assets/0.5.3/favicon_green.png +0 -0
  27. data/coverage/assets/0.5.3/favicon_red.png +0 -0
  28. data/coverage/assets/0.5.3/favicon_yellow.png +0 -0
  29. data/coverage/assets/0.5.3/highlight.css +129 -0
  30. data/coverage/assets/0.5.3/highlight.pack.js +1 -0
  31. data/coverage/assets/0.5.3/jquery-1.6.2.min.js +18 -0
  32. data/coverage/assets/0.5.3/jquery.dataTables.min.js +152 -0
  33. data/coverage/assets/0.5.3/jquery.timeago.js +141 -0
  34. data/coverage/assets/0.5.3/jquery.url.js +174 -0
  35. data/coverage/assets/0.5.3/loading.gif +0 -0
  36. data/coverage/assets/0.5.3/magnify.png +0 -0
  37. data/coverage/assets/0.5.3/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  38. data/coverage/assets/0.5.3/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  39. data/coverage/assets/0.5.3/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  40. data/coverage/assets/0.5.3/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  41. data/coverage/assets/0.5.3/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  42. data/coverage/assets/0.5.3/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  43. data/coverage/assets/0.5.3/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  44. data/coverage/assets/0.5.3/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  45. data/coverage/assets/0.5.3/smoothness/images/ui-icons_222222_256x240.png +0 -0
  46. data/coverage/assets/0.5.3/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
  47. data/coverage/assets/0.5.3/smoothness/images/ui-icons_454545_256x240.png +0 -0
  48. data/coverage/assets/0.5.3/smoothness/images/ui-icons_888888_256x240.png +0 -0
  49. data/coverage/assets/0.5.3/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
  50. data/coverage/assets/0.5.3/smoothness/jquery-ui-1.8.4.custom.css +295 -0
  51. data/coverage/assets/0.5.3/stylesheet.css +383 -0
  52. data/coverage/index.html +3573 -0
  53. data/lib/api_resource/associations/abstract_scope.rb +191 -0
  54. data/lib/api_resource/associations/association_scope.rb +47 -0
  55. data/lib/api_resource/associations/belongs_to_remote_object_proxy.rb +5 -6
  56. data/lib/api_resource/associations/has_many_remote_object_proxy.rb +5 -8
  57. data/lib/api_resource/associations/has_one_remote_object_proxy.rb +12 -13
  58. data/lib/api_resource/associations/multi_object_proxy.rb +65 -39
  59. data/lib/api_resource/associations/resource_scope.rb +6 -17
  60. data/lib/api_resource/associations/scope.rb +23 -121
  61. data/lib/api_resource/associations/single_object_proxy.rb +41 -50
  62. data/lib/api_resource/associations.rb +32 -11
  63. data/lib/api_resource/attributes.rb +108 -69
  64. data/lib/api_resource/base.rb +114 -106
  65. data/lib/api_resource/local.rb +1 -1
  66. data/lib/api_resource/model_errors.rb +9 -6
  67. data/lib/api_resource/scopes.rb +53 -16
  68. data/lib/api_resource.rb +3 -1
  69. data/spec/lib/api_resource_spec.rb +3 -7
  70. data/spec/lib/associations/association_scope_spec.rb +19 -0
  71. data/spec/lib/associations_spec.rb +251 -162
  72. data/spec/lib/attributes_spec.rb +33 -15
  73. data/spec/lib/base_spec.rb +302 -64
  74. data/spec/lib/callbacks_spec.rb +4 -2
  75. data/spec/lib/local_spec.rb +5 -1
  76. data/spec/spec_helper.rb +2 -3
  77. data/spec/support/mocks/association_mocks.rb +9 -1
  78. data/spec/support/requests/association_requests.rb +5 -5
  79. data/spec/support/requests/test_resource_requests.rb +16 -4
  80. data/spec/tmp/api_resource_test_db.sqlite +0 -0
  81. metadata +68 -22
  82. data/.document +0 -5
  83. data/.rspec +0 -5
  84. data/.travis.yml +0 -4
  85. data/lib/api_resource/associations/association_proxy.rb +0 -121
  86. data/lib/api_resource/associations/dynamic_resource_scope.rb +0 -23
  87. data/lib/api_resource/associations/generic_scope.rb +0 -68
  88. data/lib/api_resource/associations/multi_argument_resource_scope.rb +0 -15
  89. 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("TestResource",{:service_uri => "/path"})
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 and not make them scopes" do
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("TestResource",{:service_uri => "/path", :test => "testval"})
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.remote_path.should eql("/path")
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("TestResource",[])
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("TestResource",[{:service_uri => "/route"}])
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("TestResource",[{:the_element => "/route"}])
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("TestResource", {:hi => 3})
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("TestResource", {:service_uri => "/route"})
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("TestResource",{:the_element => "/route"})
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 define scopes based on the other keys in a settings hash" do
282
- ap = Associations::MultiObjectProxy.new("TestResource", [{:service_uri => "/route", :scope1 => {"scope1" => true}, :scope2 => {"scope2" => true}}])
283
- [:scope1, :scope2].each{|s| ap.scopes.include?(s).should be_true }
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
- ap = Associations::MultiObjectProxy.new("TestResource", [{:service_uri => "/route", :scope1 => {"scope1" => true}, :scope2 => {"scope2" => true}}])
289
- [:scope1, :scope2, :class_scope].each{|s| ap.scopes.include?(s).should be_true}
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 :scope1, "scope1" => "true"
294
- ap = Associations::MultiObjectProxy.new("TestResource", [{:service_uri => "/route", :scope1 => {"scope1" => true}, :scope2 => {"scope2" => true}}])
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 "no_arg=true"
317
- # ScopeResource.one_arg(5).to_query.should eql "one_arg[id]=5"
318
- # ScopeResource.one_array_arg([3, 5]).to_query.should eql "one_array_arg[ids][]=3&one_array_arg[ids][]=5"
319
- # ScopeResource.two_args(1, 20).to_query.should eql "two_args[page]=1&two_args[per_page]=20"
320
- # ScopeResource.opt_arg.to_query.should eql "opt_args=true"
321
- # ScopeResource.opt_args(3).to_query.should eql "opt_args[arg1]=3"
322
- # ScopeResource.var_args(1, 2).to_query.should eql "var_args[ids][]=1&var_args[ids][]=2"
323
- # ScopeResource.mix_args("a", {:opt1 => 1}, {:opt2 => 2}).to_query.should eql "mix_args[arg1]=a&mix_args[vararg][][opt1]=1&mix_arg[vararg][][opt2]=2"
324
- end
325
-
326
- it "should be able to change scopes" do
327
- ap = Associations::MultiObjectProxy.new("TestResource", [{:service_uri => "/route", :scope1 => {"scope1" => true}, :scope2 => {"scope2" => true}}])
328
- ap.scope1.should be_a(Associations::RelationScope)
329
- ap.scope1.current_scope.scope1_scope?.should be_true
330
- end
331
-
332
- it "should be able to chain scope calls together" do
333
- ap = Associations::MultiObjectProxy.new("TestResource", [{:service_uri => "/route", :scope1 => {"scope1" => true}, :scope2 => {"scope2" => true}}])
334
- ap.scope1.scope2.current_scope.scope1_and_scope2_scope?.should be_true
335
- ap.scope1.scope2.to_query.should eql("scope1=true&scope2=true")
336
- end
337
-
338
- it "should support scopes that contain underscores" do
339
- ap = Associations::MultiObjectProxy.new("TestResource", [{:service_uri => "/route", :scope_1 => {"scope_1" => true}, :scope_2 => {"scope_2" => true}}])
340
- ap.scope_1.scope_2.current_scope.scope_1_and_scope_2_scope?.should be_true
341
- end
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 = Associations::SingleObjectProxy.new("TestResource",{:service_uri => '/single_object_association', :active => {:active => true}, :scopes_only => true})
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.loaded.should_not be_blank
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("TestResource",{:service_uri => '/single_object_association', :active => {:active => false}, :with_birthday => {:birthday => true}, :scopes_only => true})
398
- ap.times_loaded.should eql(0)
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.times_loaded.should eql(1)
449
+ ap.should be_loaded
401
450
  end
402
451
 
403
452
  it "should load scopes with caching" do
404
- ap = Associations::SingleObjectProxy.new("TestResource",{:service_uri => '/single_object_association', :active => {:active => true}, :scopes_only => true})
405
- ap.times_loaded.should eql(0)
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.times_loaded.should eql(1)
465
+ ap.should be_loaded
409
466
  end
410
467
 
411
468
  it "should check that ttl matches the expiration parameter" do
412
- ap = Associations::SingleObjectProxy.new("TestResource",{:service_uri => '/single_object_association', :active => {:active => true}, :scopes_only => true})
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("TestResource",{:service_uri => '/single_object_association', :active => {:active => false}, :with_birthday => {:birthday => true}, :scopes_only => true})
418
- ApiResource.expects(:with_ttl).with(10)
419
- ap.active(:active => true, :expires_in => 10).internal_object
420
- end
421
-
422
- it "should only load each distinct set of scopes once" do
423
- ap = Associations::SingleObjectProxy.new("TestResource",{:service_uri => '/single_object_association', :active => {:active => false}, :with_birthday => {:birthday => true}, :scopes_only => true})
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("TestResource",{:service_uri => '/single_object_association', :active => {:active => true}, :with_birthday => {:birthday => true}, :scopes_only => true})
433
- ap.active.internal_object
434
- ap.times_loaded.should eql(1)
435
- ap.reload
436
- ap.active.internal_object
437
- ap.times_loaded.should eql(1)
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("TestResource",{:service_uri => '/single_object_association', :active => {:active => true}, :scopes_only => true})
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
- ap = Associations::MultiObjectProxy.new("TestResource",{:service_uri => '/multi_object_association', :active => {:active => false}, :inactive => {:active => false}, :with_birthday => {:birthday => true}})
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", {:service_uri => "/multi_object_association"}
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("TestResource",{:service_uri => '/multi_object_association', :active => {:active => false}, :inactive => {:active => false}, :with_birthday => {:birthday => true}})
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.active.should be_false
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("TestResource",{:service_uri => '/multi_object_association', :active => {:active => false}, :inactive => {:active => false}, :with_birthday => {:birthday => true}})
492
- results = ap.active.internal_object
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.active.should be_true
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("TestResource",{:service_uri => '/multi_object_association', :active => {:active => true}, :inactive => {:active => false}, :with_birthday => {:birthday => true}})
499
- results = ap.active.with_birthday.internal_object
500
- results.first.active.should be_true
501
- results.first.birthday.should_not be_blank
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 proxy unknown methods to the object array loading if it hasn't already" do
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
- it "should only load each distinct set of scopes once" do
519
- ap = Associations::MultiObjectProxy.new("TestResource",{:service_uri => '/multi_object_association', :active => {:active => true}, :inactive => {:active => false}, :with_birthday => {:birthday => true}})
520
- ap.first
521
- ap.active.first
522
- ap.times_loaded.should eql(2)
523
- ap.active.first
524
- ap.times_loaded.should eql(2)
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
- it "should be able to clear it's loading cache" do
531
- ap = Associations::MultiObjectProxy.new("TestResource",{:service_uri => '/multi_object_association', :active => {:active => true}, :inactive => {:active => false}, :with_birthday => {:birthday => true}})
532
- ap.active.first
533
- ap.times_loaded.should eql(1)
534
- ap.reload
535
- ap.active.first
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("TestResource",{:service_uri => '/multi_object_association', :active => {:active => true}, :inactive => {:active => false}, :with_birthday => {:birthday => true}})
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::ResourceScope
567
- scp.to_query.should eql("active=true&paginate=true")
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).with("/test_resources.json?test_ar_id=1").once.returns([{"name" => "testing"}])
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
@@ -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
- tst = TestResource.new({:attr1 => "attr1", :attr3 => "attr3"})
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