smooth_operator 1.8.8 → 1.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/console.rb +1 -1
- data/lib/smooth_operator.rb +1 -1
- data/lib/smooth_operator/array_with_meta_data.rb +1 -1
- data/lib/smooth_operator/attribute_assignment.rb +49 -5
- data/lib/smooth_operator/attributes/base.rb +17 -0
- data/lib/smooth_operator/attributes/dirty.rb +31 -0
- data/lib/smooth_operator/helpers.rb +5 -1
- data/lib/smooth_operator/open_struct.rb +15 -7
- data/lib/smooth_operator/type_converter.rb +35 -0
- data/lib/smooth_operator/version.rb +1 -1
- data/spec/factories/user_factory.rb +3 -3
- data/spec/smooth_operator/attribute_assignment_spec.rb +24 -10
- data/spec/smooth_operator/attributes_dirty_spec.rb +53 -0
- data/spec/smooth_operator/delegation_spec.rb +1 -47
- data/spec/smooth_operator/model_schema_spec.rb +1 -1
- data/spec/smooth_operator/operator_spec.rb +1 -1
- data/spec/smooth_operator/validations_spec.rb +1 -1
- data/spec/support/models/address.rb +4 -0
- data/spec/support/models/post.rb +0 -2
- data/spec/support/models/user.rb +25 -7
- data/spec/support/models/user_with_address_and_posts.rb +9 -1
- metadata +5 -2
- data/lib/smooth_operator/internal_attribute.rb +0 -49
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
M2UzYWIwNGJhMGE3YTA4YTUyNjA5MzM2NzdkMTM1MzdjZWFmZjVlYg==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
YTVjOTE5MWM3NmNkNjA3MWUyNmU5M2Y5YThjMDM1NzYwOTQyZjdkMw==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
N2YwN2Y3ODg3YzFhZDQxNjA1OWM4YTk3M2ExYTZkZWYxYjhkN2Y4N2M1ZTQw
|
10
|
+
NTllZTBhMGYxOGM3OTU4OTA4ZWUyMGIwNmY2YzM2NTZjNmQ2YmJiMzMwYjE1
|
11
|
+
MmQwYjgwOWI4ZjI5MjU1NTljNTg5MzY0ZWZjM2FiYzk5MDc3YWU=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
M2I2NWVhZjExZGYzN2NkYTIwNjM5YWRjNGZlZDQ4Njk5MjNlZGI1YjQzM2U3
|
14
|
+
MmVlNWZkMWUyMDI1Y2ZhMGZmZWUwY2VjYjA2MzYyNWI0YjRmNDlkM2I1MWY4
|
15
|
+
YTVjZTRmZGM4NGY0YzdlNjBmMDAwOTg4YmNiMjFkMWFiYmYxMjA=
|
data/console.rb
CHANGED
data/lib/smooth_operator.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
|
-
require 'smooth_operator/
|
1
|
+
require 'smooth_operator/attributes/base'
|
2
|
+
require 'smooth_operator/attributes/dirty'
|
2
3
|
|
3
4
|
module SmoothOperator
|
4
5
|
|
@@ -10,7 +11,11 @@ module SmoothOperator
|
|
10
11
|
|
11
12
|
module ClassMethods
|
12
13
|
|
13
|
-
|
14
|
+
attr_writer :unknown_hash_class
|
15
|
+
|
16
|
+
def unknown_hash_class
|
17
|
+
Helpers.get_instance_variable(self, :unknown_hash_class, ::OpenStruct)
|
18
|
+
end
|
14
19
|
|
15
20
|
def attributes_white_list
|
16
21
|
Helpers.get_instance_variable(self, :attributes_white_list, Set.new)
|
@@ -28,6 +33,14 @@ module SmoothOperator
|
|
28
33
|
attributes_black_list.merge getters.map(&:to_s)
|
29
34
|
end
|
30
35
|
|
36
|
+
def dirty_attributes
|
37
|
+
@dirty_attributes = true
|
38
|
+
end
|
39
|
+
|
40
|
+
def dirty_attributes?
|
41
|
+
@dirty_attributes
|
42
|
+
end
|
43
|
+
|
31
44
|
end
|
32
45
|
|
33
46
|
|
@@ -50,7 +63,15 @@ module SmoothOperator
|
|
50
63
|
end
|
51
64
|
|
52
65
|
def get_internal_data(field, method = :value)
|
53
|
-
|
66
|
+
result = internal_data[field]
|
67
|
+
|
68
|
+
if result.nil?
|
69
|
+
nil
|
70
|
+
elsif method == :value
|
71
|
+
result.is_a?(Attributes::Dirty) ? internal_data[field].send(method) : internal_data[field]
|
72
|
+
else
|
73
|
+
internal_data[field].send(method)
|
74
|
+
end
|
54
75
|
end
|
55
76
|
|
56
77
|
def push_to_internal_data(attribute_name, attribute_value)
|
@@ -61,9 +82,9 @@ module SmoothOperator
|
|
61
82
|
known_attributes.add attribute_name
|
62
83
|
|
63
84
|
if internal_data[attribute_name].nil?
|
64
|
-
|
85
|
+
initiate_internal_data(attribute_name, attribute_value)
|
65
86
|
else
|
66
|
-
|
87
|
+
update_internal_data(attribute_name, attribute_value)
|
67
88
|
end
|
68
89
|
end
|
69
90
|
|
@@ -84,6 +105,29 @@ module SmoothOperator
|
|
84
105
|
end
|
85
106
|
end
|
86
107
|
|
108
|
+
|
109
|
+
private ######################## PRIVATE #############################
|
110
|
+
|
111
|
+
def initiate_internal_data(attribute_name, attribute_value)
|
112
|
+
internal_data[attribute_name] = new_attribute_object(attribute_name, attribute_value)
|
113
|
+
|
114
|
+
internal_data[attribute_name] = internal_data[attribute_name].value unless self.class.dirty_attributes?
|
115
|
+
end
|
116
|
+
|
117
|
+
def update_internal_data(attribute_name, attribute_value)
|
118
|
+
if self.class.dirty_attributes?
|
119
|
+
internal_data[attribute_name].set_value(attribute_value)
|
120
|
+
else
|
121
|
+
internal_data[attribute_name] = new_attribute_object(attribute_name, attribute_value)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def new_attribute_object(attribute_name, attribute_value)
|
126
|
+
attribute_class = self.class.dirty_attributes? ? Attributes::Dirty : Attributes::Base
|
127
|
+
|
128
|
+
attribute_class.new(attribute_name, attribute_value, internal_structure[attribute_name], self.class.unknown_hash_class)
|
129
|
+
end
|
130
|
+
|
87
131
|
end
|
88
132
|
|
89
133
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'smooth_operator/type_converter'
|
2
|
+
|
3
|
+
module SmoothOperator
|
4
|
+
module Attributes
|
5
|
+
|
6
|
+
class Base
|
7
|
+
|
8
|
+
attr_reader :value
|
9
|
+
|
10
|
+
def initialize(name, value, type, unknown_hash_class)
|
11
|
+
@value = TypeConverter.cast_to_type(name, value, type, self.class, unknown_hash_class)
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'smooth_operator/type_converter'
|
2
|
+
|
3
|
+
module SmoothOperator
|
4
|
+
module Attributes
|
5
|
+
|
6
|
+
class Dirty
|
7
|
+
|
8
|
+
attr_reader :original_name, :original_value, :first_value, :value, :type, :unknown_hash_class
|
9
|
+
|
10
|
+
def initialize(name, value, type, unknown_hash_class)
|
11
|
+
@original_name, @original_value, @type, @unknown_hash_class = name, value, type, unknown_hash_class
|
12
|
+
|
13
|
+
@first_value = set_value(value)
|
14
|
+
end
|
15
|
+
|
16
|
+
def set_value(new_value)
|
17
|
+
@value = TypeConverter.cast_to_type(original_name, new_value, type, self.class, unknown_hash_class)
|
18
|
+
end
|
19
|
+
|
20
|
+
def changed?
|
21
|
+
@first_value != @value
|
22
|
+
end
|
23
|
+
|
24
|
+
def was
|
25
|
+
@first_value
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
@@ -13,8 +13,12 @@ module SmoothOperator
|
|
13
13
|
|
14
14
|
return instance_var unless instance_var.nil?
|
15
15
|
|
16
|
-
(super_method(object, variable) || default_value)
|
16
|
+
instance_var = (super_method(object, variable) || default_value)
|
17
|
+
|
18
|
+
if instance_var.class == Class
|
17
19
|
object.instance_variable_set("@#{variable}", instance_var)
|
20
|
+
else
|
21
|
+
object.instance_variable_set("@#{variable}", duplicate(instance_var))
|
18
22
|
end
|
19
23
|
end
|
20
24
|
|
@@ -5,15 +5,23 @@ require "smooth_operator/serialization"
|
|
5
5
|
require "smooth_operator/attribute_assignment"
|
6
6
|
|
7
7
|
module SmoothOperator
|
8
|
+
module OpenStruct
|
8
9
|
|
9
|
-
|
10
|
+
class Base
|
10
11
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
12
|
+
include Delegation
|
13
|
+
include Validations
|
14
|
+
include ModelSchema
|
15
|
+
include Serialization
|
16
|
+
include AttributeAssignment
|
16
17
|
|
17
|
-
|
18
|
+
end
|
19
|
+
|
20
|
+
class Dirty < Base
|
18
21
|
|
22
|
+
dirty_attributes
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
19
27
|
end
|
@@ -4,6 +4,17 @@ module SmoothOperator
|
|
4
4
|
|
5
5
|
extend self
|
6
6
|
|
7
|
+
def cast_to_type(name, value, type, array_class, unknown_hash_class)
|
8
|
+
case value
|
9
|
+
when Array
|
10
|
+
value.map { |array_entry| array_class.new(name, array_entry, type, unknown_hash_class).value }
|
11
|
+
when Hash
|
12
|
+
type.nil? ? new_unknown_hash(value, array_class, unknown_hash_class) : type.new(value)
|
13
|
+
else
|
14
|
+
TypeConverter.convert(value, type)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
7
18
|
def convert(value, type)
|
8
19
|
case type
|
9
20
|
|
@@ -63,6 +74,30 @@ module SmoothOperator
|
|
63
74
|
|
64
75
|
value.nil? ? 0 : value
|
65
76
|
end
|
77
|
+
|
78
|
+
|
79
|
+
protected ################### PROTECTED #####################
|
80
|
+
|
81
|
+
def new_unknown_hash(hash, array_class, unknown_hash_class)
|
82
|
+
if unknown_hash_class == :none
|
83
|
+
hash
|
84
|
+
else
|
85
|
+
unknown_hash_class.new(cast_params(hash, array_class, unknown_hash_class))
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
|
90
|
+
private ################### PRIVATE #####################
|
91
|
+
|
92
|
+
def cast_params(attributes, array_class, unknown_hash_class)
|
93
|
+
hash = {}
|
94
|
+
|
95
|
+
attributes.each do |key, value|
|
96
|
+
hash[key] = cast_to_type(key, value, nil, array_class, unknown_hash_class)
|
97
|
+
end
|
98
|
+
|
99
|
+
hash
|
100
|
+
end
|
66
101
|
|
67
102
|
end
|
68
103
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
FactoryGirl.define do
|
2
2
|
|
3
|
-
factory :user, class: User do
|
3
|
+
factory :user, class: User::Base do
|
4
4
|
|
5
5
|
id 1
|
6
6
|
admin true
|
@@ -20,12 +20,12 @@ FactoryGirl.define do
|
|
20
20
|
|
21
21
|
end
|
22
22
|
|
23
|
-
factory :white_list, class: User do
|
23
|
+
factory :white_list, class: User::Base do
|
24
24
|
id 1
|
25
25
|
first_name 'John'
|
26
26
|
end
|
27
27
|
|
28
|
-
factory :black_list, class: User do
|
28
|
+
factory :black_list, class: User::Base do
|
29
29
|
admin true
|
30
30
|
last_name 'Doe'
|
31
31
|
end
|
@@ -34,28 +34,42 @@ describe SmoothOperator::AttributeAssignment do
|
|
34
34
|
context "when something other than a hash is introduced" do
|
35
35
|
it "should do nothing" do
|
36
36
|
[nil, '', [1, 2], 'test', 1, 2].each do |something_other_than_a_hash|
|
37
|
-
expect(User.new(something_other_than_a_hash).internal_data).to eq({})
|
37
|
+
expect(User::Base.new(something_other_than_a_hash).internal_data).to eq({})
|
38
38
|
end
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
42
42
|
context "when one of the attribute's value, is an hash and is unknown to the schema" do
|
43
|
-
context "when the .
|
44
|
-
subject { User.new(address: { street: 'something', postal_code: { code: '123' } }) }
|
43
|
+
context "when the .unknown_hash_class is unused" do
|
44
|
+
subject { User::Base.new(address: { street: 'something', postal_code: { code: '123' } }) }
|
45
45
|
|
46
|
-
it "a new instance of
|
46
|
+
it "a new instance of OpenStruct will be initialized with that hash" do
|
47
47
|
address = subject.address
|
48
48
|
|
49
|
-
expect(address).to be_instance_of(
|
49
|
+
expect(address).to be_instance_of(OpenStruct)
|
50
50
|
expect(address.street).to eq('something')
|
51
51
|
|
52
|
-
expect(address.postal_code).to be_instance_of(
|
52
|
+
expect(address.postal_code).to be_instance_of(OpenStruct)
|
53
53
|
expect(address.postal_code.code).to eq('123')
|
54
54
|
end
|
55
55
|
end
|
56
|
-
|
57
|
-
context "when the .
|
58
|
-
subject {
|
56
|
+
|
57
|
+
context "when the .unknown_hash_class is set to SmoothOperator::OpenStruct::Base" do
|
58
|
+
subject { User::UnknownHashClass::OpenStructBase.new(address: { street: 'something', postal_code: { code: '123' } }) }
|
59
|
+
|
60
|
+
it "a new instance of SmoothOperator::OpenStruct::Base will be initialized with that hash" do
|
61
|
+
address = subject.address
|
62
|
+
|
63
|
+
expect(address).to be_instance_of(SmoothOperator::OpenStruct::Base)
|
64
|
+
expect(address.street).to eq('something')
|
65
|
+
|
66
|
+
expect(address.postal_code).to be_instance_of(SmoothOperator::OpenStruct::Base)
|
67
|
+
expect(address.postal_code.code).to eq('123')
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
context "when the .unknown_hash_class is set to :none" do
|
72
|
+
subject { User::UnknownHashClass::None.new(creator: { first_name: 'admin', address: { street: 'something' } }) }
|
59
73
|
|
60
74
|
it "the hash will be copied as it is" do
|
61
75
|
creator = subject.creator
|
@@ -70,7 +84,7 @@ describe SmoothOperator::AttributeAssignment do
|
|
70
84
|
end
|
71
85
|
|
72
86
|
context "when there is no declared schema" do
|
73
|
-
subject { User.new(attributes_for(:user)) }
|
87
|
+
subject { User::Base.new(attributes_for(:user)) }
|
74
88
|
let(:expected_internal_data) { SmoothOperator::Helpers.stringify_keys(attributes_for(:user)) }
|
75
89
|
|
76
90
|
it "it should populate 'internal_data' with unaltered duplicate data from the received hash" do
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe SmoothOperator::Attributes::Dirty do
|
4
|
+
|
5
|
+
subject { UserWithAddressAndPosts::DirtyAttributes.new(attributes_for(:user_with_address_and_posts)) }
|
6
|
+
|
7
|
+
context "when no changes are made to an attribute" do
|
8
|
+
it "checking if that attribute is changed, should return false" do
|
9
|
+
expect(subject.first_name_changed?).to be false
|
10
|
+
end
|
11
|
+
|
12
|
+
it "checking that attribute past value, should its original value" do
|
13
|
+
expect(subject.first_name_was).to eq('John')
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
context "when there are changes made to an attribute" do
|
18
|
+
before { subject.first_name = 'nhoJ' }
|
19
|
+
|
20
|
+
it "checking if that attribute is changed, should return true" do
|
21
|
+
expect(subject.first_name_changed?).to be true
|
22
|
+
end
|
23
|
+
|
24
|
+
it "checking that attribute past value, should its original value" do
|
25
|
+
expect(subject.first_name_was).to eq('John')
|
26
|
+
end
|
27
|
+
|
28
|
+
context "when there are changes to the changes made to an attribute" do
|
29
|
+
before { subject.first_name = 'no_name' }
|
30
|
+
|
31
|
+
it "checking if that attribute is changed, should return true" do
|
32
|
+
expect(subject.first_name_changed?).to be true
|
33
|
+
end
|
34
|
+
|
35
|
+
it "checking that attribute past value, should its first original value" do
|
36
|
+
expect(subject.first_name_was).to eq('John')
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context "when there are changes made to a nested object" do
|
42
|
+
before { subject.address.street = 'my street' }
|
43
|
+
|
44
|
+
it "checking if the nested object as changed, should return false" do
|
45
|
+
expect(subject.address_changed?).to be false
|
46
|
+
end
|
47
|
+
|
48
|
+
it "checking if the nested object's attribute as changed, should return true" do
|
49
|
+
expect(subject.address.street_changed?).to be true
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
@@ -45,7 +45,7 @@ describe SmoothOperator::Delegation do
|
|
45
45
|
describe "#method_missing" do
|
46
46
|
|
47
47
|
context "when calling a method that matches the initialized attributes" do
|
48
|
-
subject { User.new(attributes_for(:user)) }
|
48
|
+
subject { User::Base.new(attributes_for(:user)) }
|
49
49
|
|
50
50
|
it 'it should return the value of that same attribute' do
|
51
51
|
attributes_for(:user).each do |key, value|
|
@@ -85,52 +85,6 @@ describe SmoothOperator::Delegation do
|
|
85
85
|
end
|
86
86
|
end
|
87
87
|
|
88
|
-
context "when no changes are made to an attribute" do
|
89
|
-
it "checking it that attribute is changed, should return false" do
|
90
|
-
expect(subject.first_name_changed?).to be false
|
91
|
-
end
|
92
|
-
|
93
|
-
it "checking that attribute past value, should its original value" do
|
94
|
-
expect(subject.first_name_was).to eq('John')
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
context "when there are changes made to an attribute" do
|
99
|
-
before { subject.first_name = 'nhoJ' }
|
100
|
-
|
101
|
-
it "checking if that attribute is changed, should return true" do
|
102
|
-
expect(subject.first_name_changed?).to be true
|
103
|
-
end
|
104
|
-
|
105
|
-
it "checking that attribute past value, should its original value" do
|
106
|
-
expect(subject.first_name_was).to eq('John')
|
107
|
-
end
|
108
|
-
|
109
|
-
context "when there are changes to the changes made to an attribute" do
|
110
|
-
before { subject.first_name = 'no_name' }
|
111
|
-
|
112
|
-
it "checking it that attribute is changed, should return true" do
|
113
|
-
expect(subject.first_name_changed?).to be true
|
114
|
-
end
|
115
|
-
|
116
|
-
it "checking that attribute past value, should its first original value" do
|
117
|
-
expect(subject.first_name_was).to eq('John')
|
118
|
-
end
|
119
|
-
end
|
120
|
-
end
|
121
|
-
|
122
|
-
context "when there are changes made to a nested object" do
|
123
|
-
before { subject.address.street = 'my street' }
|
124
|
-
|
125
|
-
it "checking if the nested object as changed, should return false" do
|
126
|
-
expect(subject.address_changed?).to be false
|
127
|
-
end
|
128
|
-
|
129
|
-
it "checking if the nested object's attribute as changed, should return true" do
|
130
|
-
expect(subject.address.street_changed?).to be true
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
88
|
end
|
135
89
|
|
136
90
|
end
|
@@ -6,7 +6,7 @@ describe SmoothOperator::ModelSchema 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.new(attributes_for(:user)) }
|
9
|
+
subject { User::Base.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::Validations do
|
4
|
-
subject { User.new(attributes_for(:user)) }
|
4
|
+
subject { User::Base.new(attributes_for(:user)) }
|
5
5
|
|
6
6
|
describe "#valid?" do
|
7
7
|
context "when executing a persistence method, and the server response has a hash with the key 'errors'" do
|
@@ -1,4 +1,7 @@
|
|
1
1
|
class Address < SmoothOperator::Base
|
2
|
+
|
3
|
+
self.dirty_attributes
|
4
|
+
|
2
5
|
self.model_name = :none
|
3
6
|
|
4
7
|
self.endpoint_user = 'admin'
|
@@ -7,4 +10,5 @@ class Address < SmoothOperator::Base
|
|
7
10
|
self.endpoint = 'http://localhost:4567/'
|
8
11
|
|
9
12
|
self.headers = { "X-APPTOKEN" => "joaquim_app_token", "X-LAYERTOKEN" => "joaquim_layer_token" }
|
13
|
+
|
10
14
|
end
|
data/spec/support/models/post.rb
CHANGED
data/spec/support/models/user.rb
CHANGED
@@ -1,15 +1,33 @@
|
|
1
|
-
|
1
|
+
module User
|
2
|
+
|
3
|
+
class Base < SmoothOperator::Base
|
2
4
|
|
3
|
-
|
5
|
+
self.model_name = 'user'
|
4
6
|
|
5
|
-
|
7
|
+
self.endpoint_user = 'admin'
|
6
8
|
|
7
|
-
|
9
|
+
self.endpoint_pass = 'admin'
|
8
10
|
|
9
|
-
|
10
|
-
|
11
|
+
self.endpoint = 'http://localhost:4567/'
|
12
|
+
|
13
|
+
def self.query_string(params)
|
14
|
+
params['query_string_param'] = true
|
15
|
+
|
16
|
+
params
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
module UnknownHashClass
|
22
|
+
|
23
|
+
class OpenStructBase < User::Base
|
24
|
+
self.unknown_hash_class = SmoothOperator::OpenStruct::Base
|
25
|
+
end
|
26
|
+
|
27
|
+
class None < User::Base
|
28
|
+
self.unknown_hash_class = :none
|
29
|
+
end
|
11
30
|
|
12
|
-
params
|
13
31
|
end
|
14
32
|
|
15
33
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module UserWithAddressAndPosts
|
2
2
|
|
3
|
-
class Father < User
|
3
|
+
class Father < User::Base
|
4
4
|
|
5
5
|
schema(
|
6
6
|
posts: Post,
|
@@ -70,4 +70,12 @@ module UserWithAddressAndPosts
|
|
70
70
|
|
71
71
|
end
|
72
72
|
|
73
|
+
class DirtyAttributes < UserWithAddressAndPosts::Son
|
74
|
+
|
75
|
+
self.dirty_attributes
|
76
|
+
|
77
|
+
self.unknown_hash_class = SmoothOperator::OpenStruct::Dirty
|
78
|
+
|
79
|
+
end
|
80
|
+
|
73
81
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: smooth_operator
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- João Gonçalves
|
@@ -69,10 +69,11 @@ files:
|
|
69
69
|
- lib/smooth_operator.rb
|
70
70
|
- lib/smooth_operator/array_with_meta_data.rb
|
71
71
|
- lib/smooth_operator/attribute_assignment.rb
|
72
|
+
- lib/smooth_operator/attributes/base.rb
|
73
|
+
- lib/smooth_operator/attributes/dirty.rb
|
72
74
|
- lib/smooth_operator/delegation.rb
|
73
75
|
- lib/smooth_operator/finder_methods.rb
|
74
76
|
- lib/smooth_operator/helpers.rb
|
75
|
-
- lib/smooth_operator/internal_attribute.rb
|
76
77
|
- lib/smooth_operator/model_schema.rb
|
77
78
|
- lib/smooth_operator/open_struct.rb
|
78
79
|
- lib/smooth_operator/operator.rb
|
@@ -86,6 +87,7 @@ files:
|
|
86
87
|
- smooth_operator.gemspec
|
87
88
|
- spec/factories/user_factory.rb
|
88
89
|
- spec/smooth_operator/attribute_assignment_spec.rb
|
90
|
+
- spec/smooth_operator/attributes_dirty_spec.rb
|
89
91
|
- spec/smooth_operator/delegation_spec.rb
|
90
92
|
- spec/smooth_operator/finder_methods_spec.rb
|
91
93
|
- spec/smooth_operator/model_schema_spec.rb
|
@@ -130,6 +132,7 @@ summary: Simple and fully customizable alternative to ActiveResource, using fara
|
|
130
132
|
test_files:
|
131
133
|
- spec/factories/user_factory.rb
|
132
134
|
- spec/smooth_operator/attribute_assignment_spec.rb
|
135
|
+
- spec/smooth_operator/attributes_dirty_spec.rb
|
133
136
|
- spec/smooth_operator/delegation_spec.rb
|
134
137
|
- spec/smooth_operator/finder_methods_spec.rb
|
135
138
|
- spec/smooth_operator/model_schema_spec.rb
|
@@ -1,49 +0,0 @@
|
|
1
|
-
require 'smooth_operator/type_converter'
|
2
|
-
|
3
|
-
module SmoothOperator
|
4
|
-
|
5
|
-
class InternalAttribute
|
6
|
-
|
7
|
-
attr_reader :original_name, :original_value, :first_value, :value, :type, :turn_unknown_hash_to_open_struct
|
8
|
-
|
9
|
-
def initialize(name, value, type, turn_to_open_struct = nil)
|
10
|
-
@original_name, @original_value, @type = name, value, type
|
11
|
-
|
12
|
-
@turn_unknown_hash_to_open_struct = turn_to_open_struct.nil? ? true : turn_to_open_struct
|
13
|
-
|
14
|
-
@first_value = set_value(value)
|
15
|
-
end
|
16
|
-
|
17
|
-
def set_value(new_value)
|
18
|
-
@value = cast_to_type(new_value)
|
19
|
-
end
|
20
|
-
|
21
|
-
def changed?
|
22
|
-
@first_value != @value
|
23
|
-
end
|
24
|
-
|
25
|
-
def was
|
26
|
-
@first_value
|
27
|
-
end
|
28
|
-
|
29
|
-
|
30
|
-
protected ######################## PROTECTED #####################
|
31
|
-
|
32
|
-
def cast_to_type(_value)
|
33
|
-
case _value
|
34
|
-
when Array
|
35
|
-
_value.map { |array_entry| InternalAttribute.new(original_name, array_entry, type, turn_unknown_hash_to_open_struct).value }
|
36
|
-
when Hash
|
37
|
-
if turn_unknown_hash_to_open_struct
|
38
|
-
(type || OpenStruct).new(_value)
|
39
|
-
else
|
40
|
-
type.nil? ? _value : type.new(_value)
|
41
|
-
end
|
42
|
-
else
|
43
|
-
TypeConverter.convert(_value, type)
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
end
|
48
|
-
|
49
|
-
end
|