protobuf-activerecord 6.1.0 → 7.1.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 +4 -4
- data/.rubocop.yml +2 -27
- data/.standard.yml +3 -0
- data/CHANGELOG.md +13 -0
- data/CODE_OF_CONDUCT.md +132 -0
- data/LICENSE.txt +17 -18
- data/README.md +8 -4
- data/Rakefile +13 -9
- data/lib/protobuf/active_record/attribute_methods.rb +2 -2
- data/lib/protobuf/active_record/columns.rb +3 -5
- data/lib/protobuf/active_record/middleware/connection_management_async.rb +2 -3
- data/lib/protobuf/active_record/middleware/query_cache.rb +1 -3
- data/lib/protobuf/active_record/nested_attributes.rb +2 -2
- data/lib/protobuf/active_record/persistence.rb +6 -6
- data/lib/protobuf/active_record/scope.rb +10 -10
- data/lib/protobuf/active_record/serialization.rb +29 -34
- data/lib/protobuf/active_record/transformation.rb +22 -25
- data/lib/protobuf/active_record/transformer.rb +1 -1
- data/lib/protobuf/active_record/version.rb +1 -1
- metadata +20 -174
- data/.gitignore +0 -12
- data/.travis.yml +0 -4
- data/Gemfile +0 -4
- data/protobuf-activerecord.gemspec +0 -43
- data/spec/protobuf/active_record/columns_spec.rb +0 -100
- data/spec/protobuf/active_record/nested_attributes_spec.rb +0 -28
- data/spec/protobuf/active_record/persistence_spec.rb +0 -70
- data/spec/protobuf/active_record/scope_spec.rb +0 -201
- data/spec/protobuf/active_record/serialization_spec.rb +0 -208
- data/spec/protobuf/active_record/transformation_spec.rb +0 -254
- data/spec/protobuf/active_record/transformer_spec.rb +0 -42
- data/spec/spec_helper.rb +0 -27
- data/spec/support/db/setup.rb +0 -29
- data/spec/support/db.rb +0 -1
- data/spec/support/definitions/messages.proto +0 -23
- data/spec/support/models/photo.rb +0 -3
- data/spec/support/models/user.rb +0 -53
- data/spec/support/models.rb +0 -2
- data/spec/support/protobuf/messages.pb.rb +0 -41
@@ -1,201 +0,0 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
|
3
|
-
describe Protobuf::ActiveRecord::Scope do
|
4
|
-
before do
|
5
|
-
@field_parsers = User.instance_variable_get("@_searchable_field_parsers")
|
6
|
-
@fields = User.instance_variable_get("@_searchable_fields")
|
7
|
-
end
|
8
|
-
|
9
|
-
after do
|
10
|
-
User.instance_variable_set("@_searchable_field_parsers", @field_parsers)
|
11
|
-
User.instance_variable_set("@_searchable_fields", @fields)
|
12
|
-
User.instance_variable_set("@_upsert_keys", [])
|
13
|
-
end
|
14
|
-
|
15
|
-
describe ".search_scope" do
|
16
|
-
let(:request) { UserSearchMessage.new(:guid => ["foo"], :email => ["foo@test.co"]) }
|
17
|
-
|
18
|
-
before {
|
19
|
-
allow(User).to receive(:searchable_field_parsers).and_return(:email => proc { |val| val })
|
20
|
-
}
|
21
|
-
|
22
|
-
it "builds scopes for searchable fields" do
|
23
|
-
allow(User).to receive(:searchable_fields).and_return(:email => :by_email)
|
24
|
-
expect(User.search_scope(request)).to eq User.by_email("foo@test.co")
|
25
|
-
end
|
26
|
-
|
27
|
-
it "is chainable" do
|
28
|
-
expect(User.limit(1).search_scope(request).order(:email)).to eq User.limit(1).order(:email)
|
29
|
-
end
|
30
|
-
|
31
|
-
context "when a searchable field does not have a value" do
|
32
|
-
let(:request) { UserSearchMessage.new(:email => ["foo@test.co"]) }
|
33
|
-
|
34
|
-
it "doesn't build a scope from that field" do
|
35
|
-
allow(User).to receive(:searchable_fields).and_return(:email => :by_email)
|
36
|
-
expect(User.search_scope(request)).to eq User.by_email("foo@test.co")
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
context "when a searchable field uses a non-existant scope" do
|
41
|
-
let(:request) { UserSearchMessage.new(:email => ["foo@test.co"]) }
|
42
|
-
|
43
|
-
it "raises an exception" do
|
44
|
-
allow(User).to receive(:searchable_fields).and_return(:email => :by_hullabaloo)
|
45
|
-
expect { User.search_scope(request) }.to raise_exception(/undefined method .*by_hullabaloo/i)
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
describe ".field_scope" do
|
51
|
-
context "when :scope is not defined" do
|
52
|
-
it "defines the given field as searchable using the `by_[:field]` as the scope" do
|
53
|
-
User.field_scope :guid
|
54
|
-
expect(User.searchable_fields[:guid]).to eq :by_guid
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
context "when :scope is defined" do
|
59
|
-
it "defines the given field as searchable using the given :scope" do
|
60
|
-
User.field_scope :guid, :scope => :custom_scope
|
61
|
-
expect(User.searchable_fields[:guid]).to eq :custom_scope
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
context "when :parser is not defined" do
|
66
|
-
it "doesn't define the given field as parseable" do
|
67
|
-
User.field_scope :guid
|
68
|
-
expect(User.searchable_field_parsers[:guid]).to eq nil
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
context "when :parser is defined" do
|
73
|
-
it "defines the given field as parseable using the given :parser" do
|
74
|
-
User.field_scope :guid, :parser => :parser
|
75
|
-
expect(User.searchable_field_parsers[:guid]).to eq :parser
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
describe ".parse_search_values" do
|
81
|
-
it "converts single values to collections" do
|
82
|
-
proto = UserMessage.new(:email => "the.email@test.in")
|
83
|
-
|
84
|
-
User.field_scope :email
|
85
|
-
expect(User.parse_search_values(proto, :email)).to eq ["the.email@test.in"]
|
86
|
-
end
|
87
|
-
|
88
|
-
context "when a field parser is defined" do
|
89
|
-
before { User.field_scope :guid, :parser => parser }
|
90
|
-
|
91
|
-
let(:proto) { UserSearchMessage.new(:guid => ["foo"]) }
|
92
|
-
|
93
|
-
context "and the parser does not respond to :to_sym" do
|
94
|
-
let(:parser) { double("parser") }
|
95
|
-
|
96
|
-
it "passes the value to the parser" do
|
97
|
-
expect(parser).to receive(:call).with(["foo"])
|
98
|
-
User.parse_search_values(proto, :guid)
|
99
|
-
end
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
context "when the field is an enum" do
|
104
|
-
it "maps values to integers" do
|
105
|
-
TheEnum = Class.new(::Protobuf::Enum) do
|
106
|
-
define :VALUE, 1
|
107
|
-
end
|
108
|
-
|
109
|
-
TheMessage = Class.new(::Protobuf::Message) do
|
110
|
-
optional TheEnum, :the_enum_value, 1
|
111
|
-
end
|
112
|
-
|
113
|
-
proto = TheMessage.new(:the_enum_value => TheEnum::VALUE)
|
114
|
-
expect(User.parse_search_values(proto, :the_enum_value)[0]).to be 1
|
115
|
-
end
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
describe ".upsert_key" do
|
120
|
-
it "adds the fields to the upsert_keys" do
|
121
|
-
::User.field_scope(:guid)
|
122
|
-
::User.upsert_key(:guid)
|
123
|
-
expect(::User.upsert_keys).to eq([[:guid]])
|
124
|
-
end
|
125
|
-
|
126
|
-
context "no field_scope defined" do
|
127
|
-
it "raises an error" do
|
128
|
-
expect { ::User.upsert_key(:foobar) }.to raise_error(::Protobuf::ActiveRecord::UpsertScopeError)
|
129
|
-
end
|
130
|
-
end
|
131
|
-
end
|
132
|
-
|
133
|
-
describe ".for_upsert" do
|
134
|
-
let(:guid) { "USR-1" }
|
135
|
-
let(:proto) { ::UserMessage.new(:guid => guid) }
|
136
|
-
|
137
|
-
before do
|
138
|
-
::User.delete_all
|
139
|
-
::User.field_scope(:guid)
|
140
|
-
::User.upsert_key(:guid)
|
141
|
-
end
|
142
|
-
|
143
|
-
context "no matching upsert keys" do
|
144
|
-
let(:proto) { ::UserMessage.new }
|
145
|
-
|
146
|
-
it "raises an error" do
|
147
|
-
expect { ::User.for_upsert(proto) }.to raise_error(::Protobuf::ActiveRecord::UpsertNotFoundError)
|
148
|
-
end
|
149
|
-
end
|
150
|
-
|
151
|
-
context "no existing records" do
|
152
|
-
it "returns a new record" do
|
153
|
-
record = ::User.for_upsert(proto)
|
154
|
-
expect(record.new_record?).to be true
|
155
|
-
end
|
156
|
-
end
|
157
|
-
|
158
|
-
context "existing record" do
|
159
|
-
before { ::User.create(:guid => guid) }
|
160
|
-
after { ::User.delete_all }
|
161
|
-
|
162
|
-
it "returns the existing record" do
|
163
|
-
record = ::User.for_upsert(proto)
|
164
|
-
expect(record.new_record?).to be false
|
165
|
-
end
|
166
|
-
end
|
167
|
-
end
|
168
|
-
|
169
|
-
describe ".upsert" do
|
170
|
-
let(:guid) { "USR-1" }
|
171
|
-
let(:proto) { ::UserMessage.new(:guid => guid, :email => "bar") }
|
172
|
-
|
173
|
-
before do
|
174
|
-
::User.delete_all
|
175
|
-
::User.field_scope(:guid)
|
176
|
-
::User.upsert_key(:guid)
|
177
|
-
end
|
178
|
-
|
179
|
-
context "no existing records" do
|
180
|
-
it "creates a new record" do
|
181
|
-
::User.upsert(proto)
|
182
|
-
expect(::User.count).to eq(1)
|
183
|
-
end
|
184
|
-
end
|
185
|
-
|
186
|
-
context "existing record" do
|
187
|
-
before { ::User.create(:guid => guid, :email => "foo") }
|
188
|
-
after { ::User.delete_all }
|
189
|
-
|
190
|
-
it "updates the existing record" do
|
191
|
-
::User.upsert(proto)
|
192
|
-
expect(::User.first.email).to eq("bar")
|
193
|
-
end
|
194
|
-
|
195
|
-
it "returns a user" do
|
196
|
-
result = ::User.upsert(proto)
|
197
|
-
expect(result).to be_a(::User)
|
198
|
-
end
|
199
|
-
end
|
200
|
-
end
|
201
|
-
end
|
@@ -1,208 +0,0 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
|
3
|
-
# Used to test calling #to_proto when no protobuf message is configured.
|
4
|
-
class UnconfiguredUser
|
5
|
-
include Protobuf::ActiveRecord::Model
|
6
|
-
end
|
7
|
-
|
8
|
-
describe Protobuf::ActiveRecord::Serialization do
|
9
|
-
let(:protobuf_message) { UserMessage }
|
10
|
-
|
11
|
-
describe ".field_from_record" do
|
12
|
-
context "when the given transformer is a symbol" do
|
13
|
-
before { User.field_from_record :first_name, :extract_first_name }
|
14
|
-
|
15
|
-
it "creates a symbol transformer from the converter" do
|
16
|
-
expect(User._protobuf_field_symbol_transformers[:first_name]).to eq :extract_first_name
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
context "when the given transformer is not callable" do
|
21
|
-
it "raises an exception" do
|
22
|
-
expect { User.field_from_record :name, nil }.to raise_exception(Protobuf::ActiveRecord::FieldTransformerError)
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
context "when the given transformer is callable" do
|
27
|
-
let(:callable) { lambda { |_proto| nil } }
|
28
|
-
|
29
|
-
before {
|
30
|
-
allow(User).to receive(:_protobuf_field_transformers).and_return({})
|
31
|
-
User.field_from_record :account_id, callable
|
32
|
-
}
|
33
|
-
|
34
|
-
it "adds the given converter to the list of protobuf field transformers" do
|
35
|
-
expect(User._protobuf_field_transformers[:account_id]).to eq(callable)
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
describe ".protobuf_message" do
|
41
|
-
let(:options) { { :only => [] } }
|
42
|
-
|
43
|
-
before { User.protobuf_message(protobuf_message, options) }
|
44
|
-
after { User.protobuf_message(protobuf_message, {}) }
|
45
|
-
|
46
|
-
context "given a value" do
|
47
|
-
it "defines #to_proto" do
|
48
|
-
expect(User.allocate).to respond_to :to_proto
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
context "given options" do
|
53
|
-
it "merges them with protobuf field options" do
|
54
|
-
expect(User._protobuf_field_options).to eq options
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
it "returns the protobuf message for this object" do
|
59
|
-
expect(User.protobuf_message).to eq protobuf_message
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
context "when protobuf_message is defined" do
|
64
|
-
let(:attributes) { {} }
|
65
|
-
let(:user) { User.new(attributes) }
|
66
|
-
|
67
|
-
before { User.protobuf_message(protobuf_message) }
|
68
|
-
|
69
|
-
describe "#_filter_field_attributes" do
|
70
|
-
context "when options has :only" do
|
71
|
-
it "only returns the given field(s)" do
|
72
|
-
fields = user._filter_field_attributes(:only => :name)
|
73
|
-
expect(fields).to eq [:name]
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
context "when options has :except" do
|
78
|
-
it "returns all except the given field(s)" do
|
79
|
-
fields = user._filter_field_attributes(:except => :name)
|
80
|
-
expect(fields).to match_array(
|
81
|
-
[:guid, :email, :email_domain, :password, :nullify, :photos, :created_at, :updated_at]
|
82
|
-
)
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
describe "#_filtered_fields" do
|
88
|
-
it "returns protobuf fields" do
|
89
|
-
expect(user._filtered_fields).to match_array(
|
90
|
-
[:guid, :name, :email, :email_domain, :password, :nullify, :photos, :created_at, :updated_at]
|
91
|
-
)
|
92
|
-
end
|
93
|
-
|
94
|
-
context "given :deprecated => false" do
|
95
|
-
it "filters all deprecated fields" do
|
96
|
-
fields = user._filtered_fields(:deprecated => false)
|
97
|
-
expect(fields).to match_array(
|
98
|
-
[:guid, :name, :email, :password, :nullify, :photos, :created_at, :updated_at]
|
99
|
-
)
|
100
|
-
end
|
101
|
-
|
102
|
-
context "and :include => :email_domain" do
|
103
|
-
it "includes deprecated fields that have been explicitly specified" do
|
104
|
-
fields = user._filtered_fields(:deprecated => false, :include => :email_domain)
|
105
|
-
expect(fields).to match_array(
|
106
|
-
[:guid, :name, :email, :email_domain, :password, :nullify, :photos, :created_at, :updated_at]
|
107
|
-
)
|
108
|
-
end
|
109
|
-
end
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
describe "#_normalize_options" do
|
114
|
-
let(:options) { { :only => [:name] } }
|
115
|
-
|
116
|
-
context "given empty options" do
|
117
|
-
before { User.protobuf_message(protobuf_message, options) }
|
118
|
-
|
119
|
-
it "returns the class's protobuf field options" do
|
120
|
-
expect(User.allocate._normalize_options({})).to eq options
|
121
|
-
end
|
122
|
-
end
|
123
|
-
|
124
|
-
context "given options" do
|
125
|
-
before { User.protobuf_message(protobuf_message, {}) }
|
126
|
-
|
127
|
-
it "merges them with the class's protobuf field options" do
|
128
|
-
normalized_options = User.allocate._normalize_options(options)
|
129
|
-
expect(normalized_options[:only]).to eq options[:only]
|
130
|
-
end
|
131
|
-
end
|
132
|
-
|
133
|
-
context "given options with :only" do
|
134
|
-
before { User.protobuf_message(protobuf_message, {}) }
|
135
|
-
|
136
|
-
it "ensures that :except exists" do
|
137
|
-
normalized_options = User.allocate._normalize_options(options)
|
138
|
-
expect(normalized_options[:except]).to eq []
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
context "given options with :except" do
|
143
|
-
let(:options) { { :except => [:name] } }
|
144
|
-
|
145
|
-
before { User.protobuf_message(protobuf_message, {}) }
|
146
|
-
|
147
|
-
it "ensures that :only exists" do
|
148
|
-
normalized_options = User.allocate._normalize_options(options)
|
149
|
-
expect(normalized_options[:only]).to eq []
|
150
|
-
end
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
|
-
describe "#fields_from_record" do
|
155
|
-
let(:attributes) {
|
156
|
-
{
|
157
|
-
:guid => "foo",
|
158
|
-
:first_name => "bar",
|
159
|
-
:last_name => "baz",
|
160
|
-
:email => "foo@test.co"
|
161
|
-
}
|
162
|
-
}
|
163
|
-
|
164
|
-
context "when a transformer is defined for the field" do
|
165
|
-
it "gets the field from the transformer" do
|
166
|
-
expect(user.fields_from_record[:email_domain]).to eq("test.co")
|
167
|
-
end
|
168
|
-
end
|
169
|
-
|
170
|
-
context "given options with :include" do
|
171
|
-
it "adds the given field to the list of serialized fields" do
|
172
|
-
fields = user.fields_from_record(:include => :token)
|
173
|
-
expect(fields).to include(:token)
|
174
|
-
end
|
175
|
-
end
|
176
|
-
|
177
|
-
context "when a field is a collection association" do
|
178
|
-
let(:user) { User.create(attributes) }
|
179
|
-
|
180
|
-
it "terminates the association proxy" do
|
181
|
-
fields = user.fields_from_record(:include => :photos)
|
182
|
-
expect(fields[:photos]).to be_an(Array)
|
183
|
-
end
|
184
|
-
end
|
185
|
-
end
|
186
|
-
|
187
|
-
describe "#to_proto" do
|
188
|
-
context "when a protobuf message is configured" do
|
189
|
-
let(:proto) { protobuf_message.new(proto_hash) }
|
190
|
-
let(:proto_hash) { { :name => "foo" } }
|
191
|
-
|
192
|
-
before { allow(user).to receive(:fields_from_record).and_return(proto_hash) }
|
193
|
-
|
194
|
-
it "intializes a new protobuf message with attributes from #to_proto_hash" do
|
195
|
-
expect(user.to_proto).to eq proto
|
196
|
-
end
|
197
|
-
end
|
198
|
-
|
199
|
-
context "when a protobuf message is not configured" do
|
200
|
-
let(:user) { UnconfiguredUser.new }
|
201
|
-
|
202
|
-
it "raises an exception" do
|
203
|
-
expect { user.to_proto }.to raise_exception(Protobuf::ActiveRecord::MessageNotDefined)
|
204
|
-
end
|
205
|
-
end
|
206
|
-
end
|
207
|
-
end
|
208
|
-
end
|
@@ -1,254 +0,0 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
|
3
|
-
describe Protobuf::ActiveRecord::Transformation do
|
4
|
-
let(:user) { User.new(user_attributes) }
|
5
|
-
let(:user_attributes) { { :first_name => "foo", :last_name => "bar", :email => "foo@test.co" } }
|
6
|
-
let(:proto_hash) { { :name => "foo bar", :email => "foo@test.co" } }
|
7
|
-
let(:proto) { UserMessage.new(proto_hash) }
|
8
|
-
|
9
|
-
describe "._filter_attribute_fields" do
|
10
|
-
it "includes fields that have values" do
|
11
|
-
attribute_fields = User._filter_attribute_fields(proto)
|
12
|
-
expect(attribute_fields[:email]).to eq proto_hash[:email]
|
13
|
-
end
|
14
|
-
|
15
|
-
it "filters repeated fields" do
|
16
|
-
attribute_fields = User._filter_attribute_fields(proto)
|
17
|
-
expect(attribute_fields.key?(:tags)).to be false
|
18
|
-
end
|
19
|
-
|
20
|
-
it "includes attributes that aren't fields, but have attribute transformers" do
|
21
|
-
allow(User).to receive(:_protobuf_attribute_transformers).and_return(:account_id => :fetch_account_id)
|
22
|
-
attribute_fields = User._filter_attribute_fields(proto)
|
23
|
-
expect(attribute_fields.key?(:account_id)).to be true
|
24
|
-
end
|
25
|
-
|
26
|
-
it "includes fields that aren't attributes, but have attribute transformers" do
|
27
|
-
attribute_fields = User._filter_attribute_fields(proto)
|
28
|
-
expect(attribute_fields.key?(:password)).to be true
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
describe "._protobuf_convert_fields_to_attributes" do
|
33
|
-
context "when the given field's corresponding column type is :date" do
|
34
|
-
let(:date) { Date.current }
|
35
|
-
let(:value) { date.to_time.to_i }
|
36
|
-
|
37
|
-
before {
|
38
|
-
allow(User).to receive(:_protobuf_date_datetime_time_or_timestamp_column?).and_return(true)
|
39
|
-
allow(User).to receive(:_protobuf_date_column?).and_return(true)
|
40
|
-
}
|
41
|
-
|
42
|
-
it "converts the given value to a Date object" do
|
43
|
-
expect(User._protobuf_convert_fields_to_attributes(:foo_date, value)).to eq date
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
context "when given field's corresponding the column type is :datetime" do
|
48
|
-
let(:datetime) { DateTime.current }
|
49
|
-
let(:value) { datetime.to_i }
|
50
|
-
|
51
|
-
before {
|
52
|
-
allow(User).to receive(:_protobuf_date_datetime_time_or_timestamp_column?).and_return(true)
|
53
|
-
allow(User).to receive(:_protobuf_datetime_column?).and_return(true)
|
54
|
-
}
|
55
|
-
|
56
|
-
it "converts the given value to a DateTime object" do
|
57
|
-
expect(User._protobuf_convert_fields_to_attributes(:foo_datetime, value)).to be_a(DateTime)
|
58
|
-
end
|
59
|
-
|
60
|
-
it "converts the given value to a DateTime object of the same value" do
|
61
|
-
expect(User._protobuf_convert_fields_to_attributes(:foo_datetime, value)).to be_within(1).of(datetime)
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
context "when given field's corresponding the column type is :time" do
|
66
|
-
let(:time) { Time.current }
|
67
|
-
let(:value) { time.to_i }
|
68
|
-
|
69
|
-
before {
|
70
|
-
allow(User).to receive(:_protobuf_date_datetime_time_or_timestamp_column?).and_return(true)
|
71
|
-
allow(User).to receive(:_protobuf_time_column?).and_return(true)
|
72
|
-
}
|
73
|
-
|
74
|
-
it "converts the given value to a Time object" do
|
75
|
-
expect(User._protobuf_convert_fields_to_attributes(:foo_time, value)).to be_a(Time)
|
76
|
-
end
|
77
|
-
|
78
|
-
it "converts the given value to a Time object of the same value" do
|
79
|
-
expect(User._protobuf_convert_fields_to_attributes(:foo_time, value)).to be_within(1).of(time)
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
context "when given field's corresponding the column type is :timestamp" do
|
84
|
-
let(:time) { Time.current }
|
85
|
-
let(:value) { time.to_i }
|
86
|
-
|
87
|
-
before {
|
88
|
-
allow(User).to receive(:_protobuf_date_datetime_time_or_timestamp_column?).and_return(true)
|
89
|
-
allow(User).to receive(:_protobuf_timestamp_column?).and_return(true)
|
90
|
-
}
|
91
|
-
|
92
|
-
it "converts the given value to a Time object" do
|
93
|
-
expect(User._protobuf_convert_fields_to_attributes(:foo_time, value)).to be_a(Time)
|
94
|
-
end
|
95
|
-
|
96
|
-
it "converts the given value to a Time object of the same value" do
|
97
|
-
expect(User._protobuf_convert_fields_to_attributes(:foo_timestamp, value)).to be_within(1).of(time)
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
context "when no conversion is necessary" do
|
102
|
-
let(:value) { "Foo" }
|
103
|
-
|
104
|
-
it "returns the given value" do
|
105
|
-
expect(User._protobuf_convert_fields_to_attributes(:foo, value)).to eq value
|
106
|
-
end
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
describe ".attributes_from_proto" do
|
111
|
-
let(:callable) { lambda { |_proto| 1 } }
|
112
|
-
let(:transformer) { ::Protobuf::ActiveRecord::Transformer.new(callable) }
|
113
|
-
|
114
|
-
context "when a transformer is defined for the attribute" do
|
115
|
-
it "transforms the field value" do
|
116
|
-
attribute_fields = User.attributes_from_proto(proto)
|
117
|
-
expect(attribute_fields[:first_name]).to eq user_attributes[:first_name]
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
context "when a transformer is a callable that returns nil" do
|
122
|
-
let(:callable) { lambda { |_proto| nil } }
|
123
|
-
|
124
|
-
before do
|
125
|
-
transformers = User._protobuf_attribute_transformers
|
126
|
-
allow(User).to receive(:_protobuf_attribute_transformers).and_return(
|
127
|
-
{ :account_id => transformer }.merge(transformers)
|
128
|
-
)
|
129
|
-
end
|
130
|
-
|
131
|
-
it "does not set the attribute" do
|
132
|
-
attribute_fields = User.attributes_from_proto(proto)
|
133
|
-
expect(attribute_fields).to eq user_attributes
|
134
|
-
end
|
135
|
-
end
|
136
|
-
|
137
|
-
context "when the transformer has a nullify_on option" do
|
138
|
-
let(:callable) { lambda { |_proto| nil } }
|
139
|
-
let(:transformer) { ::Protobuf::ActiveRecord::Transformer.new(callable, :nullify_on => :account_id) }
|
140
|
-
let(:proto_hash) { { :name => "foo bar", :email => "foo@test.co", :nullify => [:account_id] } }
|
141
|
-
|
142
|
-
before do
|
143
|
-
transformers = User._protobuf_attribute_transformers
|
144
|
-
allow(User).to receive(:_protobuf_attribute_transformers).and_return(
|
145
|
-
{ :account_id => transformer }.merge(transformers)
|
146
|
-
)
|
147
|
-
end
|
148
|
-
|
149
|
-
it "does not set the attribute" do
|
150
|
-
attribute_fields = User.attributes_from_proto(proto)
|
151
|
-
expect(attribute_fields).to include(:account_id => nil)
|
152
|
-
end
|
153
|
-
end
|
154
|
-
|
155
|
-
context "when a transformer is a callable that returns a value" do
|
156
|
-
before do
|
157
|
-
transformers = User._protobuf_attribute_transformers
|
158
|
-
allow(User).to receive(:_protobuf_attribute_transformers).and_return(
|
159
|
-
{ :account_id => transformer }.merge(transformers)
|
160
|
-
)
|
161
|
-
end
|
162
|
-
|
163
|
-
it "sets the attribute" do
|
164
|
-
attribute_fields = User.attributes_from_proto(proto)
|
165
|
-
expect(attribute_fields).to eq user_attributes.merge(:account_id => 1)
|
166
|
-
end
|
167
|
-
end
|
168
|
-
|
169
|
-
context "when a transformer is not defined for the attribute" do
|
170
|
-
before {
|
171
|
-
allow(User).to receive(:_protobuf_convert_fields_to_attributes) do |_key, value|
|
172
|
-
value
|
173
|
-
end
|
174
|
-
}
|
175
|
-
|
176
|
-
it "converts the field value" do
|
177
|
-
attribute_fields = User.attributes_from_proto(proto)
|
178
|
-
expect(attribute_fields).to eq user_attributes
|
179
|
-
end
|
180
|
-
end
|
181
|
-
end
|
182
|
-
|
183
|
-
describe ".attribute_from_proto" do
|
184
|
-
context "when the given transformer is a symbol" do
|
185
|
-
let(:callable) { lambda { |_value| User.__send__(:extract_first_name) } }
|
186
|
-
|
187
|
-
before { User.attribute_from_proto :first_name, :extract_first_name }
|
188
|
-
|
189
|
-
it "creates a callable method object from the converter" do
|
190
|
-
expect(User).to receive(:extract_first_name)
|
191
|
-
User._protobuf_attribute_transformers[:first_name].call(1)
|
192
|
-
end
|
193
|
-
end
|
194
|
-
|
195
|
-
context "when the given transformer is not callable" do
|
196
|
-
it "raises an exception" do
|
197
|
-
expect { User.attribute_from_proto :name, nil }.to raise_exception(Protobuf::ActiveRecord::AttributeTransformerError)
|
198
|
-
end
|
199
|
-
end
|
200
|
-
|
201
|
-
context "when the given transformer is callable" do
|
202
|
-
let(:callable) { lambda { |_proto| nil } }
|
203
|
-
|
204
|
-
before { allow(User).to receive(:_protobuf_attribute_transformers).and_return({}) }
|
205
|
-
|
206
|
-
it "adds the given converter to the list of protobuf field transformers" do
|
207
|
-
User.attribute_from_proto :account_id, callable
|
208
|
-
expect(User._protobuf_attribute_transformers[:account_id].callable).to eq callable
|
209
|
-
end
|
210
|
-
end
|
211
|
-
end
|
212
|
-
|
213
|
-
describe ".convert_int64_to_date" do
|
214
|
-
let(:date) { Date.current }
|
215
|
-
let(:int64) { date.to_time.to_i }
|
216
|
-
|
217
|
-
it "initializes a new Date object from the value" do
|
218
|
-
Timecop.freeze(Date.current) do
|
219
|
-
expect(User.convert_int64_to_date(int64)).to eq date
|
220
|
-
end
|
221
|
-
end
|
222
|
-
end
|
223
|
-
|
224
|
-
describe ".convert_int64_to_datetime" do
|
225
|
-
let(:datetime) { DateTime.current }
|
226
|
-
let(:int64) { datetime.to_i }
|
227
|
-
|
228
|
-
it "initializes a new DateTime object from the value" do
|
229
|
-
Timecop.freeze(DateTime.current) do
|
230
|
-
expected_datetime = Time.at(datetime.to_i)
|
231
|
-
converted_datetime = User.convert_int64_to_datetime(int64)
|
232
|
-
expect(converted_datetime).to eq expected_datetime
|
233
|
-
end
|
234
|
-
end
|
235
|
-
end
|
236
|
-
|
237
|
-
describe ".convert_int64_to_time" do
|
238
|
-
let(:time) { Time.current }
|
239
|
-
let(:int64) { time.to_time.to_i }
|
240
|
-
|
241
|
-
it "initializes a new Time object from the value" do
|
242
|
-
Timecop.freeze(Time.current) do
|
243
|
-
expect(User.convert_int64_to_time(int64)).to be_within(1).of(time)
|
244
|
-
end
|
245
|
-
end
|
246
|
-
end
|
247
|
-
|
248
|
-
describe "#attributes_from_proto" do
|
249
|
-
it "gets attributes from the given protobuf message" do
|
250
|
-
expect(User).to receive(:attributes_from_proto).with(proto)
|
251
|
-
user.attributes_from_proto(proto)
|
252
|
-
end
|
253
|
-
end
|
254
|
-
end
|
@@ -1,42 +0,0 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
|
3
|
-
describe ::Protobuf::ActiveRecord::Transformer do
|
4
|
-
let(:callable) { lambda { |proto| proto.name } }
|
5
|
-
let(:proto) { ::UserMessage.new(:name => "test", :nullify => ["name"]) }
|
6
|
-
let(:options) { {} }
|
7
|
-
|
8
|
-
subject { described_class.new(callable, options) }
|
9
|
-
|
10
|
-
describe "#call" do
|
11
|
-
it "calls the callable" do
|
12
|
-
result = subject.call(proto)
|
13
|
-
expect(result).to eq("test")
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
describe "#nullify?" do
|
18
|
-
context "no nullify_on set" do
|
19
|
-
it "returns false" do
|
20
|
-
expect(subject.nullify?(proto)).to eq(false)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
context "nullify_on name" do
|
25
|
-
let(:options) { { :nullify_on => :name } }
|
26
|
-
|
27
|
-
context "invalid message" do
|
28
|
-
let(:proto) { ::UserSearchMessage.new }
|
29
|
-
|
30
|
-
it "returns false" do
|
31
|
-
expect(subject.nullify?(proto)).to eq(false)
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
context "valid message" do
|
36
|
-
it "returns true" do
|
37
|
-
expect(subject.nullify?(proto)).to eq(true)
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|