protobuf-activerecord 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,265 @@
1
+ require 'spec_helper'
2
+
3
+ describe Protoable::Convert do
4
+ describe ".convert_int64_to_date" do
5
+ let(:date) { Date.current }
6
+ let(:int64) { date.to_time.to_i }
7
+
8
+ it "initializes a new Date object from the value" do
9
+ Timecop.freeze(Date.current) do
10
+ User.convert_int64_to_date(int64).should eq date
11
+ end
12
+ end
13
+ end
14
+
15
+ describe ".convert_int64_to_datetime" do
16
+ let(:datetime) { DateTime.current }
17
+ let(:int64) { datetime.to_time.to_i }
18
+
19
+ it "initializes a new DateTime object from the value" do
20
+ Timecop.freeze(DateTime.current) do
21
+ User.convert_int64_to_datetime(int64).should eq datetime
22
+ end
23
+ end
24
+ end
25
+
26
+ describe ".convert_int64_to_time" do
27
+ let(:time) { Time.current }
28
+ let(:int64) { time.to_time.to_i }
29
+
30
+ it "initializes a new Time object from the value" do
31
+ Timecop.freeze(Time.current) do
32
+ User.convert_int64_to_time(int64).should be_within(1).of(time)
33
+ end
34
+ end
35
+ end
36
+
37
+ describe "._protobuf_convert_columns_to_fields" do
38
+ context "when there is a column converter for the field" do
39
+ let(:email_value) { "foo@test.co" }
40
+ let(:email_converter) { User.method(:convert_email_to_lowercase) }
41
+
42
+ before { User.stub(:_protobuf_column_converters).and_return({ :email => email_converter }) }
43
+
44
+ it "calls the column converter with the given value" do
45
+ email_converter.should_receive(:call).with(email_value)
46
+ User._protobuf_convert_columns_to_fields(:email, email_value)
47
+ end
48
+
49
+ context "and it's corresponding column type has a default converter" do
50
+ before { User.stub(:_protobuf_date_column?).and_return(true) }
51
+
52
+ it "calls the column converter with the given value" do
53
+ email_converter.should_receive(:call).with(email_value)
54
+ User._protobuf_convert_columns_to_fields(:email, email_value)
55
+ end
56
+ end
57
+ end
58
+
59
+ context "when the column type is :date" do
60
+ let(:date) { Date.current }
61
+ let(:integer) { date.to_time.to_i }
62
+
63
+ before { User.stub(:_protobuf_date_column?).and_return(true) }
64
+
65
+ it "converts the given value to an integer" do
66
+ User._protobuf_convert_columns_to_fields(:foo_date, date).should eq integer
67
+ end
68
+ end
69
+
70
+ context "when the column type is :datetime" do
71
+ let(:datetime) { DateTime.current }
72
+ let(:integer) { datetime.to_time.to_i }
73
+
74
+ before { User.stub(:_protobuf_datetime_column?).and_return(true) }
75
+
76
+ it "converts the given value to an integer" do
77
+ User._protobuf_convert_columns_to_fields(:foo_datetime, datetime).should eq integer
78
+ end
79
+ end
80
+
81
+ context "when the column type is :time" do
82
+ let(:time) { Time.current }
83
+ let(:integer) { time.to_time.to_i }
84
+
85
+ before { User.stub(:_protobuf_time_column?).and_return(true) }
86
+
87
+ it "converts the given value to an integer" do
88
+ User._protobuf_convert_columns_to_fields(:foo_time, time).should eq integer
89
+ end
90
+ end
91
+
92
+ context "when the column type is :timestamp" do
93
+ let(:timestamp) { Time.current }
94
+ let(:integer) { timestamp.to_time.to_i }
95
+
96
+ before { User.stub(:_protobuf_timestamp_column?).and_return(true) }
97
+
98
+ it "converts the given value to an integer" do
99
+ User._protobuf_convert_columns_to_fields(:foo_timestamp, timestamp).should eq integer
100
+ end
101
+ end
102
+
103
+ context "when no conversion is necessary" do
104
+ let(:value) { "Foo" }
105
+
106
+ it "returns the given value" do
107
+ User._protobuf_convert_columns_to_fields(:foo, value).should eq value
108
+ end
109
+ end
110
+ end
111
+
112
+ describe "._protobuf_convert_fields_to_columns" do
113
+ let(:email_value) { "foo@test.co" }
114
+ let(:email_converter) { lambda { |value| value } }
115
+
116
+ before { User.stub(:_protobuf_field_converters).and_return({ :email => email_converter }) }
117
+
118
+ it "calls the field converter with the given value" do
119
+ email_converter.should_receive(:call).with(email_value)
120
+ User._protobuf_convert_fields_to_columns(:email, email_value)
121
+ end
122
+
123
+ context "and it's corresponding column type has a default converter" do
124
+ before { User.stub(:_protobuf_date_column?).and_return(true) }
125
+
126
+ it "calls the field converter with the given value" do
127
+ email_converter.should_receive(:call).with(email_value)
128
+ User._protobuf_convert_fields_to_columns(:email, email_value)
129
+ end
130
+ end
131
+
132
+ context "when the given field's corresponding column type is :date" do
133
+ let(:date) { Date.current }
134
+ let(:value) { date.to_time.to_i }
135
+
136
+ before { User.stub(:_protobuf_date_column?).and_return(true) }
137
+
138
+ it "converts the given value to a Date object" do
139
+ User._protobuf_convert_fields_to_columns(:foo_date, value).should eq date
140
+ end
141
+ end
142
+
143
+ context "when given field's corresponding the column type is :datetime" do
144
+ let(:datetime) { DateTime.current }
145
+ let(:value) { datetime.to_i }
146
+
147
+ before { User.stub(:_protobuf_datetime_column?).and_return(true) }
148
+
149
+ it "converts the given value to a DateTime object" do
150
+ User._protobuf_convert_fields_to_columns(:foo_datetime, value).should be_a(DateTime)
151
+ end
152
+
153
+ it "converts the given value to a DateTime object of the same value" do
154
+ User._protobuf_convert_fields_to_columns(:foo_datetime, value).should be_within(1).of(datetime)
155
+ end
156
+ end
157
+
158
+ context "when given field's corresponding the column type is :time" do
159
+ let(:time) { Time.current }
160
+ let(:value) { time.to_i }
161
+
162
+ before { User.stub(:_protobuf_time_column?).and_return(true) }
163
+
164
+ it "converts the given value to a Time object" do
165
+ User._protobuf_convert_fields_to_columns(:foo_time, value).should be_a(Time)
166
+ end
167
+
168
+ it "converts the given value to a Time object of the same value" do
169
+ User._protobuf_convert_fields_to_columns(:foo_time, value).should be_within(1).of(time)
170
+ end
171
+ end
172
+
173
+ context "when given field's corresponding the column type is :timestamp" do
174
+ let(:time) { Time.current }
175
+ let(:value) { time.to_i }
176
+
177
+ before { User.stub(:_protobuf_timestamp_column?).and_return(true) }
178
+
179
+ it "converts the given value to a Time object" do
180
+ User._protobuf_convert_fields_to_columns(:foo_time, value).should be_a(Time)
181
+ end
182
+
183
+ it "converts the given value to a Time object of the same value" do
184
+ User._protobuf_convert_fields_to_columns(:foo_timestamp, value).should be_within(1).of(time)
185
+ end
186
+ end
187
+
188
+ context "when no conversion is necessary" do
189
+ let(:value) { "Foo" }
190
+
191
+ it "returns the given value" do
192
+ User._protobuf_convert_fields_to_columns(:foo, value).should eq value
193
+ end
194
+ end
195
+ end
196
+
197
+ context "column type predicates" do
198
+ before { User.stub(:_protobuf_column_types).and_return(Hash.new) }
199
+ after { User.unstub(:_protobuf_column_types) }
200
+
201
+ describe "._protobuf_date_column?" do
202
+ before { User._protobuf_column_types[:date] = [ :foo_date ] }
203
+
204
+ context "when the column type is :date" do
205
+ it "is true" do
206
+ User._protobuf_date_column?(:foo_date).should be_true
207
+ end
208
+ end
209
+
210
+ context "when the column type is not :date" do
211
+ it "is false" do
212
+ User._protobuf_date_column?(:bar_date).should be_false
213
+ end
214
+ end
215
+ end
216
+
217
+ describe "._protobuf_datetime_column?" do
218
+ before { User._protobuf_column_types[:datetime] = [ :foo_datetime ] }
219
+
220
+ context "when the column type is :datetime" do
221
+ it "is true" do
222
+ User._protobuf_datetime_column?(:foo_datetime).should be_true
223
+ end
224
+ end
225
+
226
+ context "when the column type is not :datetime" do
227
+ it "is false" do
228
+ User._protobuf_datetime_column?(:bar_datetime).should be_false
229
+ end
230
+ end
231
+ end
232
+
233
+ describe "._protobuf_time_column?" do
234
+ before { User._protobuf_column_types[:time] = [ :foo_time ] }
235
+
236
+ context "when the column type is :time" do
237
+ it "is true" do
238
+ User._protobuf_time_column?(:foo_time).should be_true
239
+ end
240
+ end
241
+
242
+ context "when the column type is not :time" do
243
+ it "is false" do
244
+ User._protobuf_time_column?(:bar_time).should be_false
245
+ end
246
+ end
247
+ end
248
+
249
+ describe "._protobuf_timestamp_column?" do
250
+ before { User._protobuf_column_types[:timestamp] = [ :foo_timestamp ] }
251
+
252
+ context "when the column type is :timestamp" do
253
+ it "is true" do
254
+ User._protobuf_timestamp_column?(:foo_timestamp).should be_true
255
+ end
256
+ end
257
+
258
+ context "when the column type is not :timestamp" do
259
+ it "is false" do
260
+ User._protobuf_timestamp_column?(:bar_timestamp).should be_false
261
+ end
262
+ end
263
+ end
264
+ end
265
+ end
@@ -0,0 +1,131 @@
1
+ require 'spec_helper'
2
+
3
+ describe Protoable::Fields do
4
+ describe "._protobuf_map_columns" do
5
+ context "when the class has a table" do
6
+ let(:expected_column_names) {
7
+ User.columns.inject({}) do |hash, column|
8
+ hash[column.name.to_sym] = column
9
+ hash
10
+ end
11
+ }
12
+
13
+ let(:expected_column_types) {
14
+ User.columns.inject({}) do |hash, column|
15
+ hash[column.type.to_sym] ||= []
16
+ hash[column.type.to_sym] << column.name.to_sym
17
+ hash
18
+ end
19
+ }
20
+
21
+ it "maps columns by name" do
22
+ User._protobuf_columns.should eq expected_column_names
23
+ end
24
+
25
+ it "maps column names by column type" do
26
+ User._protobuf_column_types.should eq expected_column_types
27
+ end
28
+ end
29
+ end
30
+
31
+ describe ".convert_field" do
32
+ context "when the given converter is a hash" do
33
+ let(:method) { User.method(:convert_base64_to_string) }
34
+
35
+ before { User.convert_field :public_key, :from => :base64, :to => :string }
36
+
37
+ it "determines the method using the hash's :to and :from keys" do
38
+ User._protobuf_field_converters[:public_key].should eq method
39
+ end
40
+ end
41
+
42
+ context "when the given converter is a symbol" do
43
+ context "when the converter is not a defined method" do
44
+ let(:callable) { User.method(:convert_base64_to_string) }
45
+
46
+ before { User.convert_field :email, :base64 }
47
+
48
+ it "determines the method using the converter as the 'from' and the column type as the 'to'" do
49
+ User._protobuf_field_converters[:email].should eq callable
50
+ end
51
+ end
52
+
53
+ context "when the converter is a defined method" do
54
+ let(:callable) { User.method(:convert_email_to_lowercase) }
55
+
56
+ before { User.convert_field :email, :convert_email_to_lowercase }
57
+
58
+ it "creates a callable method object from the converter" do
59
+ User._protobuf_field_converters[:email].should eq callable
60
+ end
61
+ end
62
+ end
63
+
64
+ context "when the given converter is nil" do
65
+ it "raises an exception" do
66
+ expect { User.convert_field :email, nil }.to raise_exception(Protoable::FieldConverterError)
67
+ end
68
+ end
69
+
70
+ context "when the given converter is not callable" do
71
+ it "raises an exception" do
72
+ expect { User.convert_field :email, :foo }.to raise_exception(Protoable::FieldConverterError)
73
+ end
74
+ end
75
+
76
+ context "when the given converter is callable" do
77
+ let(:callable) { lambda { |value| value } }
78
+
79
+ before { User.convert_field :email, callable }
80
+
81
+ it "adds the given converter to list of field converters" do
82
+ User._protobuf_field_converters[:email].should eq callable
83
+ end
84
+ end
85
+ end
86
+
87
+ describe ".transform_column" do
88
+ context "when the given converter is a symbol" do
89
+ context "when the converter is not a defined method" do
90
+ it "raises an exception" do
91
+ expect { User.transform_column :name, :foo }.to raise_exception(Protoable::ColumnTransformerError)
92
+ end
93
+ end
94
+
95
+ context "when the converter is a defined method" do
96
+ let(:callable) { User.method(:extract_first_name) }
97
+
98
+ before { User.transform_column :first_name, :extract_first_name }
99
+
100
+ it "creates a callable method object from the converter" do
101
+ User._protobuf_column_transformers[:first_name].should eq callable
102
+ end
103
+ end
104
+ end
105
+
106
+ context "when the given converter is nil" do
107
+ it "raises an exception" do
108
+ expect { User.transform_column :name, nil }.to raise_exception(Protoable::ColumnTransformerError)
109
+ end
110
+ end
111
+
112
+ context "when the given converter is not callable" do
113
+ it "raises an exception" do
114
+ expect { User.transform_column :name, double(:not_callable) }.to raise_exception(Protoable::ColumnTransformerError)
115
+ end
116
+ end
117
+
118
+ context "when the given transformer is callable" do
119
+ let(:callable) { lambda { |proto| nil } }
120
+
121
+ before {
122
+ User.stub(:_protobuf_column_transformers).and_return(Hash.new)
123
+ User.transform_column :account_id, callable
124
+ }
125
+
126
+ it "adds the given converter to the list of protobuf field transformers" do
127
+ User._protobuf_column_transformers[:account_id] = callable
128
+ end
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,5 @@
1
+ require 'spec_helper'
2
+
3
+ describe Protoable::InheritableClassInstanceVariables do
4
+ pending
5
+ end
@@ -0,0 +1,158 @@
1
+ require 'spec_helper'
2
+
3
+ describe Protoable::Persistence 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) { Proto::User.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
+ attribute_fields[:email].should eq proto_hash[:email]
13
+ end
14
+
15
+ it "filters repeated fields" do
16
+ attribute_fields = User._filter_attribute_fields(proto)
17
+ attribute_fields.has_key?(:tags).should be_false
18
+ end
19
+
20
+ it "filters fields that map to protected attributes" do
21
+ User.stub(:protected_attributes).and_return([ "email" ])
22
+ attribute_fields = User._filter_attribute_fields(proto)
23
+ attribute_fields.has_key?(:email).should be_false
24
+ end
25
+
26
+ it "includes attributes that aren't fields, but have column transformers" do
27
+ User.stub(:_protobuf_column_transformers).and_return({ :account_id => :fetch_account_id })
28
+ attribute_fields = User._filter_attribute_fields(proto)
29
+ attribute_fields.has_key?(:account_id).should be_true
30
+ end
31
+ end
32
+
33
+ describe ".attributes_from_proto" do
34
+ context "when a column transformer is defined for the field" do
35
+ it "transforms the field value" do
36
+ attribute_fields = User.attributes_from_proto(proto)
37
+ attribute_fields[:first_name].should eq user_attributes[:first_name]
38
+ end
39
+ end
40
+
41
+ context "when column transformer is not defined for the field" do
42
+ before {
43
+ User.stub(:_protobuf_convert_fields_to_columns) do |key, value|
44
+ value
45
+ end
46
+ }
47
+
48
+ it "converts the field value" do
49
+ attribute_fields = User.attributes_from_proto(proto)
50
+ attribute_fields.should eq user_attributes
51
+ end
52
+ end
53
+ end
54
+
55
+ describe ".create_from_proto" do
56
+ it "initializes a new object with attributes from the given protobuf message" do
57
+ user = User.create_from_proto(proto)
58
+ attributes = user.attributes.slice("first_name", "last_name", "email")
59
+ attributes.should eq user_attributes.stringify_keys
60
+ end
61
+
62
+ context "when a block is given" do
63
+ it "yields to the block with attributes from the given protobuf message" do
64
+ yielded = nil
65
+
66
+ User.create_from_proto(proto) do |attributes|
67
+ yielded = "boom!"
68
+ end
69
+
70
+ yielded.should eq "boom!"
71
+ end
72
+ end
73
+
74
+ context "when the object is valid" do
75
+ it "saves the record" do
76
+ user = User.create_from_proto(proto)
77
+ user.persisted?.should be_true
78
+ end
79
+
80
+ context "when an error occurs while saving" do
81
+ before { User.any_instance.stub(:save!).and_raise(RuntimeError) }
82
+
83
+ it "raises an exception" do
84
+ expect { User.create_from_proto(proto) }.to raise_exception
85
+ end
86
+ end
87
+ end
88
+
89
+ context "when the object is not valid" do
90
+ before { User.any_instance.stub(:valid?).and_return(false) }
91
+
92
+ it "returns the new object, unsaved" do
93
+ user = User.create_from_proto(proto)
94
+ user.persisted?.should be_false
95
+ end
96
+ end
97
+ end
98
+
99
+ describe "#attributes_from_proto" do
100
+ it "gets attributes from the given protobuf message" do
101
+ User.should_receive(:attributes_from_proto).with(proto)
102
+ user.attributes_from_proto(proto)
103
+ end
104
+ end
105
+
106
+ describe "#destroy_from_proto" do
107
+ it "destroys the object" do
108
+ user.should_receive(:destroy)
109
+ user.destroy_from_proto
110
+ end
111
+ end
112
+
113
+ describe "#update_from_proto" do
114
+ it "updates the object with attributes from the given protobuf message" do
115
+ user.should_receive(:assign_attributes).with(user_attributes)
116
+ user.update_from_proto(proto)
117
+ end
118
+
119
+ context "when a block is given" do
120
+ it "yields to the block with attributes from the given protobuf message" do
121
+ yielded = nil
122
+
123
+ user.update_from_proto(proto) do |attributes|
124
+ yielded = "boom!"
125
+ end
126
+
127
+ yielded.should eq "boom!"
128
+ end
129
+ end
130
+
131
+ context "when the object is valid" do
132
+ before { user.stub(:valid?).and_return(true) }
133
+
134
+ context "when saving is successful" do
135
+ it "returns true" do
136
+ user.stub(:save!).and_return(true)
137
+ user.update_from_proto(proto).should be_true
138
+ end
139
+ end
140
+
141
+ context "when an error occurs while saving" do
142
+ before { user.stub(:save!).and_raise(RuntimeError) }
143
+
144
+ it "raises an exception" do
145
+ expect { user.update_from_proto }.to raise_exception
146
+ end
147
+ end
148
+ end
149
+
150
+ context "when the object is invalid" do
151
+ before { user.stub(:valid?).and_return(false) }
152
+
153
+ it "returns false" do
154
+ user.update_from_proto(proto).should be_false
155
+ end
156
+ end
157
+ end
158
+ end
@@ -0,0 +1,133 @@
1
+ require 'spec_helper'
2
+
3
+ describe Protoable::Serialization do
4
+ let(:protobuf_message) { ::Proto::User }
5
+
6
+ describe ".convert_column" do
7
+ context "when the given converter is a hash" do
8
+ let(:method) { User.method(:convert_base64_to_string) }
9
+
10
+ before { User.convert_column :public_key, :from => :base64, :to => :string }
11
+
12
+ it "determines the method using the hash's :to and :from keys" do
13
+ User._protobuf_column_converters[:public_key].should eq method
14
+ end
15
+ end
16
+
17
+ context "when the given converter is a symbol" do
18
+ context "when the converter is not a defined method" do
19
+ let(:callable) { User.method(:convert_base64_to_string) }
20
+
21
+ before { User.convert_column :email, :base64 }
22
+
23
+ it "determines the method using the converter as the 'from' and the column type as the 'to'" do
24
+ User._protobuf_column_converters[:email].should eq callable
25
+ end
26
+ end
27
+
28
+ context "when the converter is a defined method" do
29
+ let(:callable) { User.method(:convert_email_to_lowercase) }
30
+
31
+ before { User.convert_column :email, :convert_email_to_lowercase }
32
+
33
+ it "creates a callable method object from the converter" do
34
+ User._protobuf_column_converters[:email].should eq callable
35
+ end
36
+ end
37
+ end
38
+
39
+ context "when the given converter is nil" do
40
+ it "raises an exception" do
41
+ expect { User.convert_column :email, nil }.to raise_exception(Protoable::ColumnConverterError)
42
+ end
43
+ end
44
+
45
+ context "when the given converter is not callable" do
46
+ it "raises an exception" do
47
+ expect { User.convert_column :email, :foo }.to raise_exception(Protoable::ColumnConverterError)
48
+ end
49
+ end
50
+
51
+ context "when the given converter is callable" do
52
+ let(:callable) { lambda { |value| value } }
53
+
54
+ before { User.convert_column :email, callable }
55
+
56
+ it "adds the given converter to list of column converters" do
57
+ User._protobuf_column_converters[:email].should eq callable
58
+ end
59
+ end
60
+ end
61
+
62
+ describe ".protobuf_message" do
63
+ before { User.protobuf_message(protobuf_message) }
64
+
65
+ context "given a value" do
66
+ let(:protobuf_fields) { [ :name, :email, :tags ] }
67
+
68
+ it "sets .protobuf_fields" do
69
+ User.protobuf_fields.should =~ protobuf_fields
70
+ end
71
+
72
+ it "defines #to_proto" do
73
+ User.allocate.should respond_to :to_proto
74
+ end
75
+
76
+ it "defines #to_proto_hash" do
77
+ User.allocate.should respond_to :to_proto_hash
78
+ end
79
+ end
80
+
81
+ it "returns the protobuf message for this object" do
82
+ User.protobuf_message.should eq protobuf_message
83
+ end
84
+ end
85
+
86
+ context "when protobuf_message is defined" do
87
+ let(:attributes) { Hash.new }
88
+ let(:user) { User.new(attributes) }
89
+
90
+ before { User.protobuf_message(protobuf_message) }
91
+
92
+ describe "#protoable_attributes" do
93
+ let(:attributes) {
94
+ {
95
+ :first_name => "foo",
96
+ :last_name => "bar",
97
+ :email => "foo@test.co"
98
+ }
99
+ }
100
+ let(:protoable_attributes) { { :name => user.name, :email => user.email, :tags => nil } }
101
+
102
+ it "returns a hash of protobuf fields that this object has getters for" do
103
+ user.protoable_attributes.should eq protoable_attributes
104
+ end
105
+
106
+ it "converts attributes values for protobuf messages" do
107
+ user.should_receive(:_protobuf_convert_columns_to_fields).any_number_of_times
108
+ user.protoable_attributes
109
+ end
110
+ end
111
+
112
+ describe "#to_proto" do
113
+ let(:proto) { protobuf_message.new(proto_hash) }
114
+ let(:proto_hash) { { :name => "foo" } }
115
+
116
+ before { user.stub(:to_proto_hash).and_return(proto_hash) }
117
+
118
+ it "intializes a new protobuf message with attributes from #to_proto_hash" do
119
+ user.to_proto.should eq proto
120
+ end
121
+ end
122
+
123
+ describe "#to_proto_hash" do
124
+ let(:proto_hash) { { :name => "foo" } }
125
+
126
+ before { user.stub(:protoable_attributes).and_return(proto_hash) }
127
+
128
+ it "returns #protoable_attributes" do
129
+ user.to_proto_hash.should eq proto_hash
130
+ end
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,13 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+
4
+ require 'simplecov'
5
+ SimpleCov.start do
6
+ add_filter '/spec/'
7
+ end
8
+
9
+ Bundler.require(:default, :development, :test)
10
+
11
+ require 'support/db'
12
+ require 'support/models'
13
+ require 'support/protobuf'