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.
- checksums.yaml +5 -5
- data/.ruby-version +1 -1
- data/.travis.yml +8 -11
- data/README.md +0 -1
- data/lib/rasti/form.rb +34 -129
- data/lib/rasti/form/errors.rb +7 -47
- data/lib/rasti/form/validable.rb +9 -3
- data/rasti-form.gemspec +3 -14
- data/spec/coverage_helper.rb +1 -3
- data/spec/minitest_helper.rb +1 -7
- data/spec/validations_spec.rb +301 -0
- metadata +11 -56
- data/lib/rasti/form/castable.rb +0 -25
- data/lib/rasti/form/formatable.rb +0 -19
- data/lib/rasti/form/types/array.rb +0 -54
- data/lib/rasti/form/types/boolean.rb +0 -42
- data/lib/rasti/form/types/enum.rb +0 -48
- data/lib/rasti/form/types/float.rb +0 -33
- data/lib/rasti/form/types/form.rb +0 -40
- data/lib/rasti/form/types/hash.rb +0 -39
- data/lib/rasti/form/types/integer.rb +0 -21
- data/lib/rasti/form/types/io.rb +0 -23
- data/lib/rasti/form/types/regexp.rb +0 -23
- data/lib/rasti/form/types/string.rb +0 -44
- data/lib/rasti/form/types/symbol.rb +0 -23
- data/lib/rasti/form/types/time.rb +0 -40
- data/lib/rasti/form/types/uuid.rb +0 -19
- data/lib/rasti/form/version.rb +0 -5
- data/spec/form_spec.rb +0 -350
- data/spec/types/array_spec.rb +0 -54
- data/spec/types/boolean_spec.rb +0 -24
- data/spec/types/enum_spec.rb +0 -28
- data/spec/types/float_spec.rb +0 -18
- data/spec/types/form_spec.rb +0 -41
- data/spec/types/hash_spec.rb +0 -20
- data/spec/types/integer_spec.rb +0 -18
- data/spec/types/io_spec.rb +0 -18
- data/spec/types/regexp_spec.rb +0 -18
- data/spec/types/string_formatted_spec.rb +0 -20
- data/spec/types/string_spec.rb +0 -16
- data/spec/types/symbol_spec.rb +0 -16
- data/spec/types/time_spec.rb +0 -25
- data/spec/types/uuid_spec.rb +0 -18
data/lib/rasti/form/types/io.rb
DELETED
@@ -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
|
data/lib/rasti/form/version.rb
DELETED
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
|