modelish 0.3.0 → 1.0.0.pre.1
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 +7 -0
- data/.gitignore +2 -0
- data/.rspec +3 -1
- data/.ruby-version +1 -1
- data/.travis.yml +14 -0
- data/Appraisals +11 -0
- data/CHANGELOG.md +11 -0
- data/Gemfile +5 -1
- data/README.md +5 -0
- data/gemfiles/hashie_1.gemfile +7 -0
- data/gemfiles/hashie_2.gemfile +7 -0
- data/gemfiles/hashie_3.gemfile +7 -0
- data/lib/modelish/base.rb +108 -72
- data/lib/modelish/configuration.rb +9 -8
- data/lib/modelish/property_translations.rb +23 -11
- data/lib/modelish/property_types.rb +67 -50
- data/lib/modelish/validations.rb +70 -51
- data/lib/modelish/version.rb +3 -1
- data/lib/modelish.rb +3 -1
- data/modelish.gemspec +20 -15
- data/spec/modelish/base_spec.rb +203 -182
- data/spec/modelish/configuration_spec.rb +26 -19
- data/spec/modelish/property_translations_spec.rb +47 -39
- data/spec/modelish/property_types_spec.rb +53 -45
- data/spec/modelish/validations_spec.rb +296 -256
- data/spec/modelish_spec.rb +5 -3
- data/spec/spec_helper.rb +97 -2
- data/spec/support/property_examples.rb +15 -12
- data/spec/support/typed_property_examples.rb +39 -35
- data/spec/support/unknown_property_examples.rb +6 -4
- data/spec/support/validation_examples.rb +29 -23
- metadata +136 -103
- data/.ruby-gemset +0 -1
data/spec/modelish/base_spec.rb
CHANGED
@@ -1,109 +1,121 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'spec_helper'
|
2
4
|
|
3
|
-
describe Modelish::Base do
|
4
|
-
subject { model_class }
|
5
|
+
RSpec.describe Modelish::Base do
|
6
|
+
subject { model_class }
|
5
7
|
let(:model_class) { Class.new(Modelish::Base) }
|
6
8
|
|
7
9
|
let(:model) { model_class.new(init_options) }
|
8
10
|
let(:init_options) { nil }
|
9
11
|
let(:default_value) { nil }
|
10
12
|
|
11
|
-
it {
|
13
|
+
it { is_expected.to respond_to(:property) }
|
12
14
|
|
13
15
|
context 'without any properties' do
|
14
16
|
subject { model }
|
15
17
|
|
16
18
|
context 'when the model is initialized with an unknown property' do
|
17
|
-
let(:init_options) { {unknown_prop => 'whatever'} }
|
19
|
+
let(:init_options) { { unknown_prop => 'whatever' } }
|
18
20
|
let(:unknown_prop) { :foo }
|
19
21
|
|
20
|
-
context 'when ignore_unknown_properties is
|
22
|
+
context 'when class ignore_unknown_properties is set' do
|
21
23
|
before { model_class.ignore_unknown_properties = ignore_unknown_props }
|
22
24
|
after { model_class.reset }
|
23
25
|
|
24
|
-
|
26
|
+
it_behaves_like 'an unknown property handler'
|
25
27
|
end
|
26
28
|
|
27
|
-
context
|
28
|
-
before
|
29
|
+
context 'when global ignore_unknown_properties is set' do
|
30
|
+
before do
|
31
|
+
Modelish.configure do |config|
|
32
|
+
config.ignore_unknown_properties = ignore_unknown_props
|
33
|
+
end
|
34
|
+
end
|
29
35
|
after { Modelish.reset }
|
30
36
|
|
31
|
-
|
37
|
+
it_behaves_like 'an unknown property handler'
|
32
38
|
|
33
|
-
context 'when
|
34
|
-
before
|
39
|
+
context 'when class and global ignore_unknown_properties are set' do
|
40
|
+
before do
|
41
|
+
Modelish.configure do |config|
|
42
|
+
config.ignore_unknown_properties = !ignore_unknown_props
|
43
|
+
end
|
44
|
+
end
|
35
45
|
after { Modelish.reset }
|
36
46
|
|
37
|
-
before
|
47
|
+
before do
|
48
|
+
model_class.ignore_unknown_properties = ignore_unknown_props
|
49
|
+
end
|
38
50
|
after { model_class.reset }
|
39
51
|
|
40
|
-
|
52
|
+
it_behaves_like 'an unknown property handler'
|
41
53
|
end
|
42
54
|
end
|
43
55
|
|
44
56
|
context 'when ignore_unknown_properties has not been configured' do
|
45
|
-
it '
|
57
|
+
it 'raises an error' do
|
46
58
|
expect { subject }.to raise_error(NoMethodError)
|
47
59
|
end
|
48
60
|
end
|
49
61
|
end
|
50
62
|
|
51
|
-
describe
|
63
|
+
describe '#to_hash' do
|
52
64
|
subject { model.to_hash }
|
53
|
-
it {
|
65
|
+
it { is_expected.to be_empty }
|
54
66
|
end
|
55
67
|
end
|
56
68
|
|
57
|
-
context
|
69
|
+
context 'with simple property' do
|
58
70
|
before { model_class.property(property_name) }
|
59
71
|
|
60
72
|
let(:property_name) { :simple_property }
|
61
73
|
let(:property_value) { 'simple string value' }
|
62
74
|
|
63
|
-
|
64
|
-
|
75
|
+
it_behaves_like 'a modelish property'
|
76
|
+
it_behaves_like 'a valid model'
|
65
77
|
|
66
|
-
describe
|
67
|
-
let(:init_options) { {property_name => property_value} }
|
78
|
+
describe '#to_hash' do
|
79
|
+
let(:init_options) { { property_name => property_value } }
|
68
80
|
subject { model.to_hash }
|
69
81
|
|
70
|
-
|
71
|
-
it {
|
72
|
-
its(['simple_property']) {
|
82
|
+
its(:size) { is_expected.to eq(1) }
|
83
|
+
it { is_expected.to have_key(property_name.to_s) }
|
84
|
+
its(['simple_property']) { is_expected.to eq(property_value) }
|
73
85
|
end
|
74
86
|
end
|
75
87
|
|
76
|
-
context
|
77
|
-
before { model_class.property(property_name, :
|
88
|
+
context 'with property default value' do
|
89
|
+
before { model_class.property(property_name, default: default_value) }
|
78
90
|
|
79
91
|
let(:property_name) { :default_property }
|
80
92
|
let(:property_value) { 'non-default value' }
|
81
93
|
let(:default_value) { 42 }
|
82
94
|
|
83
|
-
|
84
|
-
|
95
|
+
it_behaves_like 'a modelish property'
|
96
|
+
it_behaves_like 'a valid model'
|
85
97
|
|
86
|
-
describe
|
98
|
+
describe '#to_hash' do
|
87
99
|
subject { model.to_hash }
|
88
100
|
|
89
|
-
context
|
90
|
-
|
91
|
-
it {
|
92
|
-
its([
|
101
|
+
context 'with default value' do
|
102
|
+
its(:size) { is_expected.to eq(1) }
|
103
|
+
it { is_expected.to have_key(property_name.to_s) }
|
104
|
+
its(['default_property']) { is_expected.to eq(default_value) }
|
93
105
|
end
|
94
106
|
|
95
107
|
context 'without default value' do
|
96
|
-
let(:init_options) { {property_name => property_value} }
|
108
|
+
let(:init_options) { { property_name => property_value } }
|
97
109
|
|
98
|
-
|
99
|
-
it {
|
100
|
-
its([
|
110
|
+
its(:size) { is_expected.to eq(1) }
|
111
|
+
it { is_expected.to have_key(property_name.to_s) }
|
112
|
+
its(['default_property']) { is_expected.to eq(property_value) }
|
101
113
|
end
|
102
114
|
end
|
103
115
|
end
|
104
116
|
|
105
|
-
context
|
106
|
-
before { model_class.property(to_name, :
|
117
|
+
context 'with translated property' do
|
118
|
+
before { model_class.property(to_name, from: from_name) }
|
107
119
|
|
108
120
|
let(:to_name) { :translated_property }
|
109
121
|
let(:from_name) { 'OldPropertyNAME' }
|
@@ -112,132 +124,134 @@ describe Modelish::Base do
|
|
112
124
|
subject { model }
|
113
125
|
|
114
126
|
context 'when there is one translation for the source property' do
|
115
|
-
|
127
|
+
it_behaves_like 'a modelish property' do
|
116
128
|
let(:property_name) { to_name }
|
117
129
|
end
|
118
130
|
|
119
|
-
it {
|
120
|
-
it {
|
131
|
+
it { is_expected.to_not respond_to(from_name) }
|
132
|
+
it { is_expected.to respond_to("#{from_name}=") }
|
121
133
|
|
122
|
-
describe
|
134
|
+
describe 'translated mutator' do
|
123
135
|
subject { model.send("#{from_name}=", property_value) }
|
124
136
|
|
125
|
-
it
|
126
|
-
expect { subject }.to change{model.send(to_name)}
|
137
|
+
it 'changes the property value' do
|
138
|
+
expect { subject }.to change { model.send(to_name) }
|
139
|
+
.from(nil).to(property_value)
|
127
140
|
end
|
128
141
|
end
|
129
142
|
|
130
|
-
|
143
|
+
it_behaves_like 'a valid model'
|
131
144
|
|
132
|
-
describe
|
145
|
+
describe '#to_hash' do
|
133
146
|
subject { model.to_hash }
|
134
147
|
|
135
|
-
context
|
136
|
-
let(:init_options) { {to_name => property_value} }
|
148
|
+
context 'when set from untranslated property name' do
|
149
|
+
let(:init_options) { { to_name => property_value } }
|
137
150
|
|
138
|
-
|
139
|
-
it {
|
140
|
-
its(['translated_property']) {
|
151
|
+
its(:size) { is_expected.to eq(1) }
|
152
|
+
it { is_expected.to have_key(to_name.to_s) }
|
153
|
+
its(['translated_property']) { is_expected.to eq(property_value) }
|
141
154
|
end
|
142
155
|
|
143
|
-
context
|
144
|
-
let(:init_options) { {from_name => property_value} }
|
156
|
+
context 'when set from the translation' do
|
157
|
+
let(:init_options) { { from_name => property_value } }
|
145
158
|
|
146
|
-
|
147
|
-
it {
|
148
|
-
its(['translated_property']) {
|
159
|
+
its(:size) { is_expected.to eq(1) }
|
160
|
+
it { is_expected.to have_key(to_name.to_s) }
|
161
|
+
its(['translated_property']) { is_expected.to eq(property_value) }
|
149
162
|
end
|
150
163
|
end
|
151
164
|
end
|
152
165
|
|
153
166
|
context 'when there are multiple translations for the source property' do
|
154
|
-
before { model_class.property(other_to_name, :
|
167
|
+
before { model_class.property(other_to_name, from: from_name) }
|
155
168
|
let(:other_to_name) { :my_other_prop }
|
156
169
|
|
157
|
-
|
170
|
+
it_behaves_like 'a modelish property' do
|
158
171
|
let(:property_name) { other_to_name }
|
159
172
|
end
|
160
173
|
|
161
|
-
|
174
|
+
it_behaves_like 'a modelish property' do
|
162
175
|
let(:property_name) { to_name }
|
163
176
|
end
|
164
177
|
|
165
|
-
|
178
|
+
it_behaves_like 'a valid model'
|
166
179
|
|
167
|
-
it {
|
168
|
-
it {
|
180
|
+
it { is_expected.to_not respond_to(from_name) }
|
181
|
+
it { is_expected.to respond_to("#{from_name}=") }
|
169
182
|
|
170
|
-
describe
|
183
|
+
describe 'translated mutator' do
|
171
184
|
subject { model.send("#{from_name}=", property_value) }
|
172
185
|
|
173
|
-
it
|
174
|
-
expect { subject }.to change{model.send(to_name)}
|
186
|
+
it 'changes the value of the first property' do
|
187
|
+
expect { subject }.to change { model.send(to_name) }
|
188
|
+
.from(nil).to(property_value)
|
175
189
|
end
|
176
190
|
|
177
|
-
it
|
178
|
-
expect { subject }.to change { model.send(other_to_name) }
|
191
|
+
it 'changes the value of the other property' do
|
192
|
+
expect { subject }.to change { model.send(other_to_name) }
|
193
|
+
.from(nil).to(property_value)
|
179
194
|
end
|
180
195
|
end
|
181
196
|
|
182
|
-
describe
|
197
|
+
describe '#to_hash' do
|
183
198
|
subject { model.to_hash }
|
184
199
|
|
185
200
|
context 'when initialized with first property' do
|
186
|
-
let(:init_options) { {to_name => property_value} }
|
201
|
+
let(:init_options) { { to_name => property_value } }
|
187
202
|
|
188
|
-
|
203
|
+
its(:size) { is_expected.to eq(2) }
|
189
204
|
|
190
|
-
it {
|
191
|
-
its(['translated_property']) {
|
205
|
+
it { is_expected.to have_key(to_name.to_s) }
|
206
|
+
its(['translated_property']) { is_expected.to eq(property_value) }
|
192
207
|
|
193
|
-
it {
|
194
|
-
its(['my_other_prop']) {
|
208
|
+
it { is_expected.to have_key(other_to_name.to_s) }
|
209
|
+
its(['my_other_prop']) { is_expected.to be_nil }
|
195
210
|
end
|
196
211
|
|
197
212
|
context 'when initialized with second property' do
|
198
|
-
let(:init_options) { {other_to_name => property_value} }
|
213
|
+
let(:init_options) { { other_to_name => property_value } }
|
199
214
|
|
200
|
-
|
215
|
+
its(:size) { is_expected.to eq(2) }
|
201
216
|
|
202
|
-
it {
|
203
|
-
its(['translated_property']) {
|
217
|
+
it { is_expected.to have_key(to_name.to_s) }
|
218
|
+
its(['translated_property']) { is_expected.to be_nil }
|
204
219
|
|
205
|
-
it {
|
206
|
-
its(['my_other_prop']) {
|
220
|
+
it { is_expected.to have_key(other_to_name.to_s) }
|
221
|
+
its(['my_other_prop']) { is_expected.to eq(property_value) }
|
207
222
|
end
|
208
223
|
|
209
224
|
context 'when initialized with translated property' do
|
210
|
-
let(:init_options) { {from_name => property_value} }
|
225
|
+
let(:init_options) { { from_name => property_value } }
|
211
226
|
|
212
227
|
context 'when there are no individual property initializations' do
|
228
|
+
its(:size) { is_expected.to eq(2) }
|
213
229
|
|
214
|
-
it {
|
230
|
+
it { is_expected.to have_key(to_name.to_s) }
|
231
|
+
its(['translated_property']) { is_expected.to eq(property_value) }
|
215
232
|
|
216
|
-
it {
|
217
|
-
its(['
|
218
|
-
|
219
|
-
it { should have_key(other_to_name.to_s) }
|
220
|
-
its(['my_other_prop']) { should == property_value }
|
233
|
+
it { is_expected.to have_key(other_to_name.to_s) }
|
234
|
+
its(['my_other_prop']) { is_expected.to eq(property_value) }
|
221
235
|
end
|
222
236
|
|
223
|
-
context 'when
|
237
|
+
context 'when the destination property is initialized' do
|
224
238
|
before { init_options[to_name] = other_value }
|
225
239
|
let(:other_value) { 'and now for something completely different' }
|
226
240
|
|
227
|
-
|
241
|
+
its(:size) { is_expected.to eq(2) }
|
228
242
|
|
229
|
-
it {
|
230
|
-
its(['translated_property']) {
|
243
|
+
it { is_expected.to have_key(to_name.to_s) }
|
244
|
+
its(['translated_property']) { is_expected.to eq(other_value) }
|
231
245
|
|
232
|
-
it {
|
233
|
-
its(['my_other_prop']) {
|
246
|
+
it { is_expected.to have_key(other_to_name.to_s) }
|
247
|
+
its(['my_other_prop']) { is_expected.to eq(property_value) }
|
234
248
|
end
|
235
249
|
end
|
236
250
|
end
|
237
251
|
end
|
238
252
|
end
|
239
253
|
|
240
|
-
context
|
254
|
+
context 'with typed property' do
|
241
255
|
before { model_class.property(property_name, options) }
|
242
256
|
|
243
257
|
subject { model }
|
@@ -249,94 +263,97 @@ describe Modelish::Base do
|
|
249
263
|
let(:valid_typed_value) { 42 }
|
250
264
|
let(:invalid_value) { '42.0' }
|
251
265
|
|
252
|
-
context
|
253
|
-
let(:options) { {:
|
266
|
+
context 'without default value' do
|
267
|
+
let(:options) { { type: property_type } }
|
254
268
|
let(:default_value) { nil }
|
255
269
|
|
256
|
-
context
|
257
|
-
|
258
|
-
|
270
|
+
context 'without init options' do
|
271
|
+
it_behaves_like 'a typed property', :my_int_property, Integer
|
272
|
+
it_behaves_like 'a valid model'
|
259
273
|
|
260
|
-
describe
|
274
|
+
describe '#to_hash' do
|
261
275
|
subject { model.to_hash }
|
262
276
|
|
263
|
-
|
264
|
-
it {
|
265
|
-
its(['my_int_property']) {
|
277
|
+
its(:size) { is_expected.to eq(1) }
|
278
|
+
it { is_expected.to have_key(property_name.to_s) }
|
279
|
+
its(['my_int_property']) { is_expected.to be_nil }
|
266
280
|
end
|
267
281
|
end
|
268
282
|
|
269
|
-
context
|
283
|
+
context 'with init options' do
|
270
284
|
let(:model) { model_class.new(property_name => valid_string) }
|
271
285
|
|
272
|
-
its(:my_int_property) {
|
273
|
-
its(:raw_my_int_property) {
|
286
|
+
its(:my_int_property) { is_expected.to eq(valid_typed_value) }
|
287
|
+
its(:raw_my_int_property) { is_expected.to eq(valid_string) }
|
274
288
|
|
275
|
-
|
289
|
+
it_behaves_like 'a valid model'
|
276
290
|
|
277
|
-
describe
|
291
|
+
describe '#to_hash' do
|
278
292
|
subject { model.to_hash }
|
279
293
|
|
280
|
-
|
281
|
-
it {
|
282
|
-
its(['my_int_property']) {
|
294
|
+
its(:size) { is_expected.to eq(1) }
|
295
|
+
it { is_expected.to have_key(property_name.to_s) }
|
296
|
+
its(['my_int_property']) { is_expected.to eq(valid_typed_value) }
|
283
297
|
end
|
284
298
|
end
|
285
299
|
end
|
286
300
|
|
287
|
-
context
|
288
|
-
let(:options) { {:
|
301
|
+
context 'with default value' do
|
302
|
+
let(:options) { { type: property_type, default: default_value } }
|
289
303
|
let(:default_value) { 0 }
|
290
304
|
|
291
|
-
|
305
|
+
it_behaves_like 'a typed property', :my_int_property, Integer
|
292
306
|
|
293
|
-
|
307
|
+
it_behaves_like 'a valid model'
|
294
308
|
|
295
|
-
describe
|
309
|
+
describe '#to_hash' do
|
296
310
|
subject { model.to_hash }
|
297
311
|
|
298
|
-
|
299
|
-
it {
|
300
|
-
its(['my_int_property']) {
|
312
|
+
its(:size) { is_expected.to eq(1) }
|
313
|
+
it { is_expected.to have_key(property_name.to_s) }
|
314
|
+
its(['my_int_property']) { is_expected.to eq(default_value) }
|
301
315
|
end
|
302
316
|
end
|
303
317
|
end
|
304
318
|
|
305
|
-
context
|
306
|
-
before { model_class.property(property_name, :
|
319
|
+
context 'with required property' do
|
320
|
+
before { model_class.property(property_name, required: true) }
|
307
321
|
|
308
322
|
let(:property_name) { :my_required_property }
|
309
323
|
let(:property_value) { 'a valid string' }
|
310
324
|
|
311
325
|
subject { model }
|
312
326
|
|
313
|
-
let(:init_options) { {property_name => property_value} }
|
327
|
+
let(:init_options) { { property_name => property_value } }
|
314
328
|
|
315
|
-
|
329
|
+
it_behaves_like 'a modelish property'
|
316
330
|
|
317
|
-
context
|
318
|
-
|
331
|
+
context 'when property value is not nil' do
|
332
|
+
it_behaves_like 'a valid model'
|
319
333
|
end
|
320
334
|
|
321
|
-
context
|
335
|
+
context 'when property value is nil' do
|
322
336
|
let(:property_value) { nil }
|
323
337
|
|
324
|
-
|
338
|
+
it_behaves_like 'a model with an invalid property' do
|
325
339
|
let(:error_count) { 1 }
|
326
340
|
end
|
327
341
|
end
|
328
342
|
|
329
|
-
context
|
343
|
+
context 'when property value is an empty string' do
|
330
344
|
let(:property_value) { ' ' }
|
331
345
|
|
332
|
-
|
346
|
+
it_behaves_like 'a model with an invalid property' do
|
333
347
|
let(:error_count) { 1 }
|
334
348
|
end
|
335
349
|
end
|
336
350
|
end
|
337
351
|
|
338
|
-
context
|
339
|
-
before
|
352
|
+
context 'with length-restricted property' do
|
353
|
+
before do
|
354
|
+
model_class.property(property_name, required: false,
|
355
|
+
max_length: max_length)
|
356
|
+
end
|
340
357
|
|
341
358
|
let(:property_name) { :my_required_property }
|
342
359
|
let(:property_value) { 'a' * (max_length - 1) }
|
@@ -344,145 +361,149 @@ describe Modelish::Base do
|
|
344
361
|
|
345
362
|
subject { model }
|
346
363
|
|
347
|
-
let(:init_options) { {property_name => property_value} }
|
364
|
+
let(:init_options) { { property_name => property_value } }
|
348
365
|
|
349
|
-
|
366
|
+
it_behaves_like 'a modelish property'
|
350
367
|
|
351
|
-
context
|
368
|
+
context 'when property value is nil' do
|
352
369
|
let(:property_value) { nil }
|
353
370
|
|
354
|
-
|
371
|
+
it_behaves_like 'a valid model'
|
355
372
|
end
|
356
373
|
|
357
|
-
context
|
358
|
-
|
374
|
+
context 'when property value is a valid string' do
|
375
|
+
it_behaves_like 'a valid model'
|
359
376
|
end
|
360
377
|
|
361
|
-
context
|
378
|
+
context 'when property value is too long' do
|
362
379
|
let(:property_value) { 'a' * (max_length + 1) }
|
363
380
|
|
364
|
-
|
381
|
+
it_behaves_like 'a model with an invalid property' do
|
365
382
|
let(:error_count) { 1 }
|
366
383
|
end
|
367
384
|
end
|
368
385
|
end
|
369
386
|
|
370
|
-
context
|
371
|
-
before
|
387
|
+
context 'with property that has validator block' do
|
388
|
+
before do
|
389
|
+
model_class.property(property_name, validator: validator_block)
|
390
|
+
end
|
372
391
|
|
373
392
|
let(:property_name) { :validated_property }
|
374
393
|
let(:validator_block) do
|
375
|
-
lambda
|
394
|
+
lambda do |val|
|
395
|
+
"#{property_name} must support to_hash" unless val.respond_to?(:to_hash)
|
396
|
+
end
|
376
397
|
end
|
377
|
-
let(:property_value) {
|
398
|
+
let(:property_value) { {} }
|
378
399
|
|
379
400
|
subject { model }
|
380
401
|
|
381
|
-
let(:init_options) { {property_name => property_value} }
|
402
|
+
let(:init_options) { { property_name => property_value } }
|
382
403
|
|
383
|
-
|
404
|
+
it_behaves_like 'a modelish property'
|
384
405
|
|
385
|
-
context
|
386
|
-
|
406
|
+
context 'when value is valid' do
|
407
|
+
it_behaves_like 'a valid model'
|
387
408
|
end
|
388
409
|
|
389
|
-
context
|
390
|
-
let(:property_value) {
|
410
|
+
context 'when value is invalid' do
|
411
|
+
let(:property_value) { [] }
|
391
412
|
|
392
|
-
|
413
|
+
it_behaves_like 'a model with an invalid property' do
|
393
414
|
let(:error_count) { 1 }
|
394
415
|
end
|
395
416
|
end
|
396
417
|
end
|
397
418
|
|
398
|
-
context
|
419
|
+
context 'with type-validated property' do
|
399
420
|
before { model_class.property(property_name, prop_options) }
|
400
421
|
|
401
|
-
let(:prop_options) { {:
|
422
|
+
let(:prop_options) { { type: Integer, validate_type: true } }
|
402
423
|
let(:property_name) { :strict_typed_property }
|
403
424
|
let(:property_value) { 42 }
|
404
425
|
|
405
426
|
subject { model }
|
406
427
|
|
407
|
-
let(:init_options) { {property_name => property_value} }
|
428
|
+
let(:init_options) { { property_name => property_value } }
|
408
429
|
|
409
|
-
|
430
|
+
it_behaves_like 'a modelish property'
|
410
431
|
|
411
|
-
context
|
432
|
+
context 'when value is nil' do
|
412
433
|
let(:property_value) { nil }
|
413
434
|
|
414
|
-
|
435
|
+
it_behaves_like 'a valid model'
|
415
436
|
end
|
416
437
|
|
417
|
-
context
|
438
|
+
context 'when value is valid' do
|
418
439
|
let(:property_value) { '42' }
|
419
440
|
|
420
|
-
|
441
|
+
it_behaves_like 'a valid model'
|
421
442
|
end
|
422
443
|
|
423
|
-
context
|
444
|
+
context 'when value is invalid' do
|
424
445
|
let(:property_value) { 'forty-two' }
|
425
446
|
|
426
|
-
|
447
|
+
it_behaves_like 'a model with an invalid property' do
|
427
448
|
let(:error_count) { 1 }
|
428
449
|
end
|
429
450
|
end
|
430
451
|
|
431
|
-
context
|
432
|
-
let(:prop_options) { {:
|
452
|
+
context 'with no property type' do
|
453
|
+
let(:prop_options) { { validate_type: true } }
|
433
454
|
|
434
|
-
context
|
455
|
+
context 'when value is nil' do
|
435
456
|
let(:property_value) { nil }
|
436
457
|
|
437
|
-
|
458
|
+
it_behaves_like 'a valid model'
|
438
459
|
end
|
439
460
|
|
440
|
-
context
|
461
|
+
context 'when value is not nil' do
|
441
462
|
let(:property_value) { Object.new }
|
442
463
|
|
443
|
-
|
464
|
+
it_behaves_like 'a valid model'
|
444
465
|
end
|
445
466
|
end
|
446
467
|
end
|
447
468
|
|
448
|
-
context
|
449
|
-
before do
|
450
|
-
model_class.property(property_name, :
|
451
|
-
:
|
452
|
-
:
|
453
|
-
:
|
469
|
+
context 'with multiple validations' do
|
470
|
+
before do
|
471
|
+
model_class.property(property_name, required: true,
|
472
|
+
max_length: 3,
|
473
|
+
type: Symbol,
|
474
|
+
validate_type: true)
|
454
475
|
end
|
455
476
|
|
456
|
-
let(:init_options) { {property_name => property_value} }
|
477
|
+
let(:init_options) { { property_name => property_value } }
|
457
478
|
|
458
479
|
let(:property_name) { :prop_with_many_validations }
|
459
480
|
|
460
|
-
context
|
481
|
+
context 'when value is valid' do
|
461
482
|
let(:property_value) { :foo }
|
462
483
|
|
463
|
-
|
484
|
+
it_behaves_like 'a valid model'
|
464
485
|
end
|
465
486
|
|
466
|
-
context
|
487
|
+
context 'when value is nil' do
|
467
488
|
let(:property_value) { nil }
|
468
489
|
|
469
|
-
|
490
|
+
it_behaves_like 'a model with an invalid property' do
|
470
491
|
let(:error_count) { 1 }
|
471
492
|
end
|
472
493
|
end
|
473
494
|
|
474
|
-
context
|
495
|
+
context 'when value is too long' do
|
475
496
|
let(:property_value) { :crazy_long_value }
|
476
497
|
|
477
|
-
|
498
|
+
it_behaves_like 'a model with an invalid property' do
|
478
499
|
let(:error_count) { 1 }
|
479
500
|
end
|
480
501
|
end
|
481
502
|
|
482
|
-
context
|
503
|
+
context 'when value is not a symbol' do
|
483
504
|
let(:property_value) { Object.new }
|
484
505
|
|
485
|
-
|
506
|
+
it_behaves_like 'a model with an invalid property' do
|
486
507
|
let(:error_count) { 1 }
|
487
508
|
end
|
488
509
|
end
|