api_resource 0.5.1 → 0.6.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/.document +5 -0
- data/.gitignore +55 -0
- data/.rspec +8 -0
- data/.travis.yml +9 -0
- data/Gemfile +3 -36
- data/Gemfile.lock +37 -57
- data/Guardfile +7 -1
- data/{LICENSE.txt → LICENSE} +4 -2
- data/README.md +29 -0
- data/README.rdoc +5 -1
- data/Rakefile +5 -36
- data/api_resource.gemspec +40 -104
- data/lib/api_resource.rb +4 -1
- data/lib/api_resource/associations.rb +30 -14
- data/lib/api_resource/associations/association_proxy.rb +97 -0
- data/lib/api_resource/associations/belongs_to_remote_object_proxy.rb +0 -1
- data/lib/api_resource/associations/has_many_remote_object_proxy.rb +0 -1
- data/lib/api_resource/associations/has_one_remote_object_proxy.rb +7 -4
- data/lib/api_resource/associations/multi_object_proxy.rb +11 -16
- data/lib/api_resource/associations/single_object_proxy.rb +8 -6
- data/lib/api_resource/attributes.rb +29 -41
- data/lib/api_resource/base.rb +31 -102
- data/lib/api_resource/conditions.rb +36 -0
- data/lib/api_resource/conditions/abstract_condition.rb +112 -0
- data/lib/api_resource/conditions/association_condition.rb +18 -0
- data/lib/api_resource/conditions/include_condition.rb +16 -0
- data/lib/api_resource/conditions/multi_object_association_condition.rb +17 -0
- data/lib/api_resource/conditions/scope_condition.rb +11 -0
- data/lib/api_resource/conditions/single_object_association_condition.rb +19 -0
- data/lib/api_resource/connection.rb +18 -12
- data/lib/api_resource/finders.rb +122 -0
- data/lib/api_resource/finders/abstract_finder.rb +89 -0
- data/lib/api_resource/finders/multi_object_association_finder.rb +39 -0
- data/lib/api_resource/finders/resource_finder.rb +33 -0
- data/lib/api_resource/finders/single_object_association_finder.rb +40 -0
- data/lib/api_resource/observing.rb +19 -3
- data/lib/api_resource/scopes.rb +3 -3
- data/lib/api_resource/typecast.rb +85 -0
- data/lib/api_resource/typecasters/array_typecaster.rb +19 -0
- data/lib/api_resource/typecasters/boolean_typecaster.rb +22 -0
- data/lib/api_resource/typecasters/date_typecaster.rb +35 -0
- data/lib/api_resource/typecasters/float_typecaster.rb +22 -0
- data/lib/api_resource/typecasters/integer_typecaster.rb +22 -0
- data/lib/api_resource/typecasters/string_typecaster.rb +19 -0
- data/lib/api_resource/typecasters/time_typecaster.rb +44 -0
- data/lib/api_resource/version.rb +3 -0
- data/spec/lib/api_resource_spec.rb +6 -0
- data/spec/lib/associations/association_scope_spec.rb +1 -1
- data/spec/lib/associations_spec.rb +17 -50
- data/spec/lib/base_spec.rb +22 -0
- data/spec/lib/conditions/abstract_conditions_spec.rb +78 -0
- data/spec/lib/connection_spec.rb +19 -0
- data/spec/lib/finders/multi_object_association_finder_spec.rb +43 -0
- data/spec/lib/finders/resource_finder_spec.rb +89 -0
- data/spec/lib/finders/single_object_association_finder_spec.rb +43 -0
- data/spec/lib/observing_spec.rb +96 -0
- data/spec/lib/typecast_spec.rb +174 -0
- data/spec/lib/typecasters/boolean_typecaster_spec.rb +33 -0
- data/spec/lib/typecasters/date_typecaster_spec.rb +62 -0
- data/spec/lib/typecasters/float_typecaster_spec.rb +39 -0
- data/spec/lib/typecasters/integer_typecaster_spec.rb +40 -0
- data/spec/lib/typecasters/string_typecaster_spec.rb +28 -0
- data/spec/lib/typecasters/time_typecaster_spec.rb +65 -0
- data/spec/spec_helper.rb +0 -1
- metadata +134 -194
- data/VERSION +0 -1
- data/coverage/assets/0.5.3/app.js +0 -88
- 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 +0 -363
- data/coverage/assets/0.5.3/fancybox/jquery.fancybox-1.3.1.pack.js +0 -44
- 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 +0 -129
- data/coverage/assets/0.5.3/highlight.pack.js +0 -1
- data/coverage/assets/0.5.3/jquery-1.6.2.min.js +0 -18
- data/coverage/assets/0.5.3/jquery.dataTables.min.js +0 -152
- data/coverage/assets/0.5.3/jquery.timeago.js +0 -141
- data/coverage/assets/0.5.3/jquery.url.js +0 -174
- 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 +0 -295
- data/coverage/assets/0.5.3/stylesheet.css +0 -383
- data/coverage/assets/0.7.1/application.css +0 -1110
- data/coverage/assets/0.7.1/application.js +0 -626
- data/coverage/assets/0.7.1/fancybox/blank.gif +0 -0
- data/coverage/assets/0.7.1/fancybox/fancy_close.png +0 -0
- data/coverage/assets/0.7.1/fancybox/fancy_loading.png +0 -0
- data/coverage/assets/0.7.1/fancybox/fancy_nav_left.png +0 -0
- data/coverage/assets/0.7.1/fancybox/fancy_nav_right.png +0 -0
- data/coverage/assets/0.7.1/fancybox/fancy_shadow_e.png +0 -0
- data/coverage/assets/0.7.1/fancybox/fancy_shadow_n.png +0 -0
- data/coverage/assets/0.7.1/fancybox/fancy_shadow_ne.png +0 -0
- data/coverage/assets/0.7.1/fancybox/fancy_shadow_nw.png +0 -0
- data/coverage/assets/0.7.1/fancybox/fancy_shadow_s.png +0 -0
- data/coverage/assets/0.7.1/fancybox/fancy_shadow_se.png +0 -0
- data/coverage/assets/0.7.1/fancybox/fancy_shadow_sw.png +0 -0
- data/coverage/assets/0.7.1/fancybox/fancy_shadow_w.png +0 -0
- data/coverage/assets/0.7.1/fancybox/fancy_title_left.png +0 -0
- data/coverage/assets/0.7.1/fancybox/fancy_title_main.png +0 -0
- data/coverage/assets/0.7.1/fancybox/fancy_title_over.png +0 -0
- data/coverage/assets/0.7.1/fancybox/fancy_title_right.png +0 -0
- data/coverage/assets/0.7.1/fancybox/fancybox-x.png +0 -0
- data/coverage/assets/0.7.1/fancybox/fancybox-y.png +0 -0
- data/coverage/assets/0.7.1/fancybox/fancybox.png +0 -0
- data/coverage/assets/0.7.1/favicon_green.png +0 -0
- data/coverage/assets/0.7.1/favicon_red.png +0 -0
- data/coverage/assets/0.7.1/favicon_yellow.png +0 -0
- data/coverage/assets/0.7.1/loading.gif +0 -0
- data/coverage/assets/0.7.1/magnify.png +0 -0
- data/coverage/assets/0.7.1/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
- data/coverage/assets/0.7.1/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
- data/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
- data/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
- data/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
- data/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
- data/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
- data/coverage/assets/0.7.1/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
- data/coverage/assets/0.7.1/smoothness/images/ui-icons_222222_256x240.png +0 -0
- data/coverage/assets/0.7.1/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
- data/coverage/assets/0.7.1/smoothness/images/ui-icons_454545_256x240.png +0 -0
- data/coverage/assets/0.7.1/smoothness/images/ui-icons_888888_256x240.png +0 -0
- data/coverage/assets/0.7.1/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
- data/coverage/index.html +0 -3564
- data/lib/api_resource/associations/abstract_scope.rb +0 -191
- data/lib/api_resource/associations/association_scope.rb +0 -47
- data/lib/api_resource/associations/resource_scope.rb +0 -21
- data/lib/api_resource/associations/scope.rb +0 -34
- data/spec/lib/associations/resource_scope_spec.rb +0 -24
- data/spec/tmp/api_resource_test_db.sqlite +0 -0
- data/tmp/rspec_guard_result +0 -1
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
module ApiResource
|
|
2
|
+
|
|
3
|
+
module Typecast
|
|
4
|
+
|
|
5
|
+
TRUE_VALUES = [true, 1, '1', 't', 'T', 'true', 'TRUE'].to_set
|
|
6
|
+
FALSE_VALUES = [false, 0, '0', 'f', 'F', 'false', 'FALSE'].to_set
|
|
7
|
+
|
|
8
|
+
module BooleanTypecaster
|
|
9
|
+
|
|
10
|
+
def self.from_api(value)
|
|
11
|
+
TRUE_VALUES.include?(value)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def self.to_api(value)
|
|
15
|
+
value
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
module ApiResource
|
|
2
|
+
|
|
3
|
+
module Typecast
|
|
4
|
+
|
|
5
|
+
ISO_DATE = /\A(\d{4})-(\d\d)-(\d\d)\z/
|
|
6
|
+
|
|
7
|
+
module DateTypecaster
|
|
8
|
+
|
|
9
|
+
def self.from_api(value)
|
|
10
|
+
return value if value.is_a?(Date)
|
|
11
|
+
|
|
12
|
+
value = value.to_s
|
|
13
|
+
if value =~ ApiResource::Typecast::ISO_DATE
|
|
14
|
+
return self.new_date($1.to_i, $2.to_i, $3.to_i)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
self.new_date(*::Date._parse(value, false).values_at(:year, :mon, :mday))
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def self.to_api(value)
|
|
21
|
+
return value.to_s
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
protected
|
|
25
|
+
|
|
26
|
+
def self.new_date(year, month, day)
|
|
27
|
+
return nil unless year && year != 0
|
|
28
|
+
return Date.new(year, month, day) rescue nil
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
module ApiResource
|
|
2
|
+
|
|
3
|
+
module Typecast
|
|
4
|
+
|
|
5
|
+
module FloatTypecaster
|
|
6
|
+
|
|
7
|
+
def self.from_api(value)
|
|
8
|
+
return value.to_f if value.respond_to?(:to_f)
|
|
9
|
+
# Special case for true to return 1.0
|
|
10
|
+
return 1.0 if value.class == TrueClass
|
|
11
|
+
return value.to_s.to_f
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def self.to_api(value)
|
|
15
|
+
value
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
module ApiResource
|
|
2
|
+
|
|
3
|
+
module Typecast
|
|
4
|
+
|
|
5
|
+
module IntegerTypecaster
|
|
6
|
+
|
|
7
|
+
def self.from_api(value)
|
|
8
|
+
return value.to_i if value.respond_to?(:to_i)
|
|
9
|
+
# Special case so that true typecasts to 1
|
|
10
|
+
return 1 if value.class == TrueClass
|
|
11
|
+
return value.to_s.to_i
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def self.to_api(value)
|
|
15
|
+
value
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
require 'active_support/time'
|
|
2
|
+
|
|
3
|
+
module ApiResource
|
|
4
|
+
|
|
5
|
+
module Typecast
|
|
6
|
+
|
|
7
|
+
ISO_DATETIME = /\A(\d{4})-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)(\.\d+)?\z/
|
|
8
|
+
|
|
9
|
+
module TimeTypecaster
|
|
10
|
+
|
|
11
|
+
def self.from_api(value)
|
|
12
|
+
return value if value.is_a?(Time)
|
|
13
|
+
value = value.to_s
|
|
14
|
+
return nil if value.empty?
|
|
15
|
+
|
|
16
|
+
if value =~ ApiResource::Typecast::ISO_DATETIME
|
|
17
|
+
micro = ($7.to_f * 1_000_000).to_i
|
|
18
|
+
return self.new_time($1.to_i, $2.to_i, $3.to_i, $4.to_i, $5.to_i, $6.to_i, micro)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
time_info = Date._parse(value)
|
|
22
|
+
time_info[:micro] = ((time_info[:sec_fraction].to_f % 1) * 1_000_000).to_i
|
|
23
|
+
|
|
24
|
+
new_time(*time_info.values_at(:year, :mon, :mday, :hour, :min, :sec, :micro))
|
|
25
|
+
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def self.to_api(value)
|
|
29
|
+
return value.to_s
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
protected
|
|
33
|
+
|
|
34
|
+
def self.new_time(*args)
|
|
35
|
+
year = args.first
|
|
36
|
+
return nil if year.nil? || year == 0
|
|
37
|
+
Time.utc(*args) rescue nil
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
end
|
|
@@ -81,6 +81,13 @@ describe "Associations" do
|
|
|
81
81
|
TestResource.association_class_name(:strange_name).should eql("BelongsToObject")
|
|
82
82
|
end
|
|
83
83
|
|
|
84
|
+
it "should be able to return the name of the foreign key field field for the association" do
|
|
85
|
+
TestResource.belongs_to :belongs_to_object
|
|
86
|
+
TestResource.has_many :has_many_objects
|
|
87
|
+
TestResource.association_foreign_key_field(:belongs_to_object).should eql(:belongs_to_object_id)
|
|
88
|
+
TestResource.association_foreign_key_field(:has_many_objects).should eql(:has_many_object_ids)
|
|
89
|
+
end
|
|
90
|
+
|
|
84
91
|
it "should only define relationships for the given class - they should not cascade" do
|
|
85
92
|
TestResource.belongs_to :belongs_to_object
|
|
86
93
|
AnotherTestResource.association?(:belongs_to_object).should_not be_true
|
|
@@ -338,38 +345,6 @@ describe "Associations" do
|
|
|
338
345
|
end
|
|
339
346
|
end
|
|
340
347
|
|
|
341
|
-
context "Defining scopes" do
|
|
342
|
-
|
|
343
|
-
it "should identify known scopes based on the scopes defined on
|
|
344
|
-
the object it is a proxy to" do
|
|
345
|
-
|
|
346
|
-
TestResource.scope :class_scope, "class_scope" => "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
|
|
354
|
-
end
|
|
355
|
-
|
|
356
|
-
it "scopes in the response should shadow class defined scopes" do
|
|
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
|
-
)
|
|
369
|
-
ap.scopes[:scope1].should eql({"scope1" => true})
|
|
370
|
-
end
|
|
371
|
-
end
|
|
372
|
-
|
|
373
348
|
end
|
|
374
349
|
|
|
375
350
|
describe "Selecting scopes" do
|
|
@@ -421,6 +396,12 @@ describe "Associations" do
|
|
|
421
396
|
|
|
422
397
|
describe "Loading and Caching loaded data" do
|
|
423
398
|
|
|
399
|
+
|
|
400
|
+
before(:each) do
|
|
401
|
+
# Clear the cache to prevent any funny business
|
|
402
|
+
ApiResource.cache(true)
|
|
403
|
+
end
|
|
404
|
+
|
|
424
405
|
context "Single Object" do
|
|
425
406
|
|
|
426
407
|
before(:all) do
|
|
@@ -460,9 +441,8 @@ describe "Associations" do
|
|
|
460
441
|
ap.active.expires_in(30).internal_object
|
|
461
442
|
|
|
462
443
|
# should only be called once
|
|
463
|
-
TestResource.connection.expects(:
|
|
444
|
+
TestResource.connection.expects(:request).never
|
|
464
445
|
ap.active.expires_in(30).internal_object
|
|
465
|
-
ap.should be_loaded
|
|
466
446
|
end
|
|
467
447
|
|
|
468
448
|
it "should check that ttl matches the expiration parameter" do
|
|
@@ -545,19 +525,6 @@ describe "Associations" do
|
|
|
545
525
|
ap.first.name.should eql old_name
|
|
546
526
|
end
|
|
547
527
|
|
|
548
|
-
it "should propagate the scopes from the associated class" do
|
|
549
|
-
|
|
550
|
-
ap = Associations::MultiObjectProxy.new(
|
|
551
|
-
"TestResource",
|
|
552
|
-
BelongsToObject.new, {
|
|
553
|
-
:service_uri => '/multi_object_association'
|
|
554
|
-
}
|
|
555
|
-
)
|
|
556
|
-
ap.scopes.should eql(TestResource.scopes)
|
|
557
|
-
true
|
|
558
|
-
end
|
|
559
|
-
|
|
560
|
-
|
|
561
528
|
context "Multi Object" do
|
|
562
529
|
|
|
563
530
|
it "should be able to load 'all'" do
|
|
@@ -642,13 +609,13 @@ describe "Associations" do
|
|
|
642
609
|
end
|
|
643
610
|
end
|
|
644
611
|
|
|
645
|
-
it "should return a
|
|
646
|
-
TestResource.send(TestResource.scopes.first.first.to_sym).should be_a
|
|
612
|
+
it "should return a ScopeCondition when calling any scope on a class" do
|
|
613
|
+
TestResource.send(TestResource.scopes.first.first.to_sym).should be_a Conditions::ScopeCondition
|
|
647
614
|
end
|
|
648
615
|
|
|
649
616
|
it "should be able to chain scopes" do
|
|
650
617
|
scp = TestResource.active.paginate(20, 1)
|
|
651
|
-
scp.should be_a
|
|
618
|
+
scp.should be_a Conditions::ScopeCondition
|
|
652
619
|
scp.to_query.should eql(
|
|
653
620
|
"active=true&paginate[current_page]=1&paginate[per_page]=20"
|
|
654
621
|
)
|
data/spec/lib/base_spec.rb
CHANGED
|
@@ -38,6 +38,27 @@ describe "Base" do
|
|
|
38
38
|
|
|
39
39
|
end
|
|
40
40
|
|
|
41
|
+
context ".load_resource_definition" do
|
|
42
|
+
|
|
43
|
+
it "should not inherit from unrelated objects" do
|
|
44
|
+
|
|
45
|
+
ErrorResource.new
|
|
46
|
+
orig_public_attr_names = ErrorResource.public_attribute_names
|
|
47
|
+
orig_protected_attr_names = ErrorResource.protected_attribute_names
|
|
48
|
+
|
|
49
|
+
TestResource.new
|
|
50
|
+
|
|
51
|
+
ErrorResource.public_attribute_names.should eql(
|
|
52
|
+
orig_public_attr_names
|
|
53
|
+
)
|
|
54
|
+
ErrorResource.protected_attribute_names.should eql(
|
|
55
|
+
orig_protected_attr_names
|
|
56
|
+
)
|
|
57
|
+
true
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
end
|
|
61
|
+
|
|
41
62
|
context "Comparison" do
|
|
42
63
|
|
|
43
64
|
context "&group_by" do
|
|
@@ -516,6 +537,7 @@ describe "Base" do
|
|
|
516
537
|
context "Updating old records" do
|
|
517
538
|
before(:all) do
|
|
518
539
|
TestResource.reload_resource_definition
|
|
540
|
+
HasOneObject.reload_resource_definition
|
|
519
541
|
TestResource.has_many :has_many_objects
|
|
520
542
|
RestClient::Payload.stubs(:has_file? => false)
|
|
521
543
|
end
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe "Conditions" do
|
|
4
|
+
|
|
5
|
+
before(:each) do
|
|
6
|
+
TestResource.reload_resource_definition
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
it "should chain scopes onto the base class" do
|
|
10
|
+
|
|
11
|
+
obj = TestResource.active
|
|
12
|
+
obj.should be_a ApiResource::Conditions::ScopeCondition
|
|
13
|
+
|
|
14
|
+
obj2 = TestResource.paginate
|
|
15
|
+
|
|
16
|
+
TestResource.expects(:paginate).returns(obj2)
|
|
17
|
+
|
|
18
|
+
obj3 = obj.paginate
|
|
19
|
+
|
|
20
|
+
obj3.to_query.should eql("active=true&paginate=true")
|
|
21
|
+
obj3.should_not be_eager_load
|
|
22
|
+
obj3.should_not be_blank_conditions
|
|
23
|
+
# Make sure that it clones
|
|
24
|
+
|
|
25
|
+
obj3.object_id.should_not eql(obj.object_id)
|
|
26
|
+
obj3.object_id.should_not eql(obj2.object_id)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it "should properly deal with calling includes" do
|
|
30
|
+
obj = TestResource.includes(:has_many_objects).active
|
|
31
|
+
|
|
32
|
+
obj.should be_eager_load
|
|
33
|
+
obj.should_not be_blank_conditions
|
|
34
|
+
obj.association.should be_nil
|
|
35
|
+
obj.to_query.should eql("active=true")
|
|
36
|
+
obj.included_objects.should eql([:has_many_objects])
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it "should be able to chain includes and scopes" do
|
|
40
|
+
obj = TestResource.includes(:has_many_objects).active.includes(:belongs_to_object)
|
|
41
|
+
|
|
42
|
+
obj.should be_eager_load
|
|
43
|
+
obj.should_not be_blank_conditions
|
|
44
|
+
obj.included_objects.should eql([:has_many_objects, :belongs_to_object])
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it "should be able to include multiple includes in the same call" do
|
|
48
|
+
obj = TestResource.includes(:has_many_objects, :belongs_to_object)
|
|
49
|
+
|
|
50
|
+
obj.should be_eager_load
|
|
51
|
+
obj.should be_blank_conditions
|
|
52
|
+
obj.included_objects.should eql([:has_many_objects, :belongs_to_object])
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
it "should raise an error if given an include that isn't a valid association" do
|
|
56
|
+
lambda {
|
|
57
|
+
TestResource.includes(:fake_assoc)
|
|
58
|
+
}.should raise_error
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
it "should create a resource finder when forced to load, and cache the result" do
|
|
62
|
+
obj = TestResource.includes(:has_many_objects)
|
|
63
|
+
|
|
64
|
+
ApiResource::Finders::ResourceFinder.expects(:new).with(TestResource, obj).returns(mock(:find => [1]))
|
|
65
|
+
obj.internal_object.should eql([1])
|
|
66
|
+
obj.all.should eql([1])
|
|
67
|
+
obj.first.should eql(1)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
it "should proxy calls to enumerable and array methods to the loaded object" do
|
|
71
|
+
obj = TestResource.includes(:has_many_objects)
|
|
72
|
+
|
|
73
|
+
ApiResource::Finders::ResourceFinder.expects(:new).with(TestResource, obj).returns(mock(:find => [1,2]))
|
|
74
|
+
|
|
75
|
+
obj.collect{|o| o * 2}.should eql([2,4])
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
end
|