rasti-form 3.0.0 → 5.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.
Files changed (43) hide show
  1. checksums.yaml +5 -5
  2. data/.ruby-version +1 -1
  3. data/.travis.yml +8 -11
  4. data/README.md +0 -1
  5. data/lib/rasti/form.rb +34 -129
  6. data/lib/rasti/form/errors.rb +7 -47
  7. data/lib/rasti/form/validable.rb +9 -3
  8. data/rasti-form.gemspec +3 -14
  9. data/spec/coverage_helper.rb +1 -3
  10. data/spec/minitest_helper.rb +1 -7
  11. data/spec/validations_spec.rb +301 -0
  12. metadata +11 -56
  13. data/lib/rasti/form/castable.rb +0 -25
  14. data/lib/rasti/form/formatable.rb +0 -19
  15. data/lib/rasti/form/types/array.rb +0 -54
  16. data/lib/rasti/form/types/boolean.rb +0 -42
  17. data/lib/rasti/form/types/enum.rb +0 -48
  18. data/lib/rasti/form/types/float.rb +0 -33
  19. data/lib/rasti/form/types/form.rb +0 -40
  20. data/lib/rasti/form/types/hash.rb +0 -39
  21. data/lib/rasti/form/types/integer.rb +0 -21
  22. data/lib/rasti/form/types/io.rb +0 -23
  23. data/lib/rasti/form/types/regexp.rb +0 -23
  24. data/lib/rasti/form/types/string.rb +0 -44
  25. data/lib/rasti/form/types/symbol.rb +0 -23
  26. data/lib/rasti/form/types/time.rb +0 -40
  27. data/lib/rasti/form/types/uuid.rb +0 -19
  28. data/lib/rasti/form/version.rb +0 -5
  29. data/spec/form_spec.rb +0 -350
  30. data/spec/types/array_spec.rb +0 -54
  31. data/spec/types/boolean_spec.rb +0 -24
  32. data/spec/types/enum_spec.rb +0 -28
  33. data/spec/types/float_spec.rb +0 -18
  34. data/spec/types/form_spec.rb +0 -41
  35. data/spec/types/hash_spec.rb +0 -20
  36. data/spec/types/integer_spec.rb +0 -18
  37. data/spec/types/io_spec.rb +0 -18
  38. data/spec/types/regexp_spec.rb +0 -18
  39. data/spec/types/string_formatted_spec.rb +0 -20
  40. data/spec/types/string_spec.rb +0 -16
  41. data/spec/types/symbol_spec.rb +0 -16
  42. data/spec/types/time_spec.rb +0 -25
  43. data/spec/types/uuid_spec.rb +0 -18
@@ -1,23 +0,0 @@
1
- module Rasti
2
- class Form
3
- module Types
4
- class IO
5
- class << self
6
-
7
- include Castable
8
-
9
- private
10
-
11
- def valid?(value)
12
- value.respond_to?(:read) && value.respond_to?(:write)
13
- end
14
-
15
- def transform(value)
16
- value
17
- end
18
-
19
- end
20
- end
21
- end
22
- end
23
- end
@@ -1,23 +0,0 @@
1
- module Rasti
2
- class Form
3
- module Types
4
- class Regexp
5
- class << self
6
-
7
- include Castable
8
-
9
- private
10
-
11
- def valid?(value)
12
- value.is_a?(::Regexp) || value.is_a?(::String)
13
- end
14
-
15
- def transform(value)
16
- value.is_a?(::Regexp) ? value.source : ::Regexp.compile(value).source
17
- end
18
-
19
- end
20
- end
21
- end
22
- end
23
- end
@@ -1,44 +0,0 @@
1
- module Rasti
2
- class Form
3
- module Types
4
- class String
5
-
6
- include Formatable
7
-
8
- class << self
9
-
10
- include Castable
11
-
12
- def [](format)
13
- new format
14
- end
15
-
16
- private
17
-
18
- def valid?(value)
19
- !value.nil? && value.respond_to?(:to_s)
20
- end
21
-
22
- def transform(value)
23
- value.to_s
24
- end
25
-
26
- end
27
-
28
- def to_s
29
- "#{self.class}[#{format.inspect}]"
30
- end
31
- alias_method :inspect, :to_s
32
-
33
- private
34
-
35
- attr_reader :format
36
-
37
- def initialize(format)
38
- @format = format.is_a?(String) ? ::Regexp.new(format) : format
39
- end
40
-
41
- end
42
- end
43
- end
44
- 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,19 +0,0 @@
1
- module Rasti
2
- class Form
3
- module Types
4
- class UUID
5
- class << self
6
-
7
- include Formatable
8
-
9
- private
10
-
11
- def format
12
- /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}+$/
13
- end
14
-
15
- end
16
- end
17
- end
18
- end
19
- end
@@ -1,5 +0,0 @@
1
- module Rasti
2
- class Form
3
- VERSION = '3.0.0'
4
- end
5
- end
data/spec/form_spec.rb DELETED
@@ -1,350 +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 error: #<Rasti::Form[]> {"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 error: #<Rasti::Form[]> {"boolean":["Invalid cast: \'x\' -> Rasti::Form::Types::Boolean"],"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 error: #<Rasti::Form[]> {\"range.min\":[\"Invalid cast: 'x' -> Rasti::Form::Types::Integer\"],\"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 error: #<Rasti::Form[]> {\"range.min\":[\"Invalid cast: 'x' -> Rasti::Form::Types::Integer\"],\"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 'Required' do
145
- form = build_form do
146
- attribute :text, Rasti::Form::Types::String
147
-
148
- def validate
149
- assert_present :text
150
- end
151
- end
152
-
153
- error = proc { form.new }.must_raise Rasti::Form::ValidationError
154
- error.message.must_equal 'Validation error: #<Rasti::Form[]> {"text":["not present"]}'
155
- end
156
-
157
- it 'Not empty string' do
158
- form = build_form do
159
- attribute :text, Rasti::Form::Types::String
160
-
161
- def validate
162
- assert_not_empty :text
163
- end
164
- end
165
-
166
- error = proc { form.new text: ' ' }.must_raise Rasti::Form::ValidationError
167
- error.message.must_equal 'Validation error: #<Rasti::Form[text: " "]> {"text":["is empty"]}'
168
- end
169
-
170
- it 'Not empty array' do
171
- form = build_form do
172
- attribute :array, Rasti::Form::Types::Array[Rasti::Form::Types::String]
173
-
174
- def validate
175
- assert_not_empty :array
176
- end
177
- end
178
-
179
- error = proc { form.new array: [] }.must_raise Rasti::Form::ValidationError
180
- error.message.must_equal 'Validation error: #<Rasti::Form[array: []]> {"array":["is empty"]}'
181
- end
182
-
183
- it 'Included in values list' do
184
- form = build_form do
185
- attribute :text, Rasti::Form::Types::String
186
-
187
- def validate
188
- assert_included_in :text, %w(value_1 value_2)
189
- end
190
- end
191
-
192
- error = proc { form.new text: 'xyz' }.must_raise Rasti::Form::ValidationError
193
- error.message.must_equal 'Validation error: #<Rasti::Form[text: "xyz"]> {"text":["not included in \'value_1\', \'value_2\'"]}'
194
- end
195
-
196
- it 'Time range' do
197
- form = build_form do
198
- attribute :from, Rasti::Form::Types::Time['%Y-%m-%d %H:%M:%S %Z']
199
- attribute :to, Rasti::Form::Types::Time['%Y-%m-%d %H:%M:%S %Z']
200
-
201
- def validate
202
- assert_time_range :from, :to
203
- end
204
- end
205
-
206
- from = '2018-01-01 15:30:00 +0000'
207
- to = '2018-01-01 03:10:00 +0000'
208
-
209
- error = proc { form.new from: from, to: to }.must_raise Rasti::Form::ValidationError
210
- error.message.must_equal "Validation error: #<Rasti::Form[from: #{from}, to: #{to}]> {\"from\":[\"invalid time range\"]}"
211
- end
212
-
213
- it 'Nested form' do
214
- form = build_form do
215
- attribute :range, Rasti::Form::Types::Form[min: Rasti::Form::Types::Integer, max: Rasti::Form::Types::Integer]
216
-
217
- def validate
218
- assert_present 'range.min'
219
- assert_present 'range.max'
220
- end
221
- end
222
-
223
- error = proc { form.new }.must_raise Rasti::Form::ValidationError
224
- error.message.must_equal 'Validation error: #<Rasti::Form[]> {"range.min":["not present"],"range.max":["not present"]}'
225
- end
226
-
227
- it 'Nested validation' do
228
- range = build_form do
229
- attribute :min, Rasti::Form::Types::Integer
230
- attribute :max, Rasti::Form::Types::Integer
231
-
232
- def validate
233
- assert :min, min < max, 'Min must be less than Max' if min && max
234
- end
235
- end
236
-
237
- form = build_form do
238
- attribute :range, Rasti::Form::Types::Form[range]
239
- end
240
-
241
- error = proc { form.new range: {min: 2, max: 1} }.must_raise Rasti::Form::ValidationError
242
- error.message.must_equal 'Validation error: #<Rasti::Form[]> {"range.min":["Min must be less than Max"]}'
243
- end
244
-
245
- end
246
-
247
- describe 'Comparable' do
248
-
249
- it 'Equivalency (==)' do
250
- point_1 = point_class.new x: 1, y: 2
251
- point_2 = point_subclass.new x: 1, y: 2
252
- point_3 = point_class.new x: 2, y: 1
253
-
254
- assert point_1 == point_2
255
- refute point_1 == point_3
256
- end
257
-
258
- it 'Equality (eql?)' do
259
- point_1 = point_class.new x: 1, y: 2
260
- point_2 = point_class.new x: 1, y: 2
261
- point_3 = point_subclass.new x: 1, y: 2
262
- point_4 = point_class.new x: 2, y: 1
263
-
264
- assert point_1.eql?(point_2)
265
- refute point_1.eql?(point_3)
266
- refute point_1.eql?(point_4)
267
- end
268
-
269
- it 'hash' do
270
- point_1 = point_class.new x: 1, y: 2
271
- point_2 = point_class.new x: 1, y: 2
272
- point_3 = point_subclass.new x: 1, y: 2
273
- point_4 = point_class.new x: 2, y: 1
274
-
275
- point_1.hash.must_equal point_2.hash
276
- point_1.hash.wont_equal point_3.hash
277
- point_1.hash.wont_equal point_4.hash
278
- end
279
-
280
- end
281
-
282
- describe 'Attributes' do
283
-
284
- let :address_class do
285
- Rasti::Form[
286
- street: Rasti::Form::Types::String,
287
- number: Rasti::Form::Types::Integer
288
- ]
289
- end
290
-
291
- let :contact_class do
292
- Rasti::Form[
293
- name: Rasti::Form::Types::String,
294
- age: Rasti::Form::Types::Integer,
295
- phones: Rasti::Form::Types::Hash[Rasti::Form::Types::Symbol, Rasti::Form::Types::Integer],
296
- addresses: Rasti::Form::Types::Array[Rasti::Form::Types::Form[address_class]],
297
- hobbies: Rasti::Form::Types::Array[Rasti::Form::Types::String]
298
- ]
299
- end
300
-
301
- let :attributes do
302
- {
303
- name: 'John',
304
- age: 24,
305
- phones: {
306
- office: 1234567890,
307
- house: 456456456
308
- },
309
- addresses: [
310
- {street: 'Lexington Avenue', number: 123},
311
- {street: 'Park Avenue', number: 456}
312
- ]
313
- }
314
- end
315
-
316
- it 'All (to_h)' do
317
- contact = contact_class.new attributes
318
-
319
- contact.attributes.must_equal attributes
320
- contact.to_h.must_equal attributes
321
- end
322
-
323
- it 'Only' do
324
- contact = contact_class.new attributes
325
-
326
- contact.attributes(only: [:name, :age]).must_equal name: attributes[:name],
327
- age: attributes[:age]
328
- end
329
-
330
- it 'Except' do
331
- contact = contact_class.new attributes
332
-
333
- contact.attributes(except: [:age, :addresses]).must_equal name: attributes[:name],
334
- phones: attributes[:phones]
335
- end
336
-
337
- end
338
-
339
- it 'to_s' do
340
- point_class.to_s.must_equal 'Rasti::Form[:x, :y]'
341
- point_class.new(x: '1', y: '2').to_s.must_equal '#<Rasti::Form[x: 1, y: 2]>'
342
- end
343
-
344
- it 'Subclass' do
345
- point = point_subclass.new x: 1, y: 2
346
- point.x.must_equal 1
347
- point.y.must_equal 2
348
- end
349
-
350
- end