rasti-form 3.1.2 → 6.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 +4 -4
- data/.github/workflows/ci.yml +36 -0
- data/README.md +6 -61
- data/lib/rasti/form/errors.rb +6 -52
- data/lib/rasti/form/validable.rb +10 -7
- data/lib/rasti/form.rb +40 -131
- data/rasti-form.gemspec +2 -12
- data/spec/coverage_helper.rb +1 -3
- data/spec/minitest_helper.rb +1 -7
- data/spec/validations_spec.rb +333 -0
- metadata +19 -48
- data/.travis.yml +0 -20
- data/lib/rasti/form/castable.rb +0 -25
- 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 -40
- 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 -7
- data/lib/rasti/form/version.rb +0 -5
- data/spec/form_spec.rb +0 -411
- 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
@@ -0,0 +1,333 @@
|
|
1
|
+
require 'minitest_helper'
|
2
|
+
|
3
|
+
describe Rasti::Form, 'Validations' do
|
4
|
+
|
5
|
+
def build_form(&block)
|
6
|
+
Class.new(Rasti::Form) do
|
7
|
+
class_eval(&block)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def assert_validation_error(expected_errors, &block)
|
12
|
+
error = proc { block.call }.must_raise Rasti::Form::ValidationError
|
13
|
+
error.errors.must_equal expected_errors
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'Validation error message' do
|
17
|
+
scope = Object.new
|
18
|
+
errors = {
|
19
|
+
x: ['not present'],
|
20
|
+
y: ['error 1', 'error 2']
|
21
|
+
}
|
22
|
+
|
23
|
+
error = Rasti::Form::ValidationError.new scope, errors
|
24
|
+
|
25
|
+
error.scope.must_equal scope
|
26
|
+
error.errors.must_equal errors
|
27
|
+
error.message.must_equal "Validation errors:\n- x: [\"not present\"]\n- y: [\"error 1\", \"error 2\"]"
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'Invalid attributes' do
|
31
|
+
assert_validation_error(z: ['unexpected attribute']) do
|
32
|
+
Rasti::Form[:x, :y].new z: 3
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'Not error' do
|
37
|
+
form = build_form do
|
38
|
+
attribute :text, T::String
|
39
|
+
|
40
|
+
def validate
|
41
|
+
assert_not_error :text do
|
42
|
+
raise 'invalid text' unless assigned? :text
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
proc { form.new text: 'text' }.must_be_silent
|
48
|
+
|
49
|
+
assert_validation_error(text: ['invalid text']) do
|
50
|
+
form.new
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe 'Present' do
|
55
|
+
|
56
|
+
let :form do
|
57
|
+
build_form do
|
58
|
+
attribute :number, T::Integer
|
59
|
+
|
60
|
+
def validate
|
61
|
+
assert_present :number
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'Success' do
|
67
|
+
proc { form.new number: 1 }.must_be_silent
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'Not assigned' do
|
71
|
+
assert_validation_error(number: ['not present']) do
|
72
|
+
form.new
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'Nil' do
|
77
|
+
assert_validation_error(number: ['not present']) do
|
78
|
+
form.new number: nil
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'Invalid cast' do
|
83
|
+
assert_validation_error(number: ['Invalid cast: true -> Rasti::Types::Integer']) do
|
84
|
+
form.new number: true
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'Invalid nested cast' do
|
89
|
+
range = build_form do
|
90
|
+
attribute :min, T::Integer
|
91
|
+
attribute :max, T::Integer
|
92
|
+
|
93
|
+
def validate
|
94
|
+
assert_range :min, :max
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
form = build_form do
|
99
|
+
attribute :range, T::Model[range]
|
100
|
+
|
101
|
+
def validate
|
102
|
+
assert_present :range
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
assert_validation_error('range.max' => ['not present']) do
|
107
|
+
form.new range: {min: 1}
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
it 'With default' do
|
112
|
+
form = build_form do
|
113
|
+
attribute :number, T::Integer, default: 1
|
114
|
+
|
115
|
+
def validate
|
116
|
+
assert_present :number
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
proc { form.new }.must_be_silent
|
121
|
+
|
122
|
+
assert_validation_error(number: ['not present']) do
|
123
|
+
form.new number: nil
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
end
|
128
|
+
|
129
|
+
describe 'Not present' do
|
130
|
+
|
131
|
+
let :form do
|
132
|
+
range = build_form do
|
133
|
+
attribute :min, T::Integer
|
134
|
+
attribute :max, T::Integer
|
135
|
+
|
136
|
+
def validate
|
137
|
+
assert_range :min, :max
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
build_form do
|
142
|
+
attribute :range, T::Model[range]
|
143
|
+
|
144
|
+
def validate
|
145
|
+
assert_not_present :range
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
it 'Success not assigned' do
|
151
|
+
proc { form.new }.must_be_silent
|
152
|
+
end
|
153
|
+
|
154
|
+
it 'Success with nil' do
|
155
|
+
proc { form.new range: nil }.must_be_silent
|
156
|
+
end
|
157
|
+
|
158
|
+
it 'Assigned' do
|
159
|
+
assert_validation_error(range: ['is present']) do
|
160
|
+
form.new range: {min: 1, max: 2}
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
it 'Invalid nested cast' do
|
165
|
+
assert_validation_error('range.max' => ['not present']) do
|
166
|
+
form.new range: {min: 1}
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
end
|
171
|
+
|
172
|
+
describe 'Not empty' do
|
173
|
+
|
174
|
+
it 'Must be present' do
|
175
|
+
form = build_form do
|
176
|
+
attribute :text, T::String
|
177
|
+
|
178
|
+
def validate
|
179
|
+
assert_not_empty :text
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
proc { form.new text: 'text' }.must_be_silent
|
184
|
+
|
185
|
+
assert_validation_error(text: ['not present']) do
|
186
|
+
form.new text: nil
|
187
|
+
end
|
188
|
+
|
189
|
+
assert_validation_error(text: ['not present']) do
|
190
|
+
form.new
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
it 'String' do
|
195
|
+
form = build_form do
|
196
|
+
attribute :text, T::String
|
197
|
+
|
198
|
+
def validate
|
199
|
+
assert_not_empty :text
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
proc { form.new text: 'text' }.must_be_silent
|
204
|
+
|
205
|
+
assert_validation_error(text: ['is empty']) do
|
206
|
+
form.new text: ' '
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
it 'Array' do
|
211
|
+
form = build_form do
|
212
|
+
attribute :array, T::Array[T::String]
|
213
|
+
|
214
|
+
def validate
|
215
|
+
assert_not_empty :array
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
proc { form.new array: ['text'] }.must_be_silent
|
220
|
+
|
221
|
+
assert_validation_error(array: ['is empty']) do
|
222
|
+
form.new array: []
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
it 'Hash' do
|
227
|
+
form = build_form do
|
228
|
+
attribute :hash, T::Hash[T::String, T::String]
|
229
|
+
|
230
|
+
def validate
|
231
|
+
assert_not_empty :hash
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
proc { form.new hash: {key: 'value'} }.must_be_silent
|
236
|
+
|
237
|
+
assert_validation_error(hash: ['is empty']) do
|
238
|
+
form.new hash: {}
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
end
|
243
|
+
|
244
|
+
it 'Included in values list' do
|
245
|
+
form = build_form do
|
246
|
+
attribute :text, T::String
|
247
|
+
|
248
|
+
def validate
|
249
|
+
assert_included_in :text, %w(value_1 value_2)
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
proc { form.new text: 'value_1' }.must_be_silent
|
254
|
+
|
255
|
+
assert_validation_error(text: ['not included in "value_1", "value_2"']) do
|
256
|
+
form.new text: 'xyz'
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
it 'Time range' do
|
261
|
+
form = build_form do
|
262
|
+
attribute :from, T::Time['%Y-%m-%d %H:%M:%S']
|
263
|
+
attribute :to, T::Time['%Y-%m-%d %H:%M:%S']
|
264
|
+
|
265
|
+
def validate
|
266
|
+
assert_range :from, :to
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
from = '2018-01-01 03:10:00'
|
271
|
+
to = '2018-01-01 15:30:00'
|
272
|
+
|
273
|
+
proc { form.new from: from, to: to }.must_be_silent
|
274
|
+
|
275
|
+
assert_validation_error(from: ['invalid range']) do
|
276
|
+
form.new from: to, to: from
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
280
|
+
it 'Nested validation' do
|
281
|
+
range = build_form do
|
282
|
+
attribute :min, T::Integer
|
283
|
+
attribute :max, T::Integer
|
284
|
+
|
285
|
+
def validate
|
286
|
+
assert_range :min, :max
|
287
|
+
end
|
288
|
+
end
|
289
|
+
|
290
|
+
form = build_form do
|
291
|
+
attribute :range, T::Model[range]
|
292
|
+
end
|
293
|
+
|
294
|
+
proc { form.new range: {min: 1, max: 2} }.must_be_silent
|
295
|
+
|
296
|
+
assert_validation_error('range.min' => ['invalid range']) do
|
297
|
+
form.new range: {min: 2, max: 1}
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
301
|
+
describe 'Validations Precedence' do
|
302
|
+
|
303
|
+
let(:form) do
|
304
|
+
build_form do
|
305
|
+
attribute :limit, T::Integer
|
306
|
+
|
307
|
+
def validate
|
308
|
+
assert :limit, limit < 10, 'invalid limit'
|
309
|
+
end
|
310
|
+
end
|
311
|
+
end
|
312
|
+
|
313
|
+
it '1) Validate unexpected attributes' do
|
314
|
+
assert_validation_error(id: ["unexpected attribute"]) do
|
315
|
+
form.new id: '123'
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
319
|
+
it '2) Validate attributes casting' do
|
320
|
+
assert_validation_error(limit: ["Invalid cast: 'pepe' -> Rasti::Types::Integer"]) do
|
321
|
+
form.new limit: 'pepe'
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
325
|
+
it '3) Run custom validations' do
|
326
|
+
assert_validation_error(limit: ["invalid limit"]) do
|
327
|
+
form.new limit: 500
|
328
|
+
end
|
329
|
+
end
|
330
|
+
|
331
|
+
end
|
332
|
+
|
333
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rasti-form
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 6.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gabriel Naiman
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-04-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: multi_require
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '1.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rasti-model
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '2.0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '2.0'
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: rake
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -136,51 +150,22 @@ extensions: []
|
|
136
150
|
extra_rdoc_files: []
|
137
151
|
files:
|
138
152
|
- ".coveralls.yml"
|
153
|
+
- ".github/workflows/ci.yml"
|
139
154
|
- ".gitignore"
|
140
155
|
- ".ruby-gemset"
|
141
156
|
- ".ruby-version"
|
142
|
-
- ".travis.yml"
|
143
157
|
- Gemfile
|
144
158
|
- LICENSE.txt
|
145
159
|
- README.md
|
146
160
|
- Rakefile
|
147
161
|
- lib/rasti-form.rb
|
148
162
|
- lib/rasti/form.rb
|
149
|
-
- lib/rasti/form/castable.rb
|
150
163
|
- lib/rasti/form/errors.rb
|
151
|
-
- lib/rasti/form/types/array.rb
|
152
|
-
- lib/rasti/form/types/boolean.rb
|
153
|
-
- lib/rasti/form/types/enum.rb
|
154
|
-
- lib/rasti/form/types/float.rb
|
155
|
-
- lib/rasti/form/types/form.rb
|
156
|
-
- lib/rasti/form/types/hash.rb
|
157
|
-
- lib/rasti/form/types/integer.rb
|
158
|
-
- lib/rasti/form/types/io.rb
|
159
|
-
- lib/rasti/form/types/regexp.rb
|
160
|
-
- lib/rasti/form/types/string.rb
|
161
|
-
- lib/rasti/form/types/symbol.rb
|
162
|
-
- lib/rasti/form/types/time.rb
|
163
|
-
- lib/rasti/form/types/uuid.rb
|
164
164
|
- lib/rasti/form/validable.rb
|
165
|
-
- lib/rasti/form/version.rb
|
166
165
|
- rasti-form.gemspec
|
167
166
|
- spec/coverage_helper.rb
|
168
|
-
- spec/form_spec.rb
|
169
167
|
- spec/minitest_helper.rb
|
170
|
-
- spec/
|
171
|
-
- spec/types/boolean_spec.rb
|
172
|
-
- spec/types/enum_spec.rb
|
173
|
-
- spec/types/float_spec.rb
|
174
|
-
- spec/types/form_spec.rb
|
175
|
-
- spec/types/hash_spec.rb
|
176
|
-
- spec/types/integer_spec.rb
|
177
|
-
- spec/types/io_spec.rb
|
178
|
-
- spec/types/regexp_spec.rb
|
179
|
-
- spec/types/string_formatted_spec.rb
|
180
|
-
- spec/types/string_spec.rb
|
181
|
-
- spec/types/symbol_spec.rb
|
182
|
-
- spec/types/time_spec.rb
|
183
|
-
- spec/types/uuid_spec.rb
|
168
|
+
- spec/validations_spec.rb
|
184
169
|
homepage: https://github.com/gabynaiman/rasti-form
|
185
170
|
licenses:
|
186
171
|
- MIT
|
@@ -206,19 +191,5 @@ specification_version: 4
|
|
206
191
|
summary: Forms validations and type casting
|
207
192
|
test_files:
|
208
193
|
- spec/coverage_helper.rb
|
209
|
-
- spec/form_spec.rb
|
210
194
|
- spec/minitest_helper.rb
|
211
|
-
- spec/
|
212
|
-
- spec/types/boolean_spec.rb
|
213
|
-
- spec/types/enum_spec.rb
|
214
|
-
- spec/types/float_spec.rb
|
215
|
-
- spec/types/form_spec.rb
|
216
|
-
- spec/types/hash_spec.rb
|
217
|
-
- spec/types/integer_spec.rb
|
218
|
-
- spec/types/io_spec.rb
|
219
|
-
- spec/types/regexp_spec.rb
|
220
|
-
- spec/types/string_formatted_spec.rb
|
221
|
-
- spec/types/string_spec.rb
|
222
|
-
- spec/types/symbol_spec.rb
|
223
|
-
- spec/types/time_spec.rb
|
224
|
-
- spec/types/uuid_spec.rb
|
195
|
+
- spec/validations_spec.rb
|
data/.travis.yml
DELETED
data/lib/rasti/form/castable.rb
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
module Rasti
|
2
|
-
class Form
|
3
|
-
module Castable
|
4
|
-
|
5
|
-
def cast(value)
|
6
|
-
if valid? value
|
7
|
-
transform! value
|
8
|
-
else
|
9
|
-
raise CastError.new self, value
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
private
|
14
|
-
|
15
|
-
def transform!(value)
|
16
|
-
transform value
|
17
|
-
rescue MultiCastError, ValidationError => ex
|
18
|
-
raise ex
|
19
|
-
rescue
|
20
|
-
raise CastError.new self, value
|
21
|
-
end
|
22
|
-
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
@@ -1,54 +0,0 @@
|
|
1
|
-
module Rasti
|
2
|
-
class Form
|
3
|
-
module Types
|
4
|
-
class Array
|
5
|
-
|
6
|
-
include Castable
|
7
|
-
|
8
|
-
attr_reader :type
|
9
|
-
|
10
|
-
def self.[](type)
|
11
|
-
new type
|
12
|
-
end
|
13
|
-
|
14
|
-
def to_s
|
15
|
-
"#{self.class}[#{type}]"
|
16
|
-
end
|
17
|
-
alias_method :inspect, :to_s
|
18
|
-
|
19
|
-
private
|
20
|
-
|
21
|
-
def initialize(type)
|
22
|
-
@type = type
|
23
|
-
end
|
24
|
-
|
25
|
-
def valid?(value)
|
26
|
-
value.is_a? ::Array
|
27
|
-
end
|
28
|
-
|
29
|
-
def transform(value)
|
30
|
-
result = []
|
31
|
-
errors = {}
|
32
|
-
|
33
|
-
value.each_with_index do |e,i|
|
34
|
-
index = i + 1
|
35
|
-
begin
|
36
|
-
result << type.cast(e)
|
37
|
-
rescue ValidationError => error
|
38
|
-
error.errors.each do |k,v|
|
39
|
-
errors["#{index}.#{k}"] = v
|
40
|
-
end
|
41
|
-
rescue => error
|
42
|
-
errors[index] = [error.message]
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
raise MultiCastError.new(self, value, errors) unless errors.empty?
|
47
|
-
|
48
|
-
result
|
49
|
-
end
|
50
|
-
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
@@ -1,42 +0,0 @@
|
|
1
|
-
module Rasti
|
2
|
-
class Form
|
3
|
-
module Types
|
4
|
-
class Boolean
|
5
|
-
class << self
|
6
|
-
|
7
|
-
include Castable
|
8
|
-
|
9
|
-
TRUE_FORMAT = /^t(rue)?$/i
|
10
|
-
FALSE_FORMAT = /^f(alse)?$/i
|
11
|
-
|
12
|
-
private
|
13
|
-
|
14
|
-
def valid?(value)
|
15
|
-
boolean?(value) || valid_string?(value)
|
16
|
-
end
|
17
|
-
|
18
|
-
def transform(value)
|
19
|
-
boolean?(value) ? value : true_string?(value)
|
20
|
-
end
|
21
|
-
|
22
|
-
def boolean?(value)
|
23
|
-
value == true || value == false
|
24
|
-
end
|
25
|
-
|
26
|
-
def valid_string?(value)
|
27
|
-
value.is_a?(::String) && (true_string?(value) || false_string?(value))
|
28
|
-
end
|
29
|
-
|
30
|
-
def true_string?(value)
|
31
|
-
!!value.match(TRUE_FORMAT)
|
32
|
-
end
|
33
|
-
|
34
|
-
def false_string?(value)
|
35
|
-
!!value.match(FALSE_FORMAT)
|
36
|
-
end
|
37
|
-
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
@@ -1,48 +0,0 @@
|
|
1
|
-
module Rasti
|
2
|
-
class Form
|
3
|
-
module Types
|
4
|
-
class Enum
|
5
|
-
|
6
|
-
include Castable
|
7
|
-
|
8
|
-
attr_reader :values
|
9
|
-
|
10
|
-
def self.[](*values)
|
11
|
-
new values
|
12
|
-
end
|
13
|
-
|
14
|
-
def to_s
|
15
|
-
"#{self.class}[#{values.map(&:inspect).join(', ')}]"
|
16
|
-
end
|
17
|
-
alias_method :inspect, :to_s
|
18
|
-
|
19
|
-
private
|
20
|
-
|
21
|
-
def initialize(values)
|
22
|
-
@values = values.map(&:to_s)
|
23
|
-
define_getters
|
24
|
-
end
|
25
|
-
|
26
|
-
def valid?(value)
|
27
|
-
values.include? String.cast(value)
|
28
|
-
rescue
|
29
|
-
false
|
30
|
-
end
|
31
|
-
|
32
|
-
def transform(value)
|
33
|
-
String.cast value
|
34
|
-
end
|
35
|
-
|
36
|
-
def define_getters
|
37
|
-
values.each do |value|
|
38
|
-
getter_name = value.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2').gsub(/([a-z])([A-Z])/, '\1_\2').downcase
|
39
|
-
define_singleton_method getter_name do
|
40
|
-
value
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
@@ -1,33 +0,0 @@
|
|
1
|
-
module Rasti
|
2
|
-
class Form
|
3
|
-
module Types
|
4
|
-
class Float
|
5
|
-
class << self
|
6
|
-
|
7
|
-
include Castable
|
8
|
-
|
9
|
-
FORMAT = /^(\d+\.)?\d+$/
|
10
|
-
|
11
|
-
private
|
12
|
-
|
13
|
-
def valid?(value)
|
14
|
-
!value.nil? && (valid_string?(value) || transformable?(value))
|
15
|
-
end
|
16
|
-
|
17
|
-
def transform(value)
|
18
|
-
value.to_f
|
19
|
-
end
|
20
|
-
|
21
|
-
def valid_string?(value)
|
22
|
-
value.is_a?(::String) && value.match(FORMAT)
|
23
|
-
end
|
24
|
-
|
25
|
-
def transformable?(value)
|
26
|
-
!value.is_a?(::String) && value.respond_to?(:to_f)
|
27
|
-
end
|
28
|
-
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
@@ -1,40 +0,0 @@
|
|
1
|
-
module Rasti
|
2
|
-
class Form
|
3
|
-
module Types
|
4
|
-
class Form
|
5
|
-
|
6
|
-
include Castable
|
7
|
-
|
8
|
-
attr_reader :form_class
|
9
|
-
|
10
|
-
def self.[](*args)
|
11
|
-
new *args
|
12
|
-
end
|
13
|
-
|
14
|
-
def to_s
|
15
|
-
"#{self.class}[#{form_class}]"
|
16
|
-
end
|
17
|
-
alias_method :inspect, :to_s
|
18
|
-
|
19
|
-
private
|
20
|
-
|
21
|
-
def initialize(form)
|
22
|
-
@form_class = case
|
23
|
-
when form.is_a?(::Hash) then Rasti::Form[form]
|
24
|
-
when form.is_a?(Class) && form.ancestors.include?(Rasti::Form) then form
|
25
|
-
else raise ArgumentError, "Invalid form specification: #{form.inspect}"
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def valid?(value)
|
30
|
-
value.is_a? ::Hash
|
31
|
-
end
|
32
|
-
|
33
|
-
def transform(value)
|
34
|
-
form_class.new value
|
35
|
-
end
|
36
|
-
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|