ddy_remote_resource 0.4.2

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 (44) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +22 -0
  3. data/.rspec +2 -0
  4. data/.ruby-gemset +1 -0
  5. data/.ruby-version +1 -0
  6. data/.travis.yml +3 -0
  7. data/Gemfile +4 -0
  8. data/LICENSE.txt +22 -0
  9. data/README.md +182 -0
  10. data/Rakefile +7 -0
  11. data/lib/extensions/ethon/easy/queryable.rb +36 -0
  12. data/lib/remote_resource.rb +64 -0
  13. data/lib/remote_resource/base.rb +126 -0
  14. data/lib/remote_resource/builder.rb +53 -0
  15. data/lib/remote_resource/collection.rb +31 -0
  16. data/lib/remote_resource/connection.rb +24 -0
  17. data/lib/remote_resource/connection_options.rb +41 -0
  18. data/lib/remote_resource/http_errors.rb +33 -0
  19. data/lib/remote_resource/querying/finder_methods.rb +34 -0
  20. data/lib/remote_resource/querying/persistence_methods.rb +38 -0
  21. data/lib/remote_resource/request.rb +106 -0
  22. data/lib/remote_resource/response.rb +69 -0
  23. data/lib/remote_resource/response_handeling.rb +48 -0
  24. data/lib/remote_resource/rest.rb +29 -0
  25. data/lib/remote_resource/url_naming.rb +34 -0
  26. data/lib/remote_resource/url_naming_determination.rb +39 -0
  27. data/lib/remote_resource/version.rb +3 -0
  28. data/remote_resource.gemspec +32 -0
  29. data/spec/lib/extensions/ethon/easy/queryable_spec.rb +135 -0
  30. data/spec/lib/remote_resource/base_spec.rb +388 -0
  31. data/spec/lib/remote_resource/builder_spec.rb +245 -0
  32. data/spec/lib/remote_resource/collection_spec.rb +148 -0
  33. data/spec/lib/remote_resource/connection_options_spec.rb +124 -0
  34. data/spec/lib/remote_resource/connection_spec.rb +61 -0
  35. data/spec/lib/remote_resource/querying/finder_methods_spec.rb +105 -0
  36. data/spec/lib/remote_resource/querying/persistence_methods_spec.rb +174 -0
  37. data/spec/lib/remote_resource/request_spec.rb +594 -0
  38. data/spec/lib/remote_resource/response_spec.rb +196 -0
  39. data/spec/lib/remote_resource/rest_spec.rb +98 -0
  40. data/spec/lib/remote_resource/url_naming_determination_spec.rb +225 -0
  41. data/spec/lib/remote_resource/url_naming_spec.rb +72 -0
  42. data/spec/lib/remote_resource/version_spec.rb +8 -0
  43. data/spec/spec_helper.rb +4 -0
  44. metadata +242 -0
@@ -0,0 +1,245 @@
1
+ require 'spec_helper'
2
+
3
+ describe RemoteResource::Builder do
4
+
5
+ module RemoteResource
6
+ class BuilderDummy
7
+ include RemoteResource::Base
8
+
9
+ self.site = 'https://foobar.com'
10
+
11
+ attr_accessor :username
12
+
13
+ end
14
+ end
15
+
16
+ let(:dummy_class) { RemoteResource::BuilderDummy }
17
+ let(:dummy) { dummy_class.new }
18
+
19
+ describe '.build_resource_from_response' do
20
+ let(:response) { RemoteResource::Response.new double.as_null_object }
21
+ let(:sanitized_response_body) do
22
+ { "id" => "12", "username" => "foobar" }
23
+ end
24
+
25
+ before { allow(response).to receive(:sanitized_response_body) { sanitized_response_body } }
26
+
27
+ it 'calls the .build_resource' do
28
+ expect(dummy_class).to receive(:build_resource).with sanitized_response_body, { _response: an_instance_of(RemoteResource::Response) }
29
+ dummy_class.build_resource_from_response response
30
+ end
31
+ end
32
+
33
+ describe '.build_resource' do
34
+ let(:response) { RemoteResource::Response.new double.as_null_object }
35
+ let(:response_hash) { dummy_class.send :response_hash, response }
36
+
37
+ context 'when collection is a Hash' do
38
+ let(:collection) do
39
+ { "id" => "12", "username" => "foobar" }
40
+ end
41
+
42
+ context 'and response_hash is given' do
43
+ it 'instantiates the resource with the collection AND response_hash' do
44
+ expect(dummy_class).to receive(:new).with(collection.merge(response_hash)).and_call_original
45
+ dummy_class.build_resource collection, response_hash
46
+ end
47
+
48
+ it 'returns the resource' do
49
+ expect(dummy_class.build_resource collection, response_hash).to be_a dummy_class
50
+ end
51
+ end
52
+
53
+ context 'and NO response_hash is given' do
54
+ it 'instantiates the resource with the collection' do
55
+ expect(dummy_class).to receive(:new).with(collection).and_call_original
56
+ dummy_class.build_resource collection
57
+ end
58
+
59
+ it 'returns the resource' do
60
+ expect(dummy_class.build_resource collection).to be_a dummy_class
61
+ end
62
+ end
63
+ end
64
+
65
+ context 'when collection is NOT a Hash' do
66
+ let(:collection) { [] }
67
+
68
+ it 'returns nil' do
69
+ expect(dummy_class.build_resource collection, response_hash).to be_nil
70
+ end
71
+ end
72
+ end
73
+
74
+ describe '.build_collection_from_response' do
75
+ let(:response) { RemoteResource::Response.new double.as_null_object }
76
+ let(:sanitized_response_body) do
77
+ [
78
+ { "id" => "10", "username" => "foobar" },
79
+ { "id" => "11", "username" => "bazbar" },
80
+ { "id" => "12", "username" => "aapmies" }
81
+ ]
82
+ end
83
+
84
+ before { allow(response).to receive(:sanitized_response_body) { sanitized_response_body } }
85
+
86
+ it 'calls the .build_collection' do
87
+ expect(dummy_class).to receive(:build_collection).with sanitized_response_body, { _response: an_instance_of(RemoteResource::Response) }
88
+ dummy_class.build_collection_from_response response
89
+ end
90
+ end
91
+
92
+ describe '.build_collection' do
93
+ let(:response) { RemoteResource::Response.new double.as_null_object }
94
+ let(:response_hash) { dummy_class.send :response_hash, response }
95
+
96
+ context 'when collection is an Array' do
97
+ let(:collection) do
98
+ [
99
+ { "id" => "10", "username" => "foobar" },
100
+ { "id" => "11", "username" => "bazbar" },
101
+ { "id" => "12", "username" => "aapmies" }
102
+ ]
103
+ end
104
+
105
+ context 'and response_hash is given' do
106
+ it 'instantiates a RemoteResource::Collection with the class, collection AND response_hash' do
107
+ expect(RemoteResource::Collection).to receive(:new).with(dummy_class, collection, response_hash).and_call_original
108
+ dummy_class.build_collection collection, response_hash
109
+ end
110
+
111
+ it 'returns the resources' do
112
+ resources = dummy_class.build_collection collection, response_hash
113
+ resources.each { |resource| expect(resource).to be_a dummy_class }
114
+ end
115
+ end
116
+
117
+ context 'and NO response_hash is given' do
118
+ it 'instantiates a RemoteResource::Collection with the class and collection' do
119
+ expect(RemoteResource::Collection).to receive(:new).with(dummy_class, collection, {}).and_call_original
120
+ dummy_class.build_collection collection
121
+ end
122
+
123
+ it 'returns the resources' do
124
+ resources = dummy_class.build_collection collection
125
+ resources.each { |resource| expect(resource).to be_a dummy_class }
126
+ end
127
+ end
128
+ end
129
+
130
+ context 'when collection is NOT an Array' do
131
+ let(:collection) { {} }
132
+
133
+ it 'returns nil' do
134
+ expect(dummy_class.build_collection collection, response_hash).to be_nil
135
+ end
136
+ end
137
+ end
138
+
139
+ describe '#rebuild_resource_from_response' do
140
+ let(:response) { RemoteResource::Response.new double.as_null_object }
141
+ let(:sanitized_response_body) do
142
+ { "id" => "12", "username" => "foobar" }
143
+ end
144
+
145
+ before { allow(response).to receive(:sanitized_response_body) { sanitized_response_body } }
146
+
147
+ it 'calls the #rebuild_resource' do
148
+ expect(dummy).to receive(:rebuild_resource).with sanitized_response_body, { _response: an_instance_of(RemoteResource::Response) }
149
+ dummy.rebuild_resource_from_response response
150
+ end
151
+ end
152
+
153
+ describe '#rebuild_resource' do
154
+ let(:response) { RemoteResource::Response.new double.as_null_object }
155
+ let(:response_hash) { dummy.send :response_hash, response }
156
+
157
+ before do
158
+ dummy.id = nil
159
+ dummy.username = "foo"
160
+ end
161
+
162
+ context 'when the collection is a Hash' do
163
+ let(:collection) do
164
+ { "id" => "12", "username" => "foobar" }
165
+ end
166
+
167
+ context 'and response_hash is given' do
168
+ it 'mass-assigns the attributes of the resource with the collection AND with response_hash' do
169
+ expect(dummy.id).to be_nil
170
+ expect(dummy.username).to eql 'foo'
171
+ expect(dummy._response).to be_nil
172
+
173
+ dummy.rebuild_resource collection, response_hash
174
+
175
+ expect(dummy.id).to eql '12'
176
+ expect(dummy.username).to eql 'foobar'
177
+ expect(dummy._response).to be_a RemoteResource::Response
178
+ end
179
+
180
+ it 'returns the resource' do
181
+ expect(dummy.rebuild_resource collection, response_hash).to be_a dummy_class
182
+ end
183
+ end
184
+
185
+ context 'and NO response_hash is given' do
186
+ it 'mass-assigns the attributes of the resource with the collection' do
187
+ expect(dummy.id).to be_nil
188
+ expect(dummy.username).to eql 'foo'
189
+ expect(dummy._response).to be_nil
190
+
191
+ dummy.rebuild_resource collection
192
+
193
+ expect(dummy.id).to eql '12'
194
+ expect(dummy.username).to eql 'foobar'
195
+ expect(dummy._response).to be_nil
196
+ end
197
+
198
+ it 'returns the resource' do
199
+ expect(dummy.rebuild_resource collection).to be_a dummy_class
200
+ end
201
+ end
202
+ end
203
+
204
+ context 'when the collection is something else' do
205
+ let(:collection) { 'foobar' }
206
+
207
+ context 'and response_hash is given' do
208
+ it 'assigns the response_hash of the resource' do
209
+ expect(dummy.id).to be_nil
210
+ expect(dummy.username).to eql 'foo'
211
+ expect(dummy._response).to be_nil
212
+
213
+ dummy.rebuild_resource collection, response_hash
214
+
215
+ expect(dummy.id).to be_nil
216
+ expect(dummy.username).to eql 'foo'
217
+ expect(dummy._response).to be_a RemoteResource::Response
218
+ end
219
+
220
+ it 'returns the resource' do
221
+ expect(dummy.rebuild_resource collection, response_hash).to be_a dummy_class
222
+ end
223
+ end
224
+
225
+ context 'and NO response_hash is given' do
226
+ it 'does NOT assign the response_hash of the resource' do
227
+ expect(dummy.id).to be_nil
228
+ expect(dummy.username).to eql 'foo'
229
+ expect(dummy._response).to be_nil
230
+
231
+ dummy.rebuild_resource collection
232
+
233
+ expect(dummy.id).to be_nil
234
+ expect(dummy.username).to eql 'foo'
235
+ expect(dummy._response).to be_nil
236
+ end
237
+
238
+ it 'returns the resource' do
239
+ expect(dummy.rebuild_resource collection).to be_a dummy_class
240
+ end
241
+ end
242
+ end
243
+ end
244
+
245
+ end
@@ -0,0 +1,148 @@
1
+ require 'spec_helper'
2
+
3
+ describe RemoteResource::Collection do
4
+
5
+ module RemoteResource
6
+ class CollectionDummy
7
+ include RemoteResource::Base
8
+
9
+ self.site = 'https://foobar.com'
10
+
11
+ attr_accessor :username
12
+ end
13
+ end
14
+
15
+ let(:dummy_class) { RemoteResource::CollectionDummy }
16
+ let(:dummy) { dummy_class.new }
17
+
18
+ let(:response) { RemoteResource::Response.new double.as_null_object }
19
+ let(:response_hash) do
20
+ { _response: response }
21
+ end
22
+
23
+ let(:resources_collection) do
24
+ [
25
+ { id: 1, username: 'mies_1' },
26
+ { id: 2, username: 'mies_2' }
27
+ ]
28
+ end
29
+
30
+ let(:collection) { described_class.new dummy_class, resources_collection, response_hash }
31
+
32
+ specify { expect(described_class).to include Enumerable }
33
+
34
+ describe '#[]' do
35
+ let(:to_a) { collection.dup.to_a }
36
+
37
+ it 'delegates to the #to_a' do
38
+ expect(collection[0].id).to eql to_a[0].id
39
+ end
40
+ end
41
+
42
+ describe '#at' do
43
+ let(:to_a) { collection.dup.to_a }
44
+
45
+ it 'delegates to the #to_a' do
46
+ expect(collection.at(0).id).to eql to_a.at(0).id
47
+ end
48
+ end
49
+
50
+ describe '#reverse' do
51
+ let(:to_a) { collection.dup.to_a }
52
+
53
+ it 'delegates to the #to_a' do
54
+ expect(collection.reverse[0].id).to eql to_a.reverse[0].id
55
+ end
56
+ end
57
+
58
+ describe '#size' do
59
+ let(:to_a) { collection.dup.to_a }
60
+
61
+ it 'delegates to the #to_a' do
62
+ expect(collection.size).to eql to_a.size
63
+ end
64
+ end
65
+
66
+ describe '#each' do
67
+ context 'when the resources_collection is an Array' do
68
+ it 'instantiates each element in the resources_collection as resource' do
69
+ expect(dummy_class).to receive(:new).with(resources_collection[0].merge(response_hash)).and_call_original
70
+ expect(dummy_class).to receive(:new).with(resources_collection[1].merge(response_hash)).and_call_original
71
+ collection.all?
72
+ end
73
+
74
+ it 'returns an Enumerable' do
75
+ expect(collection).to be_an Enumerable
76
+ end
77
+
78
+ context 'Enumerable' do
79
+ it 'includes the resources' do
80
+ expect(collection[0]).to be_a RemoteResource::CollectionDummy
81
+ expect(collection[1]).to be_a RemoteResource::CollectionDummy
82
+ end
83
+
84
+ it 'includes the instantiated resources' do
85
+ expect(collection[0].username).to eql 'mies_1'
86
+ expect(collection[1].username).to eql 'mies_2'
87
+ end
88
+
89
+ it 'includes the responses in the instantiated resources' do
90
+ expect(collection[0]._response).to eql response
91
+ expect(collection[1]._response).to eql response
92
+ end
93
+ end
94
+ end
95
+
96
+ context 'when the resources_collection is NOT an Array' do
97
+ let(:resources_collection) { {} }
98
+
99
+ it 'returns nil' do
100
+ expect(collection.each).to be_nil
101
+ end
102
+ end
103
+ end
104
+
105
+ describe '#empty?' do
106
+ context 'when the resources_collection is nil' do
107
+ let(:resources_collection) { nil }
108
+
109
+ it 'returns true' do
110
+ expect(collection.empty?).to eql true
111
+ end
112
+ end
113
+
114
+ context 'when the resources_collection is blank' do
115
+ let(:resources_collection) { '' }
116
+
117
+ it 'returns true' do
118
+ expect(collection.empty?).to eql true
119
+ end
120
+ end
121
+
122
+ context 'when the resources_collection is NOT nil or blank' do
123
+ it 'returns false' do
124
+ expect(collection.empty?).to eql false
125
+ end
126
+ end
127
+ end
128
+
129
+ describe '#success?' do
130
+ context 'when response is successful' do
131
+ before { allow(response).to receive(:success?) { true } }
132
+
133
+ it 'returns true' do
134
+ expect(collection.success?).to eql true
135
+ end
136
+ end
137
+
138
+ context 'when response is NOT successful' do
139
+ before { allow(response).to receive(:success?) { false } }
140
+
141
+ it 'returns false' do
142
+ expect(collection.success?).to eql false
143
+ end
144
+ end
145
+ end
146
+
147
+
148
+ end
@@ -0,0 +1,124 @@
1
+ require 'spec_helper'
2
+
3
+ describe RemoteResource::ConnectionOptions do
4
+
5
+ module RemoteResource
6
+ class ConnectionOptionsDummy
7
+ include RemoteResource::Base
8
+
9
+ self.site = 'https://foobar.com'
10
+ self.content_type = ''
11
+ self.extra_headers = { "X-Locale" => "nl" }
12
+ self.version = '/v1'
13
+ self.path_prefix = '/prefix'
14
+ self.path_postfix = '/postfix'
15
+ self.content_type = '.json'
16
+ self.collection = true
17
+ self.root_element = :test_dummy
18
+
19
+ end
20
+ end
21
+
22
+ let(:dummy_class) { RemoteResource::ConnectionOptionsDummy }
23
+ let(:dummy) { dummy_class.new }
24
+
25
+ let(:connection_options) { described_class.new dummy_class }
26
+
27
+ describe '#initialize' do
28
+ it 'assigns the given class as #base_class' do
29
+ allow_any_instance_of(described_class).to receive(:initialize_connection_options)
30
+
31
+ expect(connection_options.base_class).to eql RemoteResource::ConnectionOptionsDummy
32
+ end
33
+
34
+ context 'RemoteResource::Base::OPTIONS' do
35
+ it 'calls #initialize_connection_options' do
36
+ expect_any_instance_of(described_class).to receive(:initialize_connection_options)
37
+ connection_options
38
+ end
39
+
40
+ it 'sets the accessor of the option from the RemoteResource::Base::OPTIONS' do
41
+ RemoteResource::Base::OPTIONS.each do |option|
42
+ expect(connection_options).to respond_to "#{option}"
43
+ expect(connection_options).to respond_to "#{option}="
44
+ end
45
+ end
46
+
47
+ it 'assigns the value of the option from the RemoteResource::Base::OPTIONS' do
48
+ RemoteResource::Base::OPTIONS.each do |option|
49
+ expect(connection_options.public_send(option)).to eql dummy_class.public_send(option)
50
+ end
51
+ end
52
+ end
53
+ end
54
+
55
+ describe '#merge' do
56
+ let(:custom_connection_options) do
57
+ {
58
+ site: 'https://dummy.foobar.com',
59
+ content_type: '.xml',
60
+ root_element: :test_dummy_api
61
+ }
62
+ end
63
+
64
+ it 'merges the custom connection_options in the connection_options' do
65
+ connection_options.merge custom_connection_options
66
+
67
+ expect(connection_options.site).to eql 'https://dummy.foobar.com'
68
+ expect(connection_options.content_type).to eql '.xml'
69
+ expect(connection_options.root_element).to eql :test_dummy_api
70
+ end
71
+
72
+ it 'returns self' do
73
+ expect(connection_options.merge custom_connection_options).to eql connection_options
74
+ end
75
+ end
76
+
77
+ describe '#to_hash' do
78
+ let(:connection_options_hash) do
79
+ {
80
+ base_url: 'https://foobar.com/v1/prefix/connection_options_dummies/postfix',
81
+ site: 'https://foobar.com',
82
+ headers: { "Accept" => "application/json", "X-Locale" => "nl" },
83
+ version: '/v1',
84
+ path_prefix: '/prefix',
85
+ path_postfix: '/postfix',
86
+ content_type: '.json',
87
+ collection: true,
88
+ collection_name: nil,
89
+ root_element: :test_dummy
90
+ }
91
+ end
92
+
93
+ it 'returns the connection_options as Hash' do
94
+ expect(connection_options.to_hash).to eql connection_options_hash
95
+ end
96
+ end
97
+
98
+ describe '#reload' do
99
+ it 'does NOT return self' do
100
+ expect(connection_options.reload).not_to eql connection_options
101
+ end
102
+
103
+ context 'RemoteResource::Base::OPTIONS' do
104
+ it 'calls #initialize_connection_options' do
105
+ expect_any_instance_of(described_class).to receive(:initialize_connection_options).twice
106
+ connection_options.reload
107
+ end
108
+ end
109
+ end
110
+
111
+ describe '#reload!' do
112
+ it 'returns self' do
113
+ expect(connection_options.reload!).to eql connection_options
114
+ end
115
+
116
+ context 'RemoteResource::Base::OPTIONS' do
117
+ it 'calls #initialize_connection_options' do
118
+ expect_any_instance_of(described_class).to receive(:initialize_connection_options).twice
119
+ connection_options.reload!
120
+ end
121
+ end
122
+ end
123
+
124
+ end