smooth_operator 0.4.4 → 1.2.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.
- checksums.yaml +9 -9
- data/.gitignore +2 -1
- data/.rspec +4 -0
- data/Gemfile +13 -0
- data/README.md +258 -10
- data/console.rb +44 -0
- data/lib/smooth_operator/array_with_meta_data.rb +31 -0
- data/lib/smooth_operator/attribute_assignment.rb +102 -0
- data/lib/smooth_operator/attribute_methods.rb +87 -0
- data/lib/smooth_operator/attributes/base.rb +107 -0
- data/lib/smooth_operator/attributes/dirty.rb +29 -0
- data/lib/smooth_operator/attributes/normal.rb +15 -0
- data/lib/smooth_operator/delegation.rb +60 -0
- data/lib/smooth_operator/finder_methods.rb +43 -0
- data/lib/smooth_operator/helpers.rb +79 -0
- data/lib/smooth_operator/model_schema.rb +81 -0
- data/lib/smooth_operator/open_struct.rb +37 -0
- data/lib/smooth_operator/operator.rb +145 -0
- data/lib/smooth_operator/operators/faraday.rb +75 -0
- data/lib/smooth_operator/operators/typhoeus.rb +77 -0
- data/lib/smooth_operator/persistence.rb +144 -0
- data/lib/smooth_operator/relation/array_relation.rb +13 -0
- data/lib/smooth_operator/relation/association_reflection.rb +75 -0
- data/lib/smooth_operator/relation/associations.rb +75 -0
- data/lib/smooth_operator/relation/reflection.rb +41 -0
- data/lib/smooth_operator/relation/single_relation.rb +14 -0
- data/lib/smooth_operator/remote_call/base.rb +80 -0
- data/lib/smooth_operator/remote_call/errors/connection_failed.rb +20 -0
- data/lib/smooth_operator/remote_call/errors/timeout.rb +20 -0
- data/lib/smooth_operator/remote_call/faraday.rb +19 -0
- data/lib/smooth_operator/remote_call/typhoeus.rb +19 -0
- data/lib/smooth_operator/serialization.rb +79 -0
- data/lib/smooth_operator/translation.rb +27 -0
- data/lib/smooth_operator/validations.rb +15 -0
- data/lib/smooth_operator/version.rb +1 -1
- data/lib/smooth_operator.rb +26 -5
- data/smooth_operator.gemspec +12 -3
- data/spec/factories/user_factory.rb +34 -0
- data/spec/require_helper.rb +11 -0
- data/spec/smooth_operator/attribute_assignment_spec.rb +351 -0
- data/spec/smooth_operator/attributes_dirty_spec.rb +53 -0
- data/spec/smooth_operator/delegation_spec.rb +139 -0
- data/spec/smooth_operator/finder_methods_spec.rb +105 -0
- data/spec/smooth_operator/model_schema_spec.rb +31 -0
- data/spec/smooth_operator/operator_spec.rb +46 -0
- data/spec/smooth_operator/persistence_spec.rb +424 -0
- data/spec/smooth_operator/remote_call_spec.rb +320 -0
- data/spec/smooth_operator/serialization_spec.rb +80 -0
- data/spec/smooth_operator/validations_spec.rb +42 -0
- data/spec/spec_helper.rb +25 -0
- data/spec/support/helpers/persistence_helper.rb +38 -0
- data/spec/support/localhost_server.rb +97 -0
- data/spec/support/models/address.rb +14 -0
- data/spec/support/models/comment.rb +3 -0
- data/spec/support/models/post.rb +13 -0
- data/spec/support/models/user.rb +41 -0
- data/spec/support/models/user_with_address_and_posts.rb +89 -0
- data/spec/support/test_server.rb +165 -0
- metadata +108 -18
- data/lib/smooth_operator/base.rb +0 -30
- data/lib/smooth_operator/core.rb +0 -218
- data/lib/smooth_operator/http_handlers/typhoeus/base.rb +0 -58
- data/lib/smooth_operator/http_handlers/typhoeus/orm.rb +0 -34
- data/lib/smooth_operator/http_handlers/typhoeus/remote_call.rb +0 -28
- data/lib/smooth_operator/operator/base.rb +0 -43
- data/lib/smooth_operator/operator/exceptions.rb +0 -64
- data/lib/smooth_operator/operator/orm.rb +0 -118
- data/lib/smooth_operator/operator/remote_call.rb +0 -84
@@ -0,0 +1,139 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe SmoothOperator::Delegation do
|
4
|
+
|
5
|
+
describe "#respond_to?" do
|
6
|
+
let(:initial_attributes_keys) { attributes_for(:user_with_address_and_posts).keys }
|
7
|
+
|
8
|
+
context "when there is no declared schema" do
|
9
|
+
subject { UserWithAddressAndPosts::UserWithMyMethod.new(attributes_for(:user_with_address_and_posts)) }
|
10
|
+
|
11
|
+
it 'it should return true for every attribute used uppon initialization' do
|
12
|
+
initial_attributes_keys.each do |attribute|
|
13
|
+
expect(subject.respond_to?(attribute)).to eq(true)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'it should return false in for unknown attributes/methods' do
|
18
|
+
expect(subject.respond_to?(:unknown)).to eq(false)
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'it should return true for any existing method' do
|
22
|
+
expect(subject.respond_to?(:my_method)).to eq(true)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context "when there is a known schema" do
|
27
|
+
subject { UserWithAddressAndPosts::Son.new(attributes_for(:user_with_address_and_posts)) }
|
28
|
+
let(:known_schema_attributes) { ["posts", "address", "manager"] }
|
29
|
+
|
30
|
+
it 'it should return true for every attribute used uppon initialization' do
|
31
|
+
initial_attributes_keys.each do |attribute|
|
32
|
+
expect(subject.respond_to?(attribute)).to eq(true)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'it should return true for known schema attributes' do
|
37
|
+
known_schema_attributes.each do |attribute|
|
38
|
+
expect(subject.respond_to?(attribute)).to eq(true)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
describe "#method_missing" do
|
46
|
+
|
47
|
+
context "when calling a method that matches the initialized attributes" do
|
48
|
+
subject { User::Base.new(attributes_for(:user)) }
|
49
|
+
|
50
|
+
it 'it should return the value of that same attribute' do
|
51
|
+
attributes_for(:user).each do |key, value|
|
52
|
+
expect(subject.send(key)).to eq(value)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context "when .strict_behaviour is true" do
|
58
|
+
subject { UserWithAddressAndPosts::Son.new(attributes_for(:user_with_address_and_posts)) }
|
59
|
+
|
60
|
+
context "when calling a method that doesn't match the initialized attributes but matches the schema" do
|
61
|
+
it 'it should return nil' do
|
62
|
+
expect(subject.manager).to eq(nil)
|
63
|
+
end
|
64
|
+
|
65
|
+
it "#respond_to? must return true" do
|
66
|
+
expect(subject.respond_to?(:manager)).to eq(true)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
context "when calling a method that doesn't match either the schema nor the initialized attributes" do
|
71
|
+
it 'it should raise NoMethodError' do
|
72
|
+
expect { subject.unknown_method }.to raise_error NoMethodError
|
73
|
+
end
|
74
|
+
|
75
|
+
it "#respond_to? must return false" do
|
76
|
+
expect(subject.respond_to?(:unknown_method)).to eq(false)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
context "when setting a new attribute not declared on schema" do
|
81
|
+
before { subject.unknown_attribute = 'unknown_value' }
|
82
|
+
|
83
|
+
it "#known_attributes must reflect that new attribute" do
|
84
|
+
expect(subject.known_attributes.to_a).to include('unknown_attribute')
|
85
|
+
end
|
86
|
+
|
87
|
+
it "#respond_to? must return true" do
|
88
|
+
expect(subject.respond_to?(:unknown_attribute)).to eq(true)
|
89
|
+
end
|
90
|
+
|
91
|
+
it "calling a method with the same name must return that attribute's value" do
|
92
|
+
expect(subject.unknown_attribute).to eq('unknown_value')
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
context "when .strict_behaviour is false" do
|
98
|
+
subject { UserWithAddressAndPosts::SoftBehaviour.new(attributes_for(:user_with_address_and_posts)) }
|
99
|
+
|
100
|
+
context "when calling a method that doesn't match the initialized attributes but matches the schema" do
|
101
|
+
it 'it should return nil' do
|
102
|
+
expect(subject.manager).to eq(nil)
|
103
|
+
end
|
104
|
+
|
105
|
+
it "#respond_to? must return true" do
|
106
|
+
expect(subject.respond_to?(:manager)).to eq(true)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
context "when calling a method that doesn't match either the schema nor the initialized attributes" do
|
111
|
+
it 'it should return nil' do
|
112
|
+
expect(subject.unknown_method).to eq(nil)
|
113
|
+
end
|
114
|
+
|
115
|
+
it "#respond_to? must return false" do
|
116
|
+
expect(subject.respond_to?(:unknown_method)).to eq(false)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
context "when setting a new attribute not declared on schema" do
|
121
|
+
before { subject.unknown_attribute = 'unknown_value' }
|
122
|
+
|
123
|
+
it "#known_attributes must reflect that new attribute" do
|
124
|
+
expect(subject.known_attributes.to_a).to include('unknown_attribute')
|
125
|
+
end
|
126
|
+
|
127
|
+
it "#respond_to? must return true" do
|
128
|
+
expect(subject.respond_to?(:unknown_attribute)).to eq(true)
|
129
|
+
end
|
130
|
+
|
131
|
+
it "calling a method with the same name must return that attribute's value" do
|
132
|
+
expect(subject.unknown_attribute).to eq('unknown_value')
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
138
|
+
|
139
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
shared_examples_for "finder method" do
|
4
|
+
it "it should return a RemoteCall instance with a subject's class instance" do
|
5
|
+
expect(user).to be_instance_of(subject)
|
6
|
+
end
|
7
|
+
|
8
|
+
it "the instance class should be populated with the returned hash" do
|
9
|
+
expect(user.attributes).to eq(attributes_for(:user_with_address_and_posts))
|
10
|
+
end
|
11
|
+
|
12
|
+
it "#has_data_from_server and #from_server should return true" do
|
13
|
+
expect(user.has_data_from_server).to be true
|
14
|
+
expect(user.from_server).to be true
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe SmoothOperator::FinderMethods do
|
19
|
+
subject { UserWithAddressAndPosts::Son }
|
20
|
+
|
21
|
+
# describe ".all" do
|
22
|
+
# context "when NO arguments are passed" do
|
23
|
+
# it "it should can .find(:all, {}, {})" do
|
24
|
+
# expect(subject).to receive(:find).with(:all, {}, {})
|
25
|
+
# subject.all
|
26
|
+
# end
|
27
|
+
# end
|
28
|
+
|
29
|
+
# context "when arguments are passed" do
|
30
|
+
# it "it should can .find(:all) with the same arguments that .alll has received" do
|
31
|
+
# arguments = [{ id: 2 }, { http_verb: 'head' }]
|
32
|
+
|
33
|
+
# expect(subject).to receive(:find).with(:all, *arguments)
|
34
|
+
|
35
|
+
# subject.all(*arguments)
|
36
|
+
# end
|
37
|
+
# end
|
38
|
+
# end
|
39
|
+
|
40
|
+
describe ".find" do
|
41
|
+
context "when the server returns a single hash" do
|
42
|
+
let(:user) { subject.find(5).object }
|
43
|
+
|
44
|
+
it_behaves_like "finder method"
|
45
|
+
end
|
46
|
+
|
47
|
+
context "when the server returns a hash with meta_data" do
|
48
|
+
let(:user) { subject.find("5/with_metadata").object }
|
49
|
+
|
50
|
+
it_behaves_like "finder method"
|
51
|
+
|
52
|
+
it "#meta_data should reflect the receiving meta_data" do
|
53
|
+
expect(user._meta_data).to eq({ "status" => 1 })
|
54
|
+
end
|
55
|
+
|
56
|
+
it "user should NOT contain meta_data" do
|
57
|
+
expect { user.status }.to raise_error NoMethodError
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context "when the server returns an array" do
|
62
|
+
it "it should return a RemoteCall instance an array that contains a subject's class instance, one for every array's entry" do
|
63
|
+
remote_call = subject.find(:all)
|
64
|
+
users = remote_call.objects
|
65
|
+
|
66
|
+
expect(users).to be_instance_of(Array)
|
67
|
+
expect(users[0]).to be_instance_of(subject)
|
68
|
+
expect(users[1]).to be_instance_of(subject)
|
69
|
+
end
|
70
|
+
|
71
|
+
it "if any of the array entries is not a hash, it shall not be converted or alteread" do
|
72
|
+
remote_call = subject.find('misc_array')
|
73
|
+
users = remote_call.objects
|
74
|
+
|
75
|
+
expect(users).to be_instance_of(Array)
|
76
|
+
expect(users[0]).to be_instance_of(subject)
|
77
|
+
expect(users[1]).to be(2)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
context "when the server returns a hash with a key (equal to subject's call.resources_name) containing an array" do
|
82
|
+
it "it should return a RemoteCall instance an instance of ArrayWithMetaData" do
|
83
|
+
remote_call = subject.find('with_metadata')
|
84
|
+
users = remote_call.data
|
85
|
+
|
86
|
+
expect(users).to be_instance_of(SmoothOperator::ArrayWithMetaData)
|
87
|
+
expect(users.page).to be(1)
|
88
|
+
expect(users.total).to be(6)
|
89
|
+
users.each { |user| expect(user).to be_instance_of(subject) }
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
context "when the server returns an array with nested object on each entry, with the same name has the resource" do
|
94
|
+
it "it should return an Array with Class instances" do
|
95
|
+
remote_call = subject.find('array_with_nested_users')
|
96
|
+
users = remote_call.data
|
97
|
+
|
98
|
+
expect(users).to be_instance_of(Array)
|
99
|
+
users.each { |user| expect(user).to be_instance_of(subject) }
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe SmoothOperator::ModelSchema do
|
4
|
+
|
5
|
+
describe "#known_attributes" do
|
6
|
+
let(:initial_attributes_keys) { attributes_for(:user).keys.map(&:to_s) }
|
7
|
+
|
8
|
+
context "when there is no declared schema" do
|
9
|
+
subject { User::Base.new(attributes_for(:user)) }
|
10
|
+
|
11
|
+
it 'it should reflect the attributes used uppon initialization' do
|
12
|
+
expect(subject.known_attributes.to_a).to match_array(initial_attributes_keys)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
context "when there is a known schema" do
|
17
|
+
subject { UserWithAddressAndPosts::Son.new(attributes_for(:user)) }
|
18
|
+
let(:known_schema_attributes) { ["posts", "address", "manager"] }
|
19
|
+
|
20
|
+
it 'it should reflect the attributes used uppon initialization' do
|
21
|
+
expect(subject.known_attributes.to_a).to include(*initial_attributes_keys)
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'it should reflect the known schema attributes' do
|
25
|
+
expect(subject.known_attributes.to_a).to include(*known_schema_attributes)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe SmoothOperator::Operator do
|
4
|
+
subject { User::Base }
|
5
|
+
|
6
|
+
describe "#get" do
|
7
|
+
|
8
|
+
context "submiting a hash, with an array" do
|
9
|
+
|
10
|
+
it 'should correctly encode that hash' do
|
11
|
+
remote_call = subject.get('test_hash_with_array', attributes_for(:user_with_address_and_posts))
|
12
|
+
|
13
|
+
expect(remote_call.status).to eq(true)
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should send the extra params set by .query_string method" do
|
19
|
+
remote_call = subject.get('test_query_string', { normal_param: true })
|
20
|
+
|
21
|
+
expect(remote_call.status).to eq(true)
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "#post" do
|
27
|
+
|
28
|
+
context "submiting a hash, with an array" do
|
29
|
+
|
30
|
+
it 'should correctly encode that hash' do
|
31
|
+
remote_call = subject.post('test_hash_with_array', attributes_for(:user_with_address_and_posts))
|
32
|
+
|
33
|
+
expect(remote_call.status).to eq(true)
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should send the extra params set by .query_string method" do
|
39
|
+
remote_call = subject.post('test_query_string', { normal_param: true })
|
40
|
+
|
41
|
+
expect(remote_call.status).to eq(true)
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|