api_resource 0.6.21 → 0.6.22

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 (58) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +1 -0
  3. data/Gemfile.lock +1 -1
  4. data/LICENSE.txt +22 -0
  5. data/README.md +16 -9
  6. data/docs/Attributes.md +64 -0
  7. data/docs/Caching.md +45 -0
  8. data/docs/GettingStarted.md +149 -0
  9. data/docs/Relationships.md +136 -0
  10. data/docs/ResourceDefinition.md +80 -0
  11. data/docs/Retrieval.md +279 -0
  12. data/docs/Serialization.md +56 -0
  13. data/lib/api_resource/associations/has_many_remote_object_proxy.rb +2 -2
  14. data/lib/api_resource/attributes.rb +16 -4
  15. data/lib/api_resource/base.rb +98 -19
  16. data/lib/api_resource/conditions/abstract_condition.rb +241 -129
  17. data/lib/api_resource/conditions/include_condition.rb +7 -1
  18. data/lib/api_resource/conditions/pagination_condition.rb +37 -0
  19. data/lib/api_resource/conditions/where_condition.rb +19 -0
  20. data/lib/api_resource/conditions.rb +18 -2
  21. data/lib/api_resource/connection.rb +27 -13
  22. data/lib/api_resource/exceptions.rb +11 -11
  23. data/lib/api_resource/finders/abstract_finder.rb +176 -95
  24. data/lib/api_resource/finders/multi_object_association_finder.rb +10 -9
  25. data/lib/api_resource/finders/resource_finder.rb +59 -49
  26. data/lib/api_resource/finders/single_finder.rb +5 -6
  27. data/lib/api_resource/finders/single_object_association_finder.rb +52 -51
  28. data/lib/api_resource/finders.rb +1 -1
  29. data/lib/api_resource/formats/file_upload_format.rb +75 -0
  30. data/lib/api_resource/formats.rb +4 -1
  31. data/lib/api_resource/response.rb +108 -0
  32. data/lib/api_resource/scopes.rb +62 -5
  33. data/lib/api_resource/serializer.rb +1 -1
  34. data/lib/api_resource/typecasters/boolean_typecaster.rb +1 -0
  35. data/lib/api_resource/typecasters/integer_typecaster.rb +1 -0
  36. data/lib/api_resource/typecasters/time_typecaster.rb +12 -4
  37. data/lib/api_resource/version.rb +1 -1
  38. data/lib/api_resource.rb +1 -0
  39. data/spec/lib/associations/has_one_remote_object_proxy_spec.rb +4 -4
  40. data/spec/lib/associations_spec.rb +3 -3
  41. data/spec/lib/attributes_spec.rb +16 -1
  42. data/spec/lib/base_spec.rb +121 -39
  43. data/spec/lib/conditions/{abstract_conditions_spec.rb → abstract_condition_spec.rb} +23 -11
  44. data/spec/lib/conditions/pagination_condition_spec.rb +88 -0
  45. data/spec/lib/finders/multi_object_association_finder_spec.rb +55 -27
  46. data/spec/lib/finders/resource_finder_spec.rb +26 -2
  47. data/spec/lib/finders/single_object_association_finder_spec.rb +14 -6
  48. data/spec/lib/finders_spec.rb +81 -81
  49. data/spec/lib/observing_spec.rb +3 -4
  50. data/spec/lib/response_spec.rb +18 -0
  51. data/spec/lib/scopes_spec.rb +25 -1
  52. data/spec/lib/typecasters/boolean_typecaster_spec.rb +1 -1
  53. data/spec/lib/typecasters/integer_typecaster_spec.rb +1 -1
  54. data/spec/lib/typecasters/time_typecaster_spec.rb +6 -0
  55. data/spec/support/files/bg-awesome.jpg +0 -0
  56. data/spec/support/mocks/test_resource_mocks.rb +26 -16
  57. data/spec/support/requests/test_resource_requests.rb +27 -23
  58. metadata +24 -4
@@ -0,0 +1,88 @@
1
+ require 'spec_helper'
2
+
3
+ module ApiResource
4
+
5
+ module Conditions
6
+
7
+ describe PaginationCondition do
8
+
9
+ context '.paginate' do
10
+
11
+ it 'returns an object that knows it is paginated from the base
12
+ class' do
13
+ paginated = TestResource.paginate(page: 1, per_page: 10).active
14
+ expect(paginated).to be_paginated
15
+ end
16
+
17
+ it 'returns an object that knows it is paginated from a scope' do
18
+ paginated = TestResource.active.paginate(
19
+ page: 1,
20
+ per_page: 10
21
+ )
22
+ expect(paginated).to be_paginated
23
+ end
24
+
25
+ end
26
+
27
+ context '#current_page' do
28
+
29
+ it 'knows its page number' do
30
+ paginated = TestResource.paginate(page: 1, per_page: 10).active
31
+ expect(paginated.current_page).to be 1
32
+ end
33
+
34
+ end
35
+
36
+ context '#offset' do
37
+
38
+ it 'passes along the headers for the total number of entries' do
39
+ paginated = TestResource.paginate(
40
+ page: 2,
41
+ per_page: 10
42
+ )
43
+ expect(paginated.offset).to be 10
44
+ end
45
+
46
+ end
47
+
48
+ context '#per_page' do
49
+
50
+ it 'knows its number per page' do
51
+ paginated = TestResource.paginate(
52
+ page: 2,
53
+ per_page: 100
54
+ )
55
+ expect(paginated.per_page).to be 100
56
+ end
57
+
58
+ end
59
+
60
+ context '#total_entries' do
61
+
62
+ it 'passes along the headers for the total number of entries' do
63
+ paginated = TestResource.paginate(
64
+ page: 1,
65
+ per_page: 10
66
+ )
67
+ expect(paginated.total_entries).to be 100
68
+ end
69
+
70
+ end
71
+
72
+ context '#total_pages' do
73
+
74
+ it 'calculates the number of pages' do
75
+ paginated = TestResource.paginate(
76
+ page: 1,
77
+ per_page: 12
78
+ )
79
+ expect(paginated.total_pages).to be 9
80
+ end
81
+
82
+ end
83
+
84
+ end
85
+
86
+ end
87
+
88
+ end
@@ -5,39 +5,67 @@ describe "MultiObjectAssociationFinder" do
5
5
  before(:each) do
6
6
  TestResource.reload_resource_definition
7
7
  end
8
-
9
- it "should build a proper load path and call into the connection" do
10
- TestResource.connection.expects(:get).with("test_resources.json?id[]=1&id[]=2").returns([])
11
-
12
- ApiResource::Finders::MultiObjectAssociationFinder.new(
13
- TestResource,
14
- stub(:remote_path => "test_resources", :to_query => "id[]=1&id[]=2", :blank_conditions? => false)
15
- ).load
8
+
9
+ context "#load" do
10
+
11
+ it "should build a proper load path and call into the connection" do
12
+ TestResource.connection.expects(:get).with("test_resources.json?id[]=1&id[]=2").returns([])
13
+
14
+ ApiResource::Finders::MultiObjectAssociationFinder.new(
15
+ TestResource,
16
+ stub(remote_path: "test_resources", to_query: "id[]=1&id[]=2", :blank_conditions? => false)
17
+ ).load
18
+ end
19
+
20
+ it "should load a has many association properly" do
21
+ # much of this test already lies in resource_finder_spec.rb
22
+ # this just verifies that the data is passed in correctly
23
+ finder = ApiResource::Finders::MultiObjectAssociationFinder.new(
24
+ TestResource,
25
+ stub(
26
+ remote_path: "test_resources",
27
+ blank_conditions?: true,
28
+ eager_load?: true,
29
+ included_objects: [:has_many_objects]
30
+ )
31
+ )
32
+
33
+ tr = TestResource.new
34
+ tr.stubs(:id).returns(1)
35
+ tr.stubs(:has_many_object_ids).returns([1,2])
36
+ TestResource.connection.expects(:get).with("test_resources.json").returns([4])
37
+ TestResource.expects(:instantiate_collection).with([4]).returns([tr])
38
+
39
+ finder.expects(:load_includes).with(has_many_objects: [1,2]).returns(5)
40
+ finder.expects(:apply_includes).with([tr], 5).returns(6)
41
+
42
+ finder.load.should eql([tr])
43
+ end
16
44
  end
17
45
 
18
- it "should load a has many association properly" do
19
- # much of this test already lies in resource_finder_spec.rb
20
- # this just verifies that the data is passed in correctly
21
- finder = ApiResource::Finders::MultiObjectAssociationFinder.new(
22
- TestResource,
23
- stub(
24
- :remote_path => "test_resources",
25
- :blank_conditions? => true,
26
- :eager_load? => true,
27
- :included_objects => [:has_many_objects]
46
+ context "#select" do
47
+
48
+ it "properly sends #select to its internal object" do
49
+
50
+ TestResource.connection.stubs(:get)
51
+ .with("test_resources.json?id[]=1&id[]=2")
52
+ .returns([{"name" => "Dan"}])
53
+
54
+ finder = ApiResource::Finders::MultiObjectAssociationFinder.new(
55
+ TestResource,
56
+ stub(
57
+ remote_path: "test_resources",
58
+ to_query: "id[]=1&id[]=2",
59
+ blank_conditions?: false,
60
+ included_objects: [],
61
+ eager_load?: true
62
+ )
28
63
  )
29
- )
30
64
 
31
- tr = TestResource.new
32
- tr.stubs(:id).returns(1)
33
- tr.stubs(:has_many_object_ids).returns([1,2])
34
- TestResource.connection.expects(:get).with("test_resources.json").returns([4])
35
- TestResource.expects(:instantiate_collection).with([4]).returns([tr])
65
+ expect(finder.select{|r| r.name == 'Dan'}.length).to eql(1)
36
66
 
37
- finder.expects(:load_includes).with(:has_many_objects => [1,2]).returns(5)
38
- finder.expects(:apply_includes).with([tr], 5).returns(6)
67
+ end
39
68
 
40
- finder.load.should eql([tr])
41
69
  end
42
70
 
43
71
  end
@@ -4,7 +4,6 @@ describe "ResourceFinder" do
4
4
 
5
5
  before(:each) do
6
6
  TestResource.reload_resource_definition
7
-
8
7
  end
9
8
 
10
9
  it "should load normally without includes using connection.get" do
@@ -20,7 +19,7 @@ describe "ResourceFinder" do
20
19
  TestResource.connection.expects(:get).with("/test_resources.json?ids%5B%5D=1&ids%5B%5D=2&ids%5B%5D=3")
21
20
 
22
21
  ApiResource::Finders::ResourceFinder.new(
23
- TestResource,
22
+ TestResource,
24
23
  mock(:to_hash => {:ids => [1,2,3]})
25
24
  ).load
26
25
  end
@@ -75,4 +74,29 @@ describe "ResourceFinder" do
75
74
  obj.second.has_many_objects.collect(&:id).should eql([2])
76
75
  end
77
76
 
77
+ context 'Headers returned from the server' do
78
+
79
+ context '#total_entries' do
80
+
81
+ it 'stores the ApiResource-Total-Entries as total_entries' do
82
+
83
+ finder = ApiResource::Finders::ResourceFinder.new(
84
+ TestResource,
85
+ ApiResource::Conditions::PaginationCondition.new(
86
+ TestResource,
87
+ { page: 2, per_page: 10 }
88
+ )
89
+ )
90
+
91
+ finder.load
92
+
93
+ expect(finder.total_entries).to be 100
94
+
95
+
96
+ end
97
+
98
+ end
99
+
100
+ end
101
+
78
102
  end
@@ -7,12 +7,20 @@ describe "SingleObjectAssociationFinder" do
7
7
  end
8
8
 
9
9
  it "should build a proper load path and call into the connection" do
10
- TestResource.connection.expects(:get).with("test_resources.json?id[]=1&id[]=2").returns(nil)
10
+ TestResource.connection
11
+ .expects(:get)
12
+ .with("test_resources.json?id[]=1&id[]=2")
13
+ .returns(nil)
11
14
 
12
- ApiResource::Finders::SingleObjectAssociationFinder.new(
15
+ finder = ApiResource::Finders::SingleObjectAssociationFinder.new(
13
16
  TestResource,
14
- stub(:remote_path => "test_resources", :to_query => "id[]=1&id[]=2", :blank_conditions? => false)
15
- ).load
17
+ stub(
18
+ :remote_path => "test_resources",
19
+ :to_query => "id[]=1&id[]=2",
20
+ :blank_conditions? => false
21
+ )
22
+ )
23
+ finder.load
16
24
  end
17
25
 
18
26
  it "should load a has many association properly" do
@@ -21,9 +29,9 @@ describe "SingleObjectAssociationFinder" do
21
29
  finder = ApiResource::Finders::SingleObjectAssociationFinder.new(
22
30
  TestResource,
23
31
  stub(
24
- :remote_path => "test_resources",
32
+ :remote_path => "test_resources",
25
33
  :blank_conditions? => true,
26
- :eager_load? => true,
34
+ :eager_load? => true,
27
35
  :included_objects => [:has_many_objects]
28
36
  )
29
37
  )
@@ -2,114 +2,114 @@ require 'spec_helper'
2
2
 
3
3
  describe ApiResource::Finders do
4
4
 
5
- before(:each) do
6
- TestResource.reload_resource_definition
7
- end
5
+ before(:each) do
6
+ TestResource.reload_resource_definition
7
+ end
8
8
 
9
- it "should be able to find a single object" do
10
- TestResource.connection.expects(:get).with("/test_resources/1.json")
9
+ it "should be able to find a single object" do
10
+ TestResource.connection.expects(:get).with("/test_resources/1.json")
11
11
 
12
- TestResource.find(1)
13
- end
12
+ TestResource.find(1)
13
+ end
14
14
 
15
- it "should be able to find with parameters, params syntax" do
16
- TestResource.connection.expects(:get).with("/test_resources.json?active=true")
17
- TestResource.all(:params => {:active => true})
18
- end
15
+ it "should be able to find with parameters, params syntax" do
16
+ TestResource.connection.expects(:get).with("/test_resources.json?active=true")
17
+ TestResource.all(:params => {:active => true})
18
+ end
19
19
 
20
- it "should be able to find with parameters without the params syntax" do
21
- TestResource.connection.expects(:get).with("/test_resources.json?active=true&passive=false")
20
+ it "should be able to find with parameters without the params syntax" do
21
+ TestResource.connection.expects(:get).with("/test_resources.json?active=true&passive=false")
22
22
 
23
- TestResource.all(:active => true, :passive => false)
24
- end
23
+ TestResource.all(:active => true, :passive => false)
24
+ end
25
25
 
26
- it "should be able to chain find on top of a scope" do
27
- TestResource.connection.expects(:get).with("/test_resources.json?active=true&passive=true")
28
- TestResource.active.all(:passive => true)
29
- end
26
+ it "should be able to chain find on top of a scope" do
27
+ TestResource.connection.expects(:get).with("/test_resources.json?active=true&passive=true")
28
+ TestResource.active.all(:passive => true)
29
+ end
30
30
 
31
- it "should be able to find a single object after a scope" do
32
- TestResource.connection.expects(:get)
33
- .with("/test_resources.json?birthday%5Bdate%5D=5&find%5Bids%5D=1").returns([{"id" => 10}])
31
+ it "should be able to find a single object as an enumerable after a scope" do
32
+ TestResource.connection.expects(:get)
33
+ .with("/test_resources.json?birthday%5Bdate%5D=5&find%5Bids%5D=1").returns([{"id" => 10}])
34
34
 
35
- val = TestResource.birthday(5).find(1)
36
- val.should be_a(TestResource)
37
- end
35
+ val = TestResource.birthday(5).find(1)
36
+ val.first.should be_a(TestResource)
37
+ end
38
38
 
39
- it "should be able to find multiple objects after a scope" do
40
- TestResource.connection.expects(:get)
41
- .with("/test_resources.json?birthday%5Bdate%5D=5&find%5Bids%5D=1").returns([{"id" => 10}, {"id" => 8}])
39
+ it "should be able to find multiple objects after a scope" do
40
+ TestResource.connection.expects(:get)
41
+ .with("/test_resources.json?birthday%5Bdate%5D=5&find%5Bids%5D=1").returns([{"id" => 10}, {"id" => 8}])
42
42
 
43
- val = TestResource.birthday(5).find(1)
44
- val.should be_a(Array)
45
- val.first.should be_a(TestResource)
46
- end
43
+ val = TestResource.birthday(5).find(1)
44
+ val.should be_a(Array)
45
+ val.first.should be_a(TestResource)
46
+ end
47
47
 
48
- it "should be able to find the first/last object" do
49
- TestResource.connection.expects(:get)
50
- .with("/test_resources.json?first=true").returns([{"id" => 10}])
48
+ it "should be able to find the first/last object" do
49
+ TestResource.connection.expects(:get)
50
+ .with("/test_resources.json?first=true").returns([{"id" => 10}])
51
51
 
52
- val = TestResource.first
53
- val.should be_a(TestResource)
54
- end
52
+ val = TestResource.first
53
+ val.should be_a(TestResource)
54
+ end
55
55
 
56
- it "should pass first and last as params" do
57
- TestResource.connection.expects(:get)
58
- .with("/test_resources.json?first=true")
56
+ it "should pass first and last as params" do
57
+ TestResource.connection.expects(:get)
58
+ .with("/test_resources.json?first=true")
59
59
 
60
- val = TestResource.first
60
+ val = TestResource.first
61
61
 
62
- TestResource.connection.expects(:get)
63
- .with("/test_resources.json?last=true")
62
+ TestResource.connection.expects(:get)
63
+ .with("/test_resources.json?last=true")
64
64
 
65
- val = TestResource.last
66
- end
65
+ val = TestResource.last
66
+ end
67
67
 
68
- it "should not pass all as a param, even when all records are requested" do
69
- TestResource.connection.expects(:get)
70
- .with("/test_resources.json")
68
+ it "should not pass all as a param, even when all records are requested" do
69
+ TestResource.connection.expects(:get)
70
+ .with("/test_resources.json")
71
71
 
72
- val = TestResource.all
73
- end
72
+ val = TestResource.all
73
+ end
74
74
 
75
- it "should be able to chain find on top of an includes call" do
76
- TestResource.connection.expects(:get).with("/test_resources/1.json").returns({"id" => 1, "has_many_object_ids" => [1,2]})
77
- HasManyObject.connection.expects(:get).with("/has_many_objects.json?ids%5B%5D=1&ids%5B%5D=2").returns([])
75
+ it "should be able to chain find on top of an includes call" do
76
+ TestResource.connection.expects(:get).with("/test_resources/1.json").returns({"id" => 1, "has_many_object_ids" => [1,2]})
77
+ HasManyObject.connection.expects(:get).with("/has_many_objects.json?ids%5B%5D=1&ids%5B%5D=2").returns([])
78
78
 
79
- TestResource.includes(:has_many_objects).find(1)
80
- end
79
+ TestResource.includes(:has_many_objects).find(1)
80
+ end
81
81
 
82
- it "should be able to chain find on top of an includes call and a scope" do
83
- TestResource.connection.expects(:get).with("/test_resources.json?birthday%5Bdate%5D=5&find%5Bids%5D=1").returns({"id" => 1, "has_many_object_ids" => [1,2]})
84
- HasManyObject.connection.expects(:get).with("/has_many_objects.json?ids%5B%5D=1&ids%5B%5D=2").returns([])
82
+ it "should be able to chain find on top of an includes call and a scope" do
83
+ TestResource.connection.expects(:get).with("/test_resources.json?birthday%5Bdate%5D=5&find%5Bids%5D=1").returns({"id" => 1, "has_many_object_ids" => [1,2]})
84
+ HasManyObject.connection.expects(:get).with("/has_many_objects.json?ids%5B%5D=1&ids%5B%5D=2").returns([])
85
85
 
86
- TestResource.includes(:has_many_objects).birthday(5).find(1)
87
- end
86
+ TestResource.includes(:has_many_objects).birthday(5).find(1)
87
+ end
88
88
 
89
- it "should disregard condition order" do
90
- TestResource.connection.expects(:get).with("/test_resources.json?birthday%5Bdate%5D=5&find%5Bids%5D=1").returns({"id" => 1, "has_many_object_ids" => [1,2]})
91
- HasManyObject.connection.expects(:get).with("/has_many_objects.json?ids%5B%5D=1&ids%5B%5D=2").returns([])
89
+ it "should disregard condition order" do
90
+ TestResource.connection.expects(:get).with("/test_resources.json?birthday%5Bdate%5D=5&find%5Bids%5D=1").returns({"id" => 1, "has_many_object_ids" => [1,2]})
91
+ HasManyObject.connection.expects(:get).with("/has_many_objects.json?ids%5B%5D=1&ids%5B%5D=2").returns([])
92
92
 
93
- TestResource.birthday(5).includes(:has_many_objects).find(1)
94
- end
93
+ TestResource.birthday(5).includes(:has_many_objects).find(1)
94
+ end
95
95
 
96
- it "should be able to use a scope with arguments" do
97
- TestResource.connection.expects(:get)
98
- .with("/test_resources.json?active=true&birthday%5Bdate%5D=5").returns([{"id" => 10}])
96
+ it "should be able to use a scope with arguments" do
97
+ TestResource.connection.expects(:get)
98
+ .with("/test_resources.json?active=true&birthday%5Bdate%5D=5").returns([{"id" => 10}])
99
99
 
100
- res = TestResource.active.birthday(5).all
101
- res.should be_a(Array)
102
- res.first.id.should eql(10)
103
- end
100
+ res = TestResource.active.birthday(5).all
101
+ res.should be_a(Array)
102
+ res.first.id.should eql(10)
103
+ end
104
104
 
105
- it "should be able to use a scope with multiple arguments" do
106
- TestResource.connection.expects(:get)
107
- .with("/test_resources.json?paginate%5Bcurrent_page%5D=10&paginate%5Bper_page%5D=5")
108
- .returns([{:id => 20}])
105
+ it "should be able to use a scope with multiple arguments" do
106
+ TestResource.connection.expects(:get)
107
+ .with("/test_resources.json?boolean%5Ba%5D=5&boolean%5Bb%5D=10")
108
+ .returns([{:id => 20}])
109
109
 
110
- res = TestResource.paginate(5, 10).all
111
- res.should be_a(Array)
112
- res.first.id.should eql(20)
113
- end
110
+ res = TestResource.boolean(5, 10).all
111
+ res.should be_a(Array)
112
+ res.first.id.should eql(20)
113
+ end
114
114
 
115
115
  end
@@ -77,16 +77,15 @@ describe "Observing" do
77
77
  end
78
78
 
79
79
  it "should run callbacks before observers" do
80
- klass = Class.new(TestResource)
81
- klass.class_eval <<-EOE, __FILE__, __LINE__ + 1
80
+ class ChildObserverResource < TestResource
82
81
  before_save :abort_save
83
82
 
84
83
  def abort_save
85
84
  return false
86
85
  end
87
- EOE
86
+ end
88
87
 
89
- tr = klass.new
88
+ tr = ChildObserverResource.new
90
89
  tr.expects(:abort_save).returns(false)
91
90
  tr.expects(:notify_observers).never
92
91
  tr.expects(:save_without_callbacks).never
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+
3
+ module ApiResource
4
+
5
+ describe Response do
6
+
7
+ context '#initialize' do
8
+
9
+ it 'handles a blank body' do
10
+ raw_response = stub(headers: {}, body: nil)
11
+ expect(Response.new(raw_response)).to be_blank
12
+ end
13
+
14
+ end
15
+
16
+ end
17
+
18
+ end
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe ApiResource::Scopes do
4
-
4
+
5
5
  before(:all) do
6
6
  ScopeResource.class_eval do
7
7
  scope :no_arg, {}
@@ -12,6 +12,7 @@ describe ApiResource::Scopes do
12
12
  scope :req_and_opt_args, {arg1: :req, arg2: :opt}
13
13
  scope :var_args, {ids: :rest}
14
14
  scope :mix_args, {id: :req, vararg: :rest}
15
+ scope :date_scope, {start_date: :req, end_date: :req}
15
16
  end
16
17
  end
17
18
 
@@ -59,6 +60,18 @@ describe ApiResource::Scopes do
59
60
  ScopeResource.add_scopes(one_arg: {id: 5})
60
61
  end
61
62
 
63
+ it 'does not apply scopes with a blank argument' do
64
+ ScopeResource.expects(:one_arg).never
65
+ ScopeResource.add_scopes(one_arg: {id: ""})
66
+ ScopeResource.add_scopes(one_arg: {id: nil})
67
+ end
68
+
69
+ it 'does not apply scopes when a parameter is missing' do
70
+ ScopeResource.expects(:two_args).never
71
+ ScopeResource.add_scopes(two_args: { page: 1 })
72
+ ScopeResource.add_scopes(two_args: { per_page: 1 })
73
+ end
74
+
62
75
  it 'applies scopes with an array argument' do
63
76
  ScopeResource.expects(:one_array_arg).with([5]).returns(ScopeResource)
64
77
  ScopeResource.add_scopes(one_array_arg: {ids: [5]})
@@ -93,6 +106,17 @@ describe ApiResource::Scopes do
93
106
  ScopeResource.expects(:mix_args).with(4,[5,6,7]).returns(ScopeResource)
94
107
  ScopeResource.add_scopes(mix_args: {id: 4, vararg: [5,6,7]})
95
108
  end
109
+
110
+ it 'parses dates if the parameters are correctly named' do
111
+ ScopeResource.expects(:date_scope)
112
+ .with(instance_of(Date), instance_of(Date))
113
+ .returns(ScopeResource)
114
+
115
+ ScopeResource.add_scopes({
116
+ date_scope: { start_date: 'May 6, 2013', end_date: 'June 8, 2014' }
117
+ })
118
+ end
119
+
96
120
  end
97
121
 
98
122
  end
@@ -13,7 +13,7 @@ describe ApiResource::Typecast::BooleanTypecaster do
13
13
  end
14
14
 
15
15
  it "should return false for any other conceivable input" do
16
- [Date.new, Time.new, Date.today, Time.now, nil, false, Float, 2.0, 2, "", "bad value"].each do |val|
16
+ [Date.new, Time.new, Date.today, Time.now, false, Float, 2.0, 2, "", "bad value"].each do |val|
17
17
  klass.from_api(val).should be_instance_of(FalseClass)
18
18
  end
19
19
  end
@@ -22,7 +22,7 @@ describe ApiResource::Typecast::IntegerTypecaster do
22
22
  end
23
23
 
24
24
  it "should be able to typecast any value you can think of" do
25
- klass.from_api(nil).should eql(0)
25
+ klass.from_api(nil).should eql(nil)
26
26
  klass.from_api("").should eql(nil)
27
27
  klass.from_api(BasicObject).should eql(0)
28
28
  klass.from_api("abc").should eql(0)
@@ -29,6 +29,12 @@ describe ApiResource::Typecast::TimeTypecaster do
29
29
  val.day.should eql(28)
30
30
  end
31
31
 
32
+ it "should parse a date not in ISO format with a time zone" do
33
+ val = klass.from_api("2012-12-21T19:29:20-04:00")
34
+ val.hour.should eql(23)
35
+ val.zone.to_s.should eql("UTC")
36
+ end
37
+
32
38
  it "should parse a date not in ISO format" do
33
39
  val = klass.from_api("2012/08/09")
34
40
  val.year.should eql(2012)
Binary file
@@ -1,47 +1,57 @@
1
1
  include ApiResource
2
2
 
3
3
  Mocks.define do
4
-
4
+
5
5
  endpoint("/test_resources/new") do
6
6
  get(HashDealer.roll(:new_test_object))
7
+ get(HashDealer.roll(:new_test_object), params: {type: 'X'}.matcher)
7
8
  end
8
-
9
+
9
10
  endpoint("/test_resources") do
10
- post(HashDealer.roll(:test_resource).merge(:id => 1), :params => {:test_resource => HashDealer.roll(:test_resource).matcher})
11
- post(HashDealer.roll(:test_resource).merge(:id => 1), :params => {:test_resource => HashDealer.roll(:test_resource_with_roles).matcher})
11
+ post(HashDealer.roll(:test_resource).merge(id: 1), params: {test_resource: HashDealer.roll(:test_resource).matcher})
12
+ post(HashDealer.roll(:test_resource).merge(id: 1), params: {test_resource: HashDealer.roll(:test_resource_with_roles).matcher})
12
13
  get((0..4).to_a.collect{HashDealer.roll(:test_resource)})
13
- get((0..4).to_a.collect{HashDealer.roll(:test_resource)}, :params => {:active => true})
14
- get((0..4).to_a.collect{HashDealer.roll(:test_resource)}, :params => {:all => true})
15
- get((0..4).to_a.collect{HashDealer.roll(:test_resource)}, :params => {:first => true})
16
- get((0..4).to_a.collect{HashDealer.roll(:test_resource)}, :params => {:last => true})
14
+ get((0..4).to_a.collect{HashDealer.roll(:test_resource)}, params: {active: true})
15
+ get((0..4).to_a.collect{HashDealer.roll(:test_resource)}, params: {all: true})
16
+ get((0..4).to_a.collect{HashDealer.roll(:test_resource)}, params: {first: true})
17
+ get((0..4).to_a.collect{HashDealer.roll(:test_resource)}, params: {last: true})
18
+
19
+ get(
20
+ (0..4).to_a.collect{HashDealer.roll(:test_resource)},
21
+ params: { page: 1, per_page: 10 }.matcher,
22
+ response_headers: {
23
+ "ApiResource-Total-Entries" => 100
24
+ }
25
+ )
26
+
17
27
  end
18
-
28
+
19
29
  endpoint("/test_resources/:id") do
20
30
  get(HashDealer.roll(:test_resource_with_proxies)) do |params|
21
31
  self.merge(params)
22
32
  end
23
33
  delete({})
24
- put({}, :params => {:test_resource => HashDealer.roll(:test_resource).matcher})
34
+ put({}, params: {test_resource: HashDealer.roll(:test_resource).matcher})
25
35
  end
26
-
36
+
27
37
  endpoint("/child_test_resources/new") do
28
38
  get({})
29
39
  end
30
-
40
+
31
41
  endpoint("/child_test_resource2s/new") do
32
42
  get({})
33
43
  end
34
-
44
+
35
45
  endpoint("/another_test_resources/new") do
36
46
  get({})
37
47
  end
38
-
48
+
39
49
  endpoint("/test_classes/new") do
40
50
  get({})
41
51
  end
42
-
52
+
43
53
  endpoint("/children/new") do
44
54
  get({})
45
55
  end
46
-
56
+
47
57
  end