formeze 4.1.0 → 4.2.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/CHANGES.md +6 -0
- data/formeze.gemspec +1 -1
- data/lib/formeze/errors.rb +11 -0
- data/lib/formeze/field.rb +155 -0
- data/lib/formeze/form.rb +5 -0
- data/lib/formeze/form_data.rb +23 -0
- data/lib/formeze/labels.rb +13 -0
- data/lib/formeze/presence.rb +11 -0
- data/lib/formeze/validation.rb +39 -0
- data/lib/formeze.rb +11 -242
- metadata +10 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 959c1584612e08ca4e490f77a71bef8e2f2be9c1db827dc2903335a7f8a340b2
|
4
|
+
data.tar.gz: 60d9b150269c308824e72282e5ea55b5bdb369f04cfe7120dec8f9a7764157bd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d19f682f89a2222e8043d9a4a3569ef8e977cf33070723e655a4e6268b2bce45e5b410608db0a8648731a4be55774fe7d89ca15d63da2ac7c7247bdba23c4e9d
|
7
|
+
data.tar.gz: fe373bbd667d964054c625e7d188721222f02d384de318184296a3fef6ed85da96443c1834649349792f33a6320e69ac29ad933b2b6e3d1a013233f6a067b30d
|
data/CHANGES.md
CHANGED
data/formeze.gemspec
CHANGED
@@ -0,0 +1,155 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Formeze::Field
|
4
|
+
include Formeze::Presence
|
5
|
+
|
6
|
+
attr_reader :name
|
7
|
+
|
8
|
+
def initialize(name, **options)
|
9
|
+
@name, @options = name, options
|
10
|
+
end
|
11
|
+
|
12
|
+
def validate_all(values, form)
|
13
|
+
size = 0
|
14
|
+
|
15
|
+
values.each do |value|
|
16
|
+
if String === value
|
17
|
+
validate(value, form)
|
18
|
+
else
|
19
|
+
validate_file(value, form)
|
20
|
+
|
21
|
+
size += value.size
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
form.add_error(self, :too_large, 'is too large') if maxsize? && size > maxsize
|
26
|
+
end
|
27
|
+
|
28
|
+
def validate(value, form)
|
29
|
+
value = Formeze.scrub(value, @options[:scrub])
|
30
|
+
|
31
|
+
if blank?(value)
|
32
|
+
form.add_error(self, :required, 'is required') if required?
|
33
|
+
|
34
|
+
value = blank_value if blank_value?
|
35
|
+
else
|
36
|
+
form.add_error(self, :not_multiline, 'cannot contain newlines') if !multiline? && value.lines.count > 1
|
37
|
+
|
38
|
+
form.add_error(self, :too_long, 'is too long') if too_long?(value)
|
39
|
+
|
40
|
+
form.add_error(self, :too_short, 'is too short') if too_short?(value)
|
41
|
+
|
42
|
+
form.add_error(self, :no_match, 'is invalid') if no_match?(value)
|
43
|
+
|
44
|
+
form.add_error(self, :bad_value, 'is invalid') if values? && !values.include?(value)
|
45
|
+
end
|
46
|
+
|
47
|
+
value = Array(form.send(name)).push(value) if multiple?
|
48
|
+
|
49
|
+
form.send(:"#{name}=", value)
|
50
|
+
end
|
51
|
+
|
52
|
+
def validate_file(object, form)
|
53
|
+
unless acceptable_file?(object)
|
54
|
+
form.add_error(self, :not_accepted, 'is not an accepted file type')
|
55
|
+
end
|
56
|
+
|
57
|
+
object = Array(form.send(name)).push(object) if multiple?
|
58
|
+
|
59
|
+
form.send(:"#{name}=", object)
|
60
|
+
end
|
61
|
+
|
62
|
+
BINARY = MIME::Types['application/octet-stream'].first
|
63
|
+
|
64
|
+
def acceptable_file?(object)
|
65
|
+
type = MIME::Types[object.content_type].first
|
66
|
+
|
67
|
+
types = MIME::Types.type_for(object.original_filename)
|
68
|
+
|
69
|
+
if type == BINARY
|
70
|
+
types.any? { |type| accept.include?(type) }
|
71
|
+
else
|
72
|
+
accept.include?(type) && types.include?(type)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def key
|
77
|
+
@key ||= @name.to_s
|
78
|
+
end
|
79
|
+
|
80
|
+
def key_required?
|
81
|
+
@options.fetch(:key_required) { true }
|
82
|
+
end
|
83
|
+
|
84
|
+
def label
|
85
|
+
@options.fetch(:label) { Formeze::Labels.translate(name) }
|
86
|
+
end
|
87
|
+
|
88
|
+
def required?
|
89
|
+
@options.fetch(:required) { true }
|
90
|
+
end
|
91
|
+
|
92
|
+
def multiline?
|
93
|
+
@options.fetch(:multiline) { false }
|
94
|
+
end
|
95
|
+
|
96
|
+
def multiple?
|
97
|
+
@options.fetch(:multiple) { false }
|
98
|
+
end
|
99
|
+
|
100
|
+
def maxsize?
|
101
|
+
@options.key?(:maxsize)
|
102
|
+
end
|
103
|
+
|
104
|
+
def maxsize
|
105
|
+
@options.fetch(:maxsize)
|
106
|
+
end
|
107
|
+
|
108
|
+
def accept
|
109
|
+
@accept ||= @options.fetch(:accept).split(',').flat_map { |type| MIME::Types[type] }
|
110
|
+
end
|
111
|
+
|
112
|
+
def too_long?(value)
|
113
|
+
value.chars.count > @options.fetch(:maxlength) { 64 }
|
114
|
+
end
|
115
|
+
|
116
|
+
def too_short?(value)
|
117
|
+
@options.key?(:minlength) && value.chars.count < @options.fetch(:minlength)
|
118
|
+
end
|
119
|
+
|
120
|
+
def no_match?(value)
|
121
|
+
@options.key?(:pattern) && value !~ @options[:pattern]
|
122
|
+
end
|
123
|
+
|
124
|
+
def blank_value?
|
125
|
+
@options.key?(:blank)
|
126
|
+
end
|
127
|
+
|
128
|
+
def blank_value
|
129
|
+
@options.fetch(:blank)
|
130
|
+
end
|
131
|
+
|
132
|
+
def values?
|
133
|
+
@options.key?(:values)
|
134
|
+
end
|
135
|
+
|
136
|
+
def values
|
137
|
+
@options.fetch(:values)
|
138
|
+
end
|
139
|
+
|
140
|
+
def defined_if?
|
141
|
+
@options.key?(:defined_if)
|
142
|
+
end
|
143
|
+
|
144
|
+
def defined_if
|
145
|
+
@options.fetch(:defined_if)
|
146
|
+
end
|
147
|
+
|
148
|
+
def defined_unless?
|
149
|
+
@options.key?(:defined_unless)
|
150
|
+
end
|
151
|
+
|
152
|
+
def defined_unless
|
153
|
+
@options.fetch(:defined_unless)
|
154
|
+
end
|
155
|
+
end
|
data/lib/formeze/form.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'cgi'
|
2
|
+
|
3
|
+
module Formeze::FormData
|
4
|
+
class CGI < ::CGI
|
5
|
+
def env_table
|
6
|
+
@options[:request].env
|
7
|
+
end
|
8
|
+
|
9
|
+
def stdinput
|
10
|
+
@options[:request].body.tap do |body|
|
11
|
+
body.rewind if body.respond_to?(:rewind)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.parse(input)
|
17
|
+
if input.is_a?(String)
|
18
|
+
CGI.parse(input)
|
19
|
+
else
|
20
|
+
CGI.new(request: input).params
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Formeze::Validation
|
4
|
+
include Formeze::Presence
|
5
|
+
|
6
|
+
def initialize(field, **kwargs, &block)
|
7
|
+
@field = field
|
8
|
+
|
9
|
+
@error = kwargs[:error] || :invalid
|
10
|
+
|
11
|
+
@precondition = kwargs[:if]
|
12
|
+
|
13
|
+
@block = block
|
14
|
+
end
|
15
|
+
|
16
|
+
def validates?(form)
|
17
|
+
@precondition ? form.instance_eval(&@precondition) : true
|
18
|
+
end
|
19
|
+
|
20
|
+
def field_value?(form)
|
21
|
+
present?(form.send(@field.name))
|
22
|
+
end
|
23
|
+
|
24
|
+
def field_errors?(form)
|
25
|
+
form.errors_on?(@field.name)
|
26
|
+
end
|
27
|
+
|
28
|
+
def validate(form)
|
29
|
+
if validates?(form) && field_value?(form) && !field_errors?(form)
|
30
|
+
return_value = if @block.arity == 1
|
31
|
+
@block.call(form.send(@field.name))
|
32
|
+
else
|
33
|
+
form.instance_eval(&@block)
|
34
|
+
end
|
35
|
+
|
36
|
+
form.add_error(@field, @error, 'is invalid') unless return_value
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/lib/formeze.rb
CHANGED
@@ -1,210 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
require 'cgi'
|
3
2
|
|
4
3
|
module Formeze
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
def blank?(string)
|
13
|
-
string !~ REGEXP
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
private_constant :Presence
|
18
|
-
|
19
|
-
class Field
|
20
|
-
include Presence
|
21
|
-
|
22
|
-
attr_reader :name
|
23
|
-
|
24
|
-
def initialize(name, **options)
|
25
|
-
@name, @options = name, options
|
26
|
-
end
|
27
|
-
|
28
|
-
def validate_all(values, form)
|
29
|
-
size = 0
|
30
|
-
|
31
|
-
values.each do |value|
|
32
|
-
if String === value
|
33
|
-
validate(value, form)
|
34
|
-
else
|
35
|
-
validate_file(value, form)
|
36
|
-
|
37
|
-
size += value.size
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
form.add_error(self, error(:too_large, 'is too large')) if maxsize? && size > maxsize
|
42
|
-
end
|
43
|
-
|
44
|
-
def validate(value, form)
|
45
|
-
value = Formeze.scrub(value, @options[:scrub])
|
46
|
-
|
47
|
-
if blank?(value)
|
48
|
-
form.add_error(self, error(:required, 'is required')) if required?
|
49
|
-
|
50
|
-
value = blank_value if blank_value?
|
51
|
-
else
|
52
|
-
form.add_error(self, error(:not_multiline, 'cannot contain newlines')) if !multiline? && value.lines.count > 1
|
53
|
-
|
54
|
-
form.add_error(self, error(:too_long, 'is too long')) if too_long?(value)
|
55
|
-
|
56
|
-
form.add_error(self, error(:too_short, 'is too short')) if too_short?(value)
|
57
|
-
|
58
|
-
form.add_error(self, error(:no_match, 'is invalid')) if no_match?(value)
|
59
|
-
|
60
|
-
form.add_error(self, error(:bad_value, 'is invalid')) if values? && !values.include?(value)
|
61
|
-
end
|
62
|
-
|
63
|
-
value = Array(form.send(name)).push(value) if multiple?
|
64
|
-
|
65
|
-
form.send(:"#{name}=", value)
|
66
|
-
end
|
67
|
-
|
68
|
-
def validate_file(object, form)
|
69
|
-
type = MIME::Types[object.content_type].first
|
70
|
-
|
71
|
-
filename_type = MIME::Types.type_for(object.original_filename).first
|
72
|
-
|
73
|
-
if type.nil? || type != filename_type || !accept.include?(type)
|
74
|
-
form.add_error(self, error(:not_accepted, 'is not an accepted file type'))
|
75
|
-
end
|
76
|
-
|
77
|
-
object = Array(form.send(name)).push(object) if multiple?
|
78
|
-
|
79
|
-
form.send(:"#{name}=", object)
|
80
|
-
end
|
81
|
-
|
82
|
-
def error(key, default)
|
83
|
-
Formeze.translate(key, scope: ERRORS_SCOPE, default: default)
|
84
|
-
end
|
85
|
-
|
86
|
-
def key
|
87
|
-
@key ||= @name.to_s
|
88
|
-
end
|
89
|
-
|
90
|
-
def key_required?
|
91
|
-
@options.fetch(:key_required) { true }
|
92
|
-
end
|
93
|
-
|
94
|
-
def label
|
95
|
-
@options.fetch(:label) { Formeze.translate(name, scope: LABELS_SCOPE, default: Formeze.label(name)) }
|
96
|
-
end
|
97
|
-
|
98
|
-
def required?
|
99
|
-
@options.fetch(:required) { true }
|
100
|
-
end
|
101
|
-
|
102
|
-
def multiline?
|
103
|
-
@options.fetch(:multiline) { false }
|
104
|
-
end
|
105
|
-
|
106
|
-
def multiple?
|
107
|
-
@options.fetch(:multiple) { false }
|
108
|
-
end
|
109
|
-
|
110
|
-
def maxsize?
|
111
|
-
@options.key?(:maxsize)
|
112
|
-
end
|
113
|
-
|
114
|
-
def maxsize
|
115
|
-
@options.fetch(:maxsize)
|
116
|
-
end
|
117
|
-
|
118
|
-
def accept
|
119
|
-
@accept ||= @options.fetch(:accept).split(',').flat_map { |type| MIME::Types[type] }
|
120
|
-
end
|
121
|
-
|
122
|
-
def too_long?(value)
|
123
|
-
value.chars.count > @options.fetch(:maxlength) { 64 }
|
124
|
-
end
|
125
|
-
|
126
|
-
def too_short?(value)
|
127
|
-
@options.key?(:minlength) && value.chars.count < @options.fetch(:minlength)
|
128
|
-
end
|
129
|
-
|
130
|
-
def no_match?(value)
|
131
|
-
@options.key?(:pattern) && value !~ @options[:pattern]
|
132
|
-
end
|
133
|
-
|
134
|
-
def blank_value?
|
135
|
-
@options.key?(:blank)
|
136
|
-
end
|
137
|
-
|
138
|
-
def blank_value
|
139
|
-
@options.fetch(:blank)
|
140
|
-
end
|
141
|
-
|
142
|
-
def values?
|
143
|
-
@options.key?(:values)
|
144
|
-
end
|
145
|
-
|
146
|
-
def values
|
147
|
-
@options.fetch(:values)
|
148
|
-
end
|
149
|
-
|
150
|
-
def defined_if?
|
151
|
-
@options.key?(:defined_if)
|
152
|
-
end
|
153
|
-
|
154
|
-
def defined_if
|
155
|
-
@options.fetch(:defined_if)
|
156
|
-
end
|
157
|
-
|
158
|
-
def defined_unless?
|
159
|
-
@options.key?(:defined_unless)
|
160
|
-
end
|
161
|
-
|
162
|
-
def defined_unless
|
163
|
-
@options.fetch(:defined_unless)
|
164
|
-
end
|
165
|
-
end
|
166
|
-
|
167
|
-
class Validation
|
168
|
-
include Presence
|
169
|
-
|
170
|
-
def initialize(field, **kwargs, &block)
|
171
|
-
@field = field
|
172
|
-
|
173
|
-
@error = kwargs[:error] || :invalid
|
174
|
-
|
175
|
-
@precondition = kwargs[:if]
|
176
|
-
|
177
|
-
@block = block
|
178
|
-
end
|
179
|
-
|
180
|
-
def error_message
|
181
|
-
Formeze.translate(@error, scope: ERRORS_SCOPE, default: 'is invalid')
|
182
|
-
end
|
183
|
-
|
184
|
-
def validates?(form)
|
185
|
-
@precondition ? form.instance_eval(&@precondition) : true
|
186
|
-
end
|
187
|
-
|
188
|
-
def field_value?(form)
|
189
|
-
present?(form.send(@field.name))
|
190
|
-
end
|
191
|
-
|
192
|
-
def field_errors?(form)
|
193
|
-
form.errors_on?(@field.name)
|
194
|
-
end
|
195
|
-
|
196
|
-
def validate(form)
|
197
|
-
if validates?(form) && field_value?(form) && !field_errors?(form)
|
198
|
-
return_value = if @block.arity == 1
|
199
|
-
@block.call(form.send(@field.name))
|
200
|
-
else
|
201
|
-
form.instance_eval(&@block)
|
202
|
-
end
|
203
|
-
|
204
|
-
form.add_error(@field, error_message) unless return_value
|
205
|
-
end
|
206
|
-
end
|
207
|
-
end
|
4
|
+
autoload :Errors, 'formeze/errors'
|
5
|
+
autoload :Field, 'formeze/field'
|
6
|
+
autoload :Form, 'formeze/form'
|
7
|
+
autoload :FormData, 'formeze/form_data'
|
8
|
+
autoload :Labels, 'formeze/labels'
|
9
|
+
autoload :Presence, 'formeze/presence'
|
10
|
+
autoload :Validation, 'formeze/validation'
|
208
11
|
|
209
12
|
module ClassMethods
|
210
13
|
def fields
|
@@ -234,20 +37,6 @@ module Formeze
|
|
234
37
|
|
235
38
|
class ValidationError < StandardError; end
|
236
39
|
|
237
|
-
class RequestCGI < CGI
|
238
|
-
def env_table
|
239
|
-
@options[:request].env
|
240
|
-
end
|
241
|
-
|
242
|
-
def stdinput
|
243
|
-
@options[:request].body.tap do |body|
|
244
|
-
body.rewind if body.respond_to?(:rewind)
|
245
|
-
end
|
246
|
-
end
|
247
|
-
end
|
248
|
-
|
249
|
-
private_constant :RequestCGI
|
250
|
-
|
251
40
|
RAILS_FORM_KEYS = %w[utf8 authenticity_token commit]
|
252
41
|
|
253
42
|
private_constant :RAILS_FORM_KEYS
|
@@ -266,11 +55,7 @@ module Formeze
|
|
266
55
|
end
|
267
56
|
|
268
57
|
def parse(input)
|
269
|
-
form_data =
|
270
|
-
CGI.parse(input)
|
271
|
-
else
|
272
|
-
RequestCGI.new(request: input).params
|
273
|
-
end
|
58
|
+
form_data = FormData.parse(input)
|
274
59
|
|
275
60
|
self.class.fields.each_value do |field|
|
276
61
|
next unless field_defined?(field)
|
@@ -307,7 +92,9 @@ module Formeze
|
|
307
92
|
return self
|
308
93
|
end
|
309
94
|
|
310
|
-
def add_error(field, message)
|
95
|
+
def add_error(field, message, default = nil)
|
96
|
+
message = Formeze::Errors.translate(message, default) unless default.nil?
|
97
|
+
|
311
98
|
error = ValidationError.new("#{field.label} #{message}")
|
312
99
|
|
313
100
|
errors << error
|
@@ -380,27 +167,9 @@ module Formeze
|
|
380
167
|
end
|
381
168
|
end
|
382
169
|
|
383
|
-
ERRORS_SCOPE = [:formeze, :errors].freeze
|
384
|
-
|
385
|
-
private_constant :ERRORS_SCOPE
|
386
|
-
|
387
|
-
LABELS_SCOPE = [:formeze, :labels].freeze
|
388
|
-
|
389
|
-
private_constant :LABELS_SCOPE
|
390
|
-
|
391
|
-
def self.translate(key, **options)
|
392
|
-
defined?(I18n) ? I18n.translate(key, **options) : options.fetch(:default)
|
393
|
-
end
|
394
|
-
|
395
170
|
def self.setup(form)
|
396
171
|
form.send :include, InstanceMethods
|
397
172
|
|
398
173
|
form.extend ClassMethods
|
399
174
|
end
|
400
|
-
|
401
|
-
class Form
|
402
|
-
def self.inherited(subclass)
|
403
|
-
Formeze.setup(subclass)
|
404
|
-
end
|
405
|
-
end
|
406
175
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: formeze
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.
|
4
|
+
version: 4.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tim Craft
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-03-07 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Ruby gem for validating form data
|
14
14
|
email:
|
@@ -22,6 +22,13 @@ files:
|
|
22
22
|
- README.md
|
23
23
|
- formeze.gemspec
|
24
24
|
- lib/formeze.rb
|
25
|
+
- lib/formeze/errors.rb
|
26
|
+
- lib/formeze/field.rb
|
27
|
+
- lib/formeze/form.rb
|
28
|
+
- lib/formeze/form_data.rb
|
29
|
+
- lib/formeze/labels.rb
|
30
|
+
- lib/formeze/presence.rb
|
31
|
+
- lib/formeze/validation.rb
|
25
32
|
homepage: https://github.com/readysteady/formeze
|
26
33
|
licenses:
|
27
34
|
- LGPL-3.0
|
@@ -45,7 +52,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
45
52
|
- !ruby/object:Gem::Version
|
46
53
|
version: '0'
|
47
54
|
requirements: []
|
48
|
-
rubygems_version: 3.
|
55
|
+
rubygems_version: 3.5.3
|
49
56
|
signing_key:
|
50
57
|
specification_version: 4
|
51
58
|
summary: See description
|