rasti-form 3.1.2 → 4.0.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.
@@ -1,40 +0,0 @@
1
- module Rasti
2
- class Form
3
- module Types
4
- class String
5
- class << self
6
-
7
- include Castable
8
-
9
- def [](format)
10
- Class.new(self) do
11
- @format = format.is_a?(::String) ? ::Regexp.new(format) : format
12
- end
13
- end
14
-
15
- def to_s
16
- name || "#{superclass.name}[#{format.inspect}]"
17
- end
18
- alias_method :inspect, :to_s
19
-
20
- private
21
-
22
- attr_reader :format
23
-
24
- def valid?(value)
25
- !value.nil? && value.respond_to?(:to_s) && valid_format?(value)
26
- end
27
-
28
- def valid_format?(value)
29
- format.nil? || !value.to_s.match(format).nil?
30
- end
31
-
32
- def transform(value)
33
- value.to_s
34
- end
35
-
36
- end
37
- end
38
- end
39
- end
40
- end
@@ -1,23 +0,0 @@
1
- module Rasti
2
- class Form
3
- module Types
4
- class Symbol
5
- class << self
6
-
7
- include Castable
8
-
9
- private
10
-
11
- def valid?(value)
12
- !value.nil? && (value.respond_to?(:to_sym) || value.respond_to?(:to_s))
13
- end
14
-
15
- def transform(value)
16
- value.respond_to?(:to_sym) ? value.to_sym : value.to_s.to_sym
17
- end
18
-
19
- end
20
- end
21
- end
22
- end
23
- end
@@ -1,40 +0,0 @@
1
- module Rasti
2
- class Form
3
- module Types
4
- class Time
5
-
6
- include Castable
7
-
8
- attr_reader :format
9
-
10
- def self.[](format)
11
- new format
12
- end
13
-
14
- def to_s
15
- "#{self.class}['#{format}']"
16
- end
17
- alias_method :inspect, :to_s
18
-
19
- private
20
-
21
- def initialize(format)
22
- @format = format
23
- end
24
-
25
- def valid?(value)
26
- value.is_a?(::String) || value.respond_to?(:to_time)
27
- end
28
-
29
- def transform(value)
30
- value.is_a?(::String) ? string_to_time(value) : value.to_time
31
- end
32
-
33
- def string_to_time(value)
34
- ::Time.strptime(value, format)
35
- end
36
-
37
- end
38
- end
39
- end
40
- end
@@ -1,7 +0,0 @@
1
- module Rasti
2
- class Form
3
- module Types
4
- UUID = String[/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}+$/]
5
- end
6
- end
7
- end
@@ -1,5 +0,0 @@
1
- module Rasti
2
- class Form
3
- VERSION = '3.1.2'
4
- end
5
- end
data/spec/form_spec.rb DELETED
@@ -1,411 +0,0 @@
1
- require 'minitest_helper'
2
-
3
- describe Rasti::Form do
4
-
5
- let(:point_class) { Rasti::Form[x: Rasti::Form::Types::Integer, y: Rasti::Form::Types::Integer] }
6
-
7
- let(:point_subclass) { Class.new point_class }
8
-
9
- def build_form(&block)
10
- Class.new(Rasti::Form) do
11
- class_eval(&block)
12
- end
13
- end
14
-
15
- describe 'Initialization' do
16
-
17
- it 'All attributes' do
18
- point = point_class.new x: 1, y: 2
19
- point.x.must_equal 1
20
- point.y.must_equal 2
21
- point.assigned?(:x).must_equal true
22
- point.assigned?(:y).must_equal true
23
- end
24
-
25
- it 'Some attributes' do
26
- point = point_class.new x: 1
27
- point.x.must_equal 1
28
- point.y.must_be_nil
29
- point.assigned?(:x).must_equal true
30
- point.assigned?(:y).must_equal false
31
- end
32
-
33
- it 'Whitout attributes' do
34
- point = point_class.new
35
- point.x.must_be_nil
36
- point.y.must_be_nil
37
- point.assigned?(:x).must_equal false
38
- point.assigned?(:y).must_equal false
39
- end
40
-
41
- it 'Invalid attributes' do
42
- error = proc { point_class.new z: 3 }.must_raise Rasti::Form::ValidationError
43
- error.message.must_equal "Validation errors:\n- z: [\"unexpected attribute\"]"
44
- end
45
-
46
- describe 'Casting' do
47
-
48
- it 'Attribute' do
49
- form = build_form do
50
- attribute :text, Rasti::Form::Types::String
51
- end
52
-
53
- f = form.new text: 123
54
- f.text.must_equal "123"
55
- end
56
-
57
- it 'Nested attributes' do
58
- form = build_form do
59
- attribute :range, Rasti::Form::Types::Form[min: Rasti::Form::Types::Integer, max: Rasti::Form::Types::Integer]
60
- end
61
-
62
- f = form.new range: {min: '1', max: '10'}
63
- f.range.min.must_equal 1
64
- f.range.max.must_equal 10
65
- end
66
-
67
- it 'Nested form' do
68
- range = build_form do
69
- attribute :min, Rasti::Form::Types::Integer
70
- attribute :max, Rasti::Form::Types::Integer
71
- end
72
-
73
- form = build_form do
74
- attribute :range, Rasti::Form::Types::Form[range]
75
- end
76
-
77
- f = form.new range: {min: '1', max: '10'}
78
- f.range.min.must_equal 1
79
- f.range.max.must_equal 10
80
- end
81
-
82
- it 'Invalid attributes' do
83
- form = build_form do
84
- attribute :boolean, Rasti::Form::Types::Boolean
85
- attribute :number, Rasti::Form::Types::Integer
86
- end
87
-
88
- error = proc { form.new boolean: 'x', number: 'y' }.must_raise Rasti::Form::ValidationError
89
- error.message.must_equal "Validation errors:\n- boolean: [\"Invalid cast: \'x\' -> Rasti::Form::Types::Boolean\"]\n- number: [\"Invalid cast: \'y\' -> Rasti::Form::Types::Integer\"]"
90
- end
91
-
92
- it 'Invalid nested attributes' do
93
- form = build_form do
94
- attribute :range, Rasti::Form::Types::Form[min: Rasti::Form::Types::Integer, max: Rasti::Form::Types::Integer]
95
- end
96
-
97
- error = proc { form.new range: {min: 'x', max: 'y'} }.must_raise Rasti::Form::ValidationError
98
- error.message.must_equal "Validation errors:\n- range.min: [\"Invalid cast: 'x' -> Rasti::Form::Types::Integer\"]\n- range.max: [\"Invalid cast: 'y' -> Rasti::Form::Types::Integer\"]"
99
- end
100
-
101
- it 'Invalid form attributes' do
102
- range = build_form do
103
- attribute :min, Rasti::Form::Types::Integer
104
- attribute :max, Rasti::Form::Types::Integer
105
- end
106
-
107
- form = build_form do
108
- attribute :range, Rasti::Form::Types::Form[range]
109
- end
110
-
111
- error = proc { form.new range: {min: 'x', max: 'y'} }.must_raise Rasti::Form::ValidationError
112
- error.message.must_equal "Validation errors:\n- range.min: [\"Invalid cast: 'x' -> Rasti::Form::Types::Integer\"]\n- range.max: [\"Invalid cast: 'y' -> Rasti::Form::Types::Integer\"]"
113
- end
114
-
115
- end
116
-
117
- end
118
-
119
- describe 'Defaults' do
120
-
121
- it 'Value' do
122
- form = build_form do
123
- attribute :text, Rasti::Form::Types::String, default: 'xyz'
124
- end
125
-
126
- f = form.new
127
- f.text.must_equal 'xyz'
128
- end
129
-
130
- it 'Block' do
131
- form = build_form do
132
- attribute :time_1, Rasti::Form::Types::Time['%F']
133
- attribute :time_2, Rasti::Form::Types::Time['%F'], default: ->(f) { f.time_1 }
134
- end
135
-
136
- f = form.new time_1: Time.now
137
- f.time_2.must_equal f.time_1
138
- end
139
-
140
- end
141
-
142
- describe 'Validations' do
143
-
144
- it 'Not error' do
145
- form = build_form do
146
- attribute :text, Rasti::Form::Types::String
147
-
148
- def validate
149
- assert_not_error :text do
150
- raise 'Invalid text' if text.nil?
151
- end
152
- end
153
- end
154
-
155
- proc { form.new text: 'text' }.must_be_silent
156
-
157
- error = proc { form.new }.must_raise Rasti::Form::ValidationError
158
- error.message.must_equal "Validation errors:\n- text: [\"Invalid text\"]"
159
- end
160
-
161
- it 'Required' do
162
- form = build_form do
163
- attribute :text, Rasti::Form::Types::String
164
-
165
- def validate
166
- assert_present :text
167
- end
168
- end
169
-
170
- proc { form.new text: 'text' }.must_be_silent
171
-
172
- error = proc { form.new }.must_raise Rasti::Form::ValidationError
173
- error.message.must_equal "Validation errors:\n- text: [\"not present\"]"
174
- end
175
-
176
- it 'Required when cast failed' do
177
- form = build_form do
178
- attribute :number, Rasti::Form::Types::Integer
179
-
180
- def validate
181
- assert_present :number
182
- end
183
- end
184
-
185
- proc { form.new number: 1 }.must_be_silent
186
-
187
- error = proc { form.new number: 'text' }.must_raise Rasti::Form::ValidationError
188
- error.message.must_equal "Validation errors:\n- number: [\"Invalid cast: 'text' -> Rasti::Form::Types::Integer\"]"
189
- end
190
-
191
- it 'Not required' do
192
- form = build_form do
193
- attribute :text, Rasti::Form::Types::String
194
-
195
- def validate
196
- assert_not_present :text
197
- end
198
- end
199
-
200
- proc { form.new }.must_be_silent
201
-
202
- error = proc { form.new text: 'text' }.must_raise Rasti::Form::ValidationError
203
- error.message.must_equal "Validation errors:\n- text: [\"is present\"]"
204
- end
205
-
206
- it 'Not empty string' do
207
- form = build_form do
208
- attribute :text, Rasti::Form::Types::String
209
-
210
- def validate
211
- assert_not_empty :text
212
- end
213
- end
214
-
215
- proc { form.new text: 'text' }.must_be_silent
216
-
217
- error = proc { form.new text: ' ' }.must_raise Rasti::Form::ValidationError
218
- error.message.must_equal "Validation errors:\n- text: [\"is empty\"]"
219
- end
220
-
221
- it 'Not empty array' do
222
- form = build_form do
223
- attribute :array, Rasti::Form::Types::Array[Rasti::Form::Types::String]
224
-
225
- def validate
226
- assert_not_empty :array
227
- end
228
- end
229
-
230
- proc { form.new array: ['text'] }.must_be_silent
231
-
232
- error = proc { form.new array: [] }.must_raise Rasti::Form::ValidationError
233
- error.message.must_equal "Validation errors:\n- array: [\"is empty\"]"
234
- end
235
-
236
- it 'Included in values list' do
237
- form = build_form do
238
- attribute :text, Rasti::Form::Types::String
239
-
240
- def validate
241
- assert_included_in :text, %w(value_1 value_2)
242
- end
243
- end
244
-
245
- proc { form.new text: 'value_1' }.must_be_silent
246
-
247
- error = proc { form.new text: 'xyz' }.must_raise Rasti::Form::ValidationError
248
- error.message.must_equal "Validation errors:\n- text: [\"not included in \'value_1\', \'value_2\'\"]"
249
- end
250
-
251
- it 'Time range' do
252
- form = build_form do
253
- attribute :from, Rasti::Form::Types::Time['%Y-%m-%d %H:%M:%S %Z']
254
- attribute :to, Rasti::Form::Types::Time['%Y-%m-%d %H:%M:%S %Z']
255
-
256
- def validate
257
- assert_time_range :from, :to
258
- end
259
- end
260
-
261
- from = Time.parse '2018-01-01 03:10:00'
262
- to = Time.parse '2018-01-01 15:30:00'
263
-
264
- proc { form.new from: from, to: to }.must_be_silent
265
-
266
- error = proc { form.new from: to.to_s, to: from.to_s }.must_raise Rasti::Form::ValidationError
267
- error.message.must_equal "Validation errors:\n- from: [\"invalid time range\"]"
268
- end
269
-
270
- it 'Nested form' do
271
- form = build_form do
272
- attribute :range, Rasti::Form::Types::Form[min: Rasti::Form::Types::Integer, max: Rasti::Form::Types::Integer]
273
-
274
- def validate
275
- assert_present 'range.min'
276
- assert_present 'range.max'
277
- end
278
- end
279
-
280
- proc { form.new range: {min: 1, max: 2} }.must_be_silent
281
-
282
- error = proc { form.new }.must_raise Rasti::Form::ValidationError
283
- error.message.must_equal "Validation errors:\n- range.min: [\"not present\"]\n- range.max: [\"not present\"]"
284
- end
285
-
286
- it 'Nested validation' do
287
- range = build_form do
288
- attribute :min, Rasti::Form::Types::Integer
289
- attribute :max, Rasti::Form::Types::Integer
290
-
291
- def validate
292
- assert :min, min < max, 'Min must be less than Max' if min && max
293
- end
294
- end
295
-
296
- form = build_form do
297
- attribute :range, Rasti::Form::Types::Form[range]
298
- end
299
-
300
- proc { form.new range: {min: 1, max: 2} }.must_be_silent
301
-
302
- error = proc { form.new range: {min: 2, max: 1} }.must_raise Rasti::Form::ValidationError
303
- error.message.must_equal "Validation errors:\n- range.min: [\"Min must be less than Max\"]"
304
- end
305
-
306
- end
307
-
308
- describe 'Comparable' do
309
-
310
- it 'Equivalency (==)' do
311
- point_1 = point_class.new x: 1, y: 2
312
- point_2 = point_subclass.new x: 1, y: 2
313
- point_3 = point_class.new x: 2, y: 1
314
-
315
- assert point_1 == point_2
316
- refute point_1 == point_3
317
- end
318
-
319
- it 'Equality (eql?)' do
320
- point_1 = point_class.new x: 1, y: 2
321
- point_2 = point_class.new x: 1, y: 2
322
- point_3 = point_subclass.new x: 1, y: 2
323
- point_4 = point_class.new x: 2, y: 1
324
-
325
- assert point_1.eql?(point_2)
326
- refute point_1.eql?(point_3)
327
- refute point_1.eql?(point_4)
328
- end
329
-
330
- it 'hash' do
331
- point_1 = point_class.new x: 1, y: 2
332
- point_2 = point_class.new x: 1, y: 2
333
- point_3 = point_subclass.new x: 1, y: 2
334
- point_4 = point_class.new x: 2, y: 1
335
-
336
- point_1.hash.must_equal point_2.hash
337
- point_1.hash.wont_equal point_3.hash
338
- point_1.hash.wont_equal point_4.hash
339
- end
340
-
341
- end
342
-
343
- describe 'Attributes' do
344
-
345
- let :address_class do
346
- Rasti::Form[
347
- street: Rasti::Form::Types::String,
348
- number: Rasti::Form::Types::Integer
349
- ]
350
- end
351
-
352
- let :contact_class do
353
- Rasti::Form[
354
- name: Rasti::Form::Types::String,
355
- age: Rasti::Form::Types::Integer,
356
- phones: Rasti::Form::Types::Hash[Rasti::Form::Types::Symbol, Rasti::Form::Types::Integer],
357
- addresses: Rasti::Form::Types::Array[Rasti::Form::Types::Form[address_class]],
358
- hobbies: Rasti::Form::Types::Array[Rasti::Form::Types::String]
359
- ]
360
- end
361
-
362
- let :attributes do
363
- {
364
- name: 'John',
365
- age: 24,
366
- phones: {
367
- office: 1234567890,
368
- house: 456456456
369
- },
370
- addresses: [
371
- {street: 'Lexington Avenue', number: 123},
372
- {street: 'Park Avenue', number: 456}
373
- ]
374
- }
375
- end
376
-
377
- it 'All (to_h)' do
378
- contact = contact_class.new attributes
379
-
380
- contact.attributes.must_equal attributes
381
- contact.to_h.must_equal attributes
382
- end
383
-
384
- it 'Only' do
385
- contact = contact_class.new attributes
386
-
387
- contact.attributes(only: [:name, :age]).must_equal name: attributes[:name],
388
- age: attributes[:age]
389
- end
390
-
391
- it 'Except' do
392
- contact = contact_class.new attributes
393
-
394
- contact.attributes(except: [:age, :addresses]).must_equal name: attributes[:name],
395
- phones: attributes[:phones]
396
- end
397
-
398
- end
399
-
400
- it 'to_s' do
401
- point_class.to_s.must_equal 'Rasti::Form[:x, :y]'
402
- point_class.new(x: '1', y: '2').to_s.must_equal '#<Rasti::Form[x: 1, y: 2]>'
403
- end
404
-
405
- it 'Subclass' do
406
- point = point_subclass.new x: 1, y: 2
407
- point.x.must_equal 1
408
- point.y.must_equal 2
409
- end
410
-
411
- end