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