smooth_operator 1.3.0 → 1.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +8 -8
  2. data/Gemfile +0 -5
  3. data/README.md +11 -308
  4. data/console.rb +3 -28
  5. data/lib/smooth_operator.rb +7 -75
  6. data/lib/smooth_operator/array_with_meta_data.rb +21 -20
  7. data/lib/smooth_operator/attribute_assignment.rb +53 -57
  8. data/lib/smooth_operator/delegation.rb +34 -15
  9. data/lib/smooth_operator/finder_methods.rb +17 -33
  10. data/lib/smooth_operator/helpers.rb +7 -37
  11. data/lib/smooth_operator/internal_attribute.rb +49 -0
  12. data/lib/smooth_operator/model_schema.rb +72 -0
  13. data/lib/smooth_operator/open_struct.rb +4 -7
  14. data/lib/smooth_operator/operator.rb +64 -102
  15. data/lib/smooth_operator/persistence.rb +64 -94
  16. data/lib/smooth_operator/remote_call.rb +70 -0
  17. data/lib/smooth_operator/serialization.rb +33 -89
  18. data/lib/smooth_operator/translation.rb +13 -26
  19. data/lib/smooth_operator/type_converter.rb +69 -0
  20. data/lib/smooth_operator/validations.rb +3 -25
  21. data/lib/smooth_operator/version.rb +1 -1
  22. data/smooth_operator.gemspec +5 -9
  23. data/spec/factories/user_factory.rb +4 -5
  24. data/spec/smooth_operator/attribute_assignment_spec.rb +11 -145
  25. data/spec/smooth_operator/delegation_spec.rb +54 -57
  26. data/spec/smooth_operator/finder_methods_spec.rb +2 -91
  27. data/spec/smooth_operator/{resource_name_spec.rb → model_schema_spec.rb} +2 -2
  28. data/spec/smooth_operator/operator_spec.rb +1 -1
  29. data/spec/smooth_operator/persistence_spec.rb +20 -140
  30. data/spec/smooth_operator/serialization_spec.rb +4 -28
  31. data/spec/spec_helper.rb +9 -7
  32. data/spec/support/models/address.rb +0 -9
  33. data/spec/support/models/post.rb +3 -9
  34. data/spec/support/models/user.rb +7 -30
  35. data/spec/support/models/user_with_address_and_posts.rb +12 -20
  36. data/spec/support/test_server.rb +7 -63
  37. metadata +18 -55
  38. data/lib/smooth_operator/associations.rb +0 -110
  39. data/lib/smooth_operator/associations/association_reflection.rb +0 -79
  40. data/lib/smooth_operator/associations/has_many_relation.rb +0 -45
  41. data/lib/smooth_operator/associations/reflection.rb +0 -41
  42. data/lib/smooth_operator/cookie_jar.rb +0 -21
  43. data/lib/smooth_operator/http_methods.rb +0 -17
  44. data/lib/smooth_operator/internal_data.rb +0 -45
  45. data/lib/smooth_operator/operators/connection_wrapper.rb +0 -15
  46. data/lib/smooth_operator/operators/faraday.rb +0 -75
  47. data/lib/smooth_operator/operators/typhoeus.rb +0 -87
  48. data/lib/smooth_operator/options.rb +0 -30
  49. data/lib/smooth_operator/remote_call/base.rb +0 -76
  50. data/lib/smooth_operator/remote_call/errors/connection_failed.rb +0 -20
  51. data/lib/smooth_operator/remote_call/errors/timeout.rb +0 -20
  52. data/lib/smooth_operator/remote_call/faraday.rb +0 -19
  53. data/lib/smooth_operator/remote_call/typhoeus.rb +0 -19
  54. data/lib/smooth_operator/resource_name.rb +0 -46
  55. data/lib/smooth_operator/schema.rb +0 -21
  56. data/lib/smooth_operator/type_casting.rb +0 -127
  57. data/spec/require_helper.rb +0 -11
  58. data/spec/smooth_operator/remote_call_spec.rb +0 -340
  59. data/spec/smooth_operator/validations_spec.rb +0 -42
  60. data/spec/support/models/comment.rb +0 -5
@@ -1,12 +1,12 @@
1
1
  require "spec_helper"
2
2
 
3
- describe SmoothOperator::ResourceName do
3
+ describe SmoothOperator::ModelSchema do
4
4
 
5
5
  describe "#known_attributes" do
6
6
  let(:initial_attributes_keys) { attributes_for(:user).keys.map(&:to_s) }
7
7
 
8
8
  context "when there is no declared schema" do
9
- subject { User::Base.new(attributes_for(:user)) }
9
+ subject { User.new(attributes_for(:user)) }
10
10
 
11
11
  it 'it should reflect the attributes used uppon initialization' do
12
12
  expect(subject.known_attributes.to_a).to match_array(initial_attributes_keys)
@@ -1,7 +1,7 @@
1
1
  require "spec_helper"
2
2
 
3
3
  describe SmoothOperator::Operator do
4
- subject { User::Base }
4
+ subject { User }
5
5
 
6
6
  describe "#get" do
7
7
 
@@ -9,7 +9,7 @@ shared_examples_for "successful persistent remote call" do
9
9
  it "it should populate 'last_remote_call' with the remote_call used on this transaction" do
10
10
  expect(subject.last_remote_call).to be_nil unless method_to_execute.to_s =~ /create/
11
11
  execute_method
12
- expect(subject.last_remote_call).to be_a_kind_of(SmoothOperator::RemoteCall::Base)
12
+ expect(subject.last_remote_call).to be_instance_of(SmoothOperator::RemoteCall::Base)
13
13
  end
14
14
  end
15
15
 
@@ -23,13 +23,7 @@ shared_examples_for "persistent remote call" do
23
23
  let(:method_arguments) { ['', { status: 200 }] }
24
24
 
25
25
  it "it should return true" do
26
- result = execute_method
27
-
28
- if !(method_to_execute.to_s =~ /create/)
29
- expect(result).to be true
30
- end
31
-
32
- expect(subject.last_remote_call.ok?).to be true
26
+ execute_method
33
27
  expect(subject.last_remote_call.status).to be true
34
28
  end
35
29
 
@@ -41,17 +35,11 @@ shared_examples_for "persistent remote call" do
41
35
  it_behaves_like "successful persistent remote call"
42
36
  end
43
37
 
44
- context "when the response is unprocessed_entity" do
38
+ context "when the response is negative" do
45
39
  let(:method_arguments) { ['', { status: 422 }] }
46
40
 
47
41
  it "it should return false" do
48
- result = execute_method
49
-
50
- if !(method_to_execute.to_s =~ /create/)
51
- expect(result).to be false
52
- end
53
-
54
- expect(subject.last_remote_call.not_processed?).to be true
42
+ execute_method
55
43
  expect(subject.last_remote_call.status).to be false
56
44
  end
57
45
 
@@ -63,39 +51,11 @@ shared_examples_for "persistent remote call" do
63
51
  it_behaves_like "successful persistent remote call"
64
52
  end
65
53
 
66
- context "when the response is client side error" do
67
- let(:method_arguments) { ['', { status: 404 }] }
68
-
69
- it "it should return nil" do
70
- result = execute_method
71
-
72
- if !(method_to_execute.to_s =~ /create/)
73
- expect(result).to be nil
74
- end
75
-
76
- expect(subject.last_remote_call.client_error?).to be true
77
- expect(subject.last_remote_call.error?).to be true
78
- expect(subject.last_remote_call.status).to be nil
79
- end
80
-
81
- it "it should assert the subject's persistence" do
82
- execute_method
83
- expect(subject.persisted?).to be(persistence_state[500])
84
- end
85
- end
86
-
87
54
  context "when the there is a connection error ou http 500" do
88
55
  let(:method_arguments) { ['', { status: 500 }] }
89
56
 
90
57
  it "it should return nil" do
91
- result = execute_method
92
-
93
- if !(method_to_execute.to_s =~ /create/)
94
- expect(result).to be nil
95
- end
96
-
97
- expect(subject.last_remote_call.server_error?).to be true
98
- expect(subject.last_remote_call.error?).to be true
58
+ execute_method
99
59
  expect(subject.last_remote_call.status).to be_nil
100
60
  end
101
61
 
@@ -107,7 +67,7 @@ shared_examples_for "persistent remote call" do
107
67
  it "it should populate 'last_remote_call' with the remote_call used on this transaction" do
108
68
  expect(subject.last_remote_call).to be_nil unless method_to_execute.to_s =~ /create/
109
69
  execute_method
110
- expect(subject.last_remote_call).to be_a_kind_of(SmoothOperator::RemoteCall::Base)
70
+ expect(subject.last_remote_call).to be_instance_of(SmoothOperator::RemoteCall::Base)
111
71
  end
112
72
 
113
73
  it "it should assert the subject's persistence" do
@@ -124,89 +84,15 @@ shared_examples_for "save method" do
124
84
  end
125
85
  end
126
86
 
127
- shared_examples_for "a method that calls the #make_the_call method" do
128
- let(:method_arguments) { ['/custom_path', { "user" => { "first_name" => "nhoJ" }, "extra_params" => 'extra_params' }, { option1: 'option1', option2: 'option2', http_verb: :get, serializable_options: { only: [:first_name] } }] }
129
-
130
- it "it should pass all arguments to #make_the_call" do
131
- _method_arguments = method_arguments.dup
132
- _method_arguments[0] = SmoothOperator::Helpers.remove_initial_slash(_method_arguments[0])
133
-
134
- expect(subject.class).to receive(:make_the_call).with(:get, *_method_arguments)
135
-
136
- execute_method
137
- end
138
-
139
- it "it should pass all arguments to .make_the_call" do
140
- _method_arguments = method_arguments.dup
141
- _method_arguments[0] = SmoothOperator::Helpers.remove_initial_slash(_method_arguments[0])
142
-
143
- expect(subject.class).to receive(:make_the_call).with(:get, *_method_arguments)
144
-
145
- execute_method
146
- end
147
- end
148
-
149
87
 
150
88
  describe SmoothOperator::Persistence, helpers: :persistence do
151
89
 
152
- describe "#reload" do
153
- subject { new_user }
154
- let(:method_to_execute) { :reload }
155
-
156
- context "when subject doesn't has an id" do
157
- it "it should raise 'UnknownPath'" do
158
- expect{ subject.reload }.to raise_error 'UnknownPath'
159
- end
160
- end
161
-
162
- context "when subject has an id" do
163
- before do
164
- subject.id = 1
165
- subject.reload
166
- end
167
-
168
- it "it should fetch server data" do
169
- expect(subject.attributes).to eq(attributes_for(:user_with_address_and_posts))
170
- end
171
- end
172
-
173
- context "when calling #reload on a nested object" do
174
-
175
- context "without the option 'ignore_parent: true'" do
176
- before do
177
- subject.id = 1
178
- subject.reload
179
- subject.posts.first.reload
180
- end
181
-
182
- it "it should fetch server data, with NESTED REST url" do
183
- expect(subject.posts.first.attributes).to eq({ id: 1, body: 'from_nested_url' })
184
- end
185
- end
186
-
187
- context "with the option 'ignore_parent: true'" do
188
- before do
189
- subject.id = 1
190
- subject.reload
191
- subject.posts.first.reload(nil, nil, { ignore_parent: true })
192
- end
193
-
194
- it "it should fetch server data, with REST url" do
195
- expect(subject.posts.first.attributes).to eq({ id: 1, body: 'from_resource_url' })
196
- end
197
- end
198
-
199
- end
200
-
201
- it_behaves_like "a method that calls the #make_the_call method"
202
- end
203
-
204
90
  describe ".create" do
205
-
206
- subject { created_subject }
91
+
207
92
  let(:method_arguments) { [] }
208
93
 
209
94
  context "when attributes DON'T contain an ID" do
95
+ subject { created_subject }
210
96
  let(:method_to_execute) { :create_without_id }
211
97
  let(:persistence_state) { { 200 => true, 422 => false, 500 => false } }
212
98
 
@@ -221,6 +107,7 @@ describe SmoothOperator::Persistence, helpers: :persistence do
221
107
  end
222
108
 
223
109
  context "when attributes contain an ID" do
110
+ subject { created_subject }
224
111
  let(:method_to_execute) { :create_with_id }
225
112
  let(:persistence_state) { { 200 => true, 422 => true, 500 => true } }
226
113
 
@@ -271,7 +158,7 @@ describe SmoothOperator::Persistence, helpers: :persistence do
271
158
  expect(subject.destroyed?).to be(true)
272
159
  end
273
160
  end
274
-
161
+
275
162
  context "after a failed execution of #destroy" do
276
163
  subject { existing_user }
277
164
  before { subject.destroy('', { status: 422 }) }
@@ -331,16 +218,14 @@ describe SmoothOperator::Persistence, helpers: :persistence do
331
218
  subject { new_user }
332
219
  let(:persistence_state) { { 200 => true, 422 => false, 500 => false } }
333
220
 
221
+ it_behaves_like "persistent remote call"
222
+
334
223
  it "it should make a post http call" do
335
224
  execute_method
336
225
  expect(subject.last_remote_call.parsed_response['http_verb']).to eq('post')
337
226
  end
338
227
 
339
228
  it_behaves_like "save method"
340
-
341
- it_behaves_like "persistent remote call"
342
-
343
- it_behaves_like "a method that calls the #make_the_call method"
344
229
  end
345
230
 
346
231
  context "when an instance IS persisted" do
@@ -348,34 +233,31 @@ describe SmoothOperator::Persistence, helpers: :persistence do
348
233
  subject { existing_user }
349
234
  let(:persistence_state) { { 200 => true, 422 => true, 500 => true } }
350
235
 
236
+ it_behaves_like "persistent remote call"
237
+
351
238
  it "it should make a put http call" do
352
239
  execute_method
353
240
  expect(subject.last_remote_call.parsed_response['http_verb']).to eq('put')
354
241
  end
355
242
 
356
243
  it_behaves_like "save method"
357
-
358
- it_behaves_like "persistent remote call"
359
-
360
- it_behaves_like "a method that calls the #make_the_call method"
361
244
  end
362
245
 
363
246
  context "and it uses 'patch' http verb to save" do
364
247
  subject { existing_user_with_patch }
365
248
  let(:persistence_state) { { 200 => true, 422 => true, 500 => true } }
366
249
 
250
+ it_behaves_like "persistent remote call"
251
+
367
252
  it "it should make a patch http call" do
368
253
  execute_method
369
254
  expect(subject.last_remote_call.parsed_response['http_verb']).to eq('patch')
370
255
  end
371
256
 
372
257
  it_behaves_like "save method"
373
-
374
- it_behaves_like "persistent remote call"
375
-
376
- it_behaves_like "a method that calls the #make_the_call method"
377
258
  end
378
259
  end
260
+
379
261
  end
380
262
 
381
263
  describe "#save!" do
@@ -395,7 +277,7 @@ describe SmoothOperator::Persistence, helpers: :persistence do
395
277
  end
396
278
 
397
279
  describe "#destroy" do
398
-
280
+
399
281
  let(:method_to_execute) { :destroy }
400
282
  let(:method_arguments) { [] }
401
283
 
@@ -417,14 +299,12 @@ describe SmoothOperator::Persistence, helpers: :persistence do
417
299
  subject { existing_user }
418
300
  let(:persistence_state) { { 200 => false, 422 => true, 500 => true } }
419
301
 
302
+ it_behaves_like "persistent remote call"
303
+
420
304
  it "it should make a delete http call" do
421
305
  execute_method
422
306
  expect(subject.last_remote_call.parsed_response['http_verb']).to eq('delete')
423
307
  end
424
-
425
- it_behaves_like "persistent remote call"
426
-
427
- it_behaves_like "a method that calls the #make_the_call method"
428
308
  end
429
309
 
430
310
  end
@@ -20,33 +20,9 @@ describe SmoothOperator::Serialization do
20
20
  describe "#to_hash" do
21
21
  subject { UserWithAddressAndPosts::Son.new(attributes_for(:user_with_address_and_posts)) }
22
22
 
23
- it 'it should call #serializable_hash with the same arguments' do
24
- options = { option1: 'option1', option2: 'option2' }
25
-
26
- expect(subject).to receive(:serializable_hash).with(options)
27
-
28
- subject.to_hash(options)
29
- end
30
- end
31
-
32
- describe "#to_json" do
33
- subject { UserWithAddressAndPosts::Son.new(attributes_for(:user_with_address_and_posts)) }
34
-
35
- it 'it should call #serializable_hash with the same arguments' do
36
- options = { option1: 'option1', option2: 'option2' }
37
-
38
- expect(subject).to receive(:serializable_hash).with(options)
39
-
40
- subject.to_json(options)
41
- end
42
- end
43
-
44
- describe "#serializable_hash" do
45
- subject { UserWithAddressAndPosts::Son.new(attributes_for(:user_with_address_and_posts)) }
46
-
47
23
  context "when no options are given" do
48
24
  it 'it should return all attributes' do
49
- expect(subject.serializable_hash).to eq(SmoothOperator::Helpers.stringify_keys(attributes_for(:user_with_address_and_posts)))
25
+ expect(subject.to_hash).to eq(attributes_for(:user_with_address_and_posts))
50
26
  end
51
27
  end
52
28
 
@@ -54,7 +30,7 @@ describe SmoothOperator::Serialization do
54
30
  let(:options_with_only) { { only: [:id, :first_name] } }
55
31
 
56
32
  it 'it should only return the filtered options' do
57
- expect(subject.serializable_hash(options_with_only)).to eq(SmoothOperator::Helpers.stringify_keys(attributes_for(:white_list)))
33
+ expect(subject.to_hash(options_with_only)).to eq(attributes_for(:white_list))
58
34
  end
59
35
  end
60
36
 
@@ -62,7 +38,7 @@ describe SmoothOperator::Serialization do
62
38
  let(:options_with_except) { { except: [:last_name, :admin] } }
63
39
 
64
40
  it 'it should return all fields except for the filtered options' do
65
- expect(subject.serializable_hash(options_with_except)).not_to include(attributes_for(:black_list))
41
+ expect(subject.to_hash(options_with_except)).not_to include(attributes_for(:black_list))
66
42
  end
67
43
  end
68
44
 
@@ -71,7 +47,7 @@ describe SmoothOperator::Serialization do
71
47
  subject(:user_with_my_method) { UserWithAddressAndPosts::UserWithMyMethod.new(attributes_for(:user_with_address_and_posts)) }
72
48
 
73
49
  it 'it should return all fields including the expected method and its returning value' do
74
- expect(user_with_my_method.serializable_hash(options_with_method)).to eq(SmoothOperator::Helpers.stringify_keys(attributes_for(:user_with_my_method)))
50
+ expect(user_with_my_method.to_hash(options_with_method)).to eq(attributes_for(:user_with_my_method))
75
51
  end
76
52
  end
77
53
 
data/spec/spec_helper.rb CHANGED
@@ -1,12 +1,14 @@
1
- require 'simplecov'
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
2
3
 
3
- SimpleCov.start do
4
- root('lib/')
5
- project_name('SmoothOperator')
6
- coverage_dir('../tmp/coverage/')
7
- end
4
+ require 'bundler'
5
+ require 'smooth_operator'
6
+
7
+ Bundler.require :test, :default
8
8
 
9
- require 'require_helper'
9
+ Dir.chdir("spec/") do
10
+ Dir["support/**/*.rb"].each { |file| require file }
11
+ end
10
12
 
11
13
  FactoryGirl.find_definitions
12
14
 
@@ -1,12 +1,3 @@
1
1
  class Address < SmoothOperator::Base
2
2
 
3
- options resource_name: '',
4
- endpoint_user: 'admin',
5
- endpoint_pass: 'admin',
6
- endpoint: 'http://localhost:4567/',
7
- headers: {
8
- "X-APPTOKEN" => "app_token",
9
- "X-LAYERTOKEN" => "layer_token"
10
- }
11
-
12
3
  end
@@ -1,13 +1,7 @@
1
1
  class Post < SmoothOperator::Base
2
2
 
3
- options endpoint_user: 'admin',
4
- endpoint_pass: 'admin',
5
- rails_serialization: true,
6
- endpoint: 'http://localhost:4567/',
7
- unknown_hash_class: SmoothOperator::OpenStruct
8
-
9
- has_many :comments#, rails_serialization: true
10
-
11
- belongs_to :address#, rails_serialization: true
3
+ self.turn_unknown_hash_to_open_struct = false
4
+
5
+ self.endpoint = 'http://localhost:3000/api/v0'
12
6
 
13
7
  end
@@ -1,38 +1,15 @@
1
- module User
1
+ class User < SmoothOperator::Base
2
2
 
3
- class Base < SmoothOperator::Base
3
+ self.endpoint_user = 'admin'
4
4
 
5
- options resource_name: 'user',
6
- endpoint_user: 'admin',
7
- endpoint_pass: 'admin',
8
- endpoint: 'http://localhost:4567/'
5
+ self.endpoint_pass = 'admin'
9
6
 
10
- def self.query_string(params)
11
- params['query_string_param'] = true
7
+ self.endpoint = 'http://localhost:4567/'
12
8
 
13
- params
14
- end
9
+ def self.query_string(params)
10
+ params['query_string_param'] = true
15
11
 
16
- end
17
-
18
- module UnknownHashClass
19
-
20
- class OpenStructBase < User::Base
21
- options unknown_hash_class: SmoothOperator::OpenStruct
22
- end
23
-
24
- class None < User::Base
25
- options unknown_hash_class: nil
26
- end
27
-
28
- end
29
-
30
- class BrokenConnection < SmoothOperator::Base
31
- options endpoint: 'http://localhost:1234/'
32
- end
33
-
34
- class TimeoutConnection < Base
35
- options timeout: 1
12
+ params
36
13
  end
37
14
 
38
15
  end