api_resource 0.6.21 → 0.6.22

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