api_resource 0.4.3 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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