formeze 1.9.1 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +87 -6
- data/Rakefile.rb +1 -0
- data/formeze.gemspec +1 -1
- data/lib/formeze.rb +96 -52
- data/spec/formeze_spec.rb +171 -36
- metadata +3 -3
data/README.md
CHANGED
@@ -1,5 +1,8 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
formeze
|
2
|
+
=======
|
3
|
+
|
4
|
+
|
5
|
+
A little library for handling form data/input.
|
3
6
|
|
4
7
|
|
5
8
|
Motivation
|
@@ -207,14 +210,93 @@ Custom scrub methods can be defined by adding a symbol/proc entry to the
|
|
207
210
|
`Formeze.scrub_methods` hash.
|
208
211
|
|
209
212
|
|
213
|
+
Custom validation
|
214
|
+
-----------------
|
215
|
+
|
216
|
+
You may need additional validation logic beyond what the field options
|
217
|
+
described above provide, such as validating the format of a field without
|
218
|
+
using a regular expression, validating that two fields are equal etc.
|
219
|
+
This can be accomplished using the `validates` class method. Pass the
|
220
|
+
name of the field to be validated, and a block/proc that encapsulates
|
221
|
+
the validation logic. For example:
|
222
|
+
|
223
|
+
```ruby
|
224
|
+
class ExampleForm < Formeze::Form
|
225
|
+
field :email
|
226
|
+
|
227
|
+
validates :email, &EmailAddress.method(:valid?)
|
228
|
+
end
|
229
|
+
```
|
230
|
+
|
231
|
+
If the block/proc takes no arguments then it will be evaluated in the
|
232
|
+
scope of the form instance, which gives you access to the values of other
|
233
|
+
fields (and methods defined on the form). For example:
|
234
|
+
|
235
|
+
```ruby
|
236
|
+
class ExampleForm < Formeze::Form
|
237
|
+
field :password
|
238
|
+
field :password_confirmation
|
239
|
+
|
240
|
+
validates :password_confirmation do
|
241
|
+
password_confirmation == password
|
242
|
+
end
|
243
|
+
end
|
244
|
+
```
|
245
|
+
|
246
|
+
Specify the `when` option with a proc to peform the validation conditionally.
|
247
|
+
Similar to the `defined_if` and `defined_unless` field options, the proc is
|
248
|
+
evaluated in the scope of the form instance. For example:
|
249
|
+
|
250
|
+
```ruby
|
251
|
+
class ExampleForm < Formeze::Form
|
252
|
+
field :business_name, :defined_if => :business_account?
|
253
|
+
field :vat_number, :defined_if => :business_account?
|
254
|
+
|
255
|
+
validates :vat_number, :when => :business_account? do
|
256
|
+
# ...
|
257
|
+
end
|
258
|
+
|
259
|
+
def initialize(account)
|
260
|
+
@account = account
|
261
|
+
end
|
262
|
+
|
263
|
+
def business_account?
|
264
|
+
@account.business?
|
265
|
+
end
|
266
|
+
end
|
267
|
+
```
|
268
|
+
|
269
|
+
Specify the `error` option with a symbol to control which error the validation
|
270
|
+
generates. The I18n integration described below can be used to specify the
|
271
|
+
error message used, both for errors that are explicitly specified using this
|
272
|
+
option, and the default "invalid" error. For example:
|
273
|
+
|
274
|
+
```ruby
|
275
|
+
class ExampleForm < Formeze::Form
|
276
|
+
field :email
|
277
|
+
field :password
|
278
|
+
field :password_confirmation
|
279
|
+
|
280
|
+
validates :email, &EmailAddress.method(:valid?)
|
281
|
+
|
282
|
+
validates :password_confirmation, :error => :does_not_match do
|
283
|
+
password_confirmation == password
|
284
|
+
end
|
285
|
+
end
|
286
|
+
```
|
287
|
+
|
288
|
+
The error for the email validation would use the `formeze.errors.invalid`
|
289
|
+
I18n key, defaulting to "is invalid". The error message for the password
|
290
|
+
confirmation validation would use the `formeze.errors.does_not_match` key.
|
291
|
+
|
292
|
+
|
210
293
|
Rails usage
|
211
294
|
-----------
|
212
295
|
|
213
296
|
This is the basic pattern for using a formeze form in a Rails controller:
|
214
297
|
|
215
298
|
```ruby
|
216
|
-
form = SomeForm.
|
217
|
-
form.parse(request.raw_post)
|
299
|
+
form = SomeForm.parse(request.raw_post)
|
218
300
|
|
219
301
|
if form.valid?
|
220
302
|
# do something with form data
|
@@ -234,8 +316,7 @@ Using formeze with sinatra is similar, the only difference is that there is
|
|
234
316
|
no raw_post method on the request object so the body has to be read directly:
|
235
317
|
|
236
318
|
```ruby
|
237
|
-
form = SomeForm.
|
238
|
-
form.parse(request.body.read)
|
319
|
+
form = SomeForm.parse(request.body.read)
|
239
320
|
|
240
321
|
if form.valid?
|
241
322
|
# do something with form data
|
data/Rakefile.rb
CHANGED
data/formeze.gemspec
CHANGED
data/lib/formeze.rb
CHANGED
@@ -16,32 +16,36 @@ module Formeze
|
|
16
16
|
|
17
17
|
def initialize(name, options = {})
|
18
18
|
@name, @options = name, options
|
19
|
+
|
20
|
+
if options.has_key?(:word_limit)
|
21
|
+
Kernel.warn '[formeze] :word_limit option is deprecated, please use custom validation instead'
|
22
|
+
end
|
19
23
|
end
|
20
24
|
|
21
25
|
def validate(value, form)
|
22
26
|
value = Formeze.scrub(value, @options[:scrub])
|
23
27
|
|
24
28
|
if value !~ /\S/
|
25
|
-
|
29
|
+
form.add_error(self, error(:required, 'is required')) if required?
|
26
30
|
|
27
31
|
form.send(:"#{name}=", blank_value? ? blank_value : value)
|
28
32
|
else
|
29
|
-
|
33
|
+
form.add_error(self, error(:not_multiline, 'cannot contain newlines')) if !multiline? && value.lines.count > 1
|
30
34
|
|
31
|
-
|
35
|
+
form.add_error(self, error(:too_long, 'is too long')) if too_long?(value)
|
32
36
|
|
33
|
-
|
37
|
+
form.add_error(self, error(:too_short, 'is too short')) if too_short?(value)
|
34
38
|
|
35
|
-
|
39
|
+
form.add_error(self, error(:no_match, 'is invalid')) if no_match?(value)
|
36
40
|
|
37
|
-
|
41
|
+
form.add_error(self, error(:bad_value, 'is invalid')) if values? && !values.include?(value)
|
38
42
|
|
39
43
|
form.send(:"#{name}=", value)
|
40
44
|
end
|
41
45
|
end
|
42
46
|
|
43
|
-
def error(
|
44
|
-
translate(
|
47
|
+
def error(key, default)
|
48
|
+
Formeze.translate(key, :scope => [:formeze, :errors], :default => default)
|
45
49
|
end
|
46
50
|
|
47
51
|
def key
|
@@ -53,7 +57,7 @@ module Formeze
|
|
53
57
|
end
|
54
58
|
|
55
59
|
def label
|
56
|
-
@options.fetch(:label) { translate(name, :scope => [:formeze, :labels], :default => Label.new(name)) }
|
60
|
+
@options.fetch(:label) { Formeze.translate(name, :scope => [:formeze, :labels], :default => Label.new(name)) }
|
57
61
|
end
|
58
62
|
|
59
63
|
def required?
|
@@ -77,15 +81,7 @@ module Formeze
|
|
77
81
|
end
|
78
82
|
|
79
83
|
def too_many_characters?(value)
|
80
|
-
|
81
|
-
value.chars.count > @options.fetch(:maxlength)
|
82
|
-
elsif @options.has_key?(:char_limit)
|
83
|
-
Kernel.warn '[formeze] :char_limit option is deprecated, please use :maxlength instead'
|
84
|
-
|
85
|
-
value.chars.count > @options.fetch(:char_limit)
|
86
|
-
else
|
87
|
-
value.chars.count > 64
|
88
|
-
end
|
84
|
+
value.chars.count > @options.fetch(:maxlength) { 64 }
|
89
85
|
end
|
90
86
|
|
91
87
|
def too_many_words?(value)
|
@@ -127,12 +123,60 @@ module Formeze
|
|
127
123
|
def defined_unless
|
128
124
|
@options.fetch(:defined_unless)
|
129
125
|
end
|
126
|
+
end
|
130
127
|
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
128
|
+
class FieldSet
|
129
|
+
include Enumerable
|
130
|
+
|
131
|
+
def initialize
|
132
|
+
@fields, @index = [], {}
|
133
|
+
end
|
134
|
+
|
135
|
+
def each(&block)
|
136
|
+
@fields.each(&block)
|
137
|
+
end
|
138
|
+
|
139
|
+
def <<(field)
|
140
|
+
@fields << field
|
141
|
+
|
142
|
+
@index[field.name] = field
|
143
|
+
end
|
144
|
+
|
145
|
+
def [](field_name)
|
146
|
+
@index.fetch(field_name)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
class Validation
|
151
|
+
def initialize(field, options, &block)
|
152
|
+
@field, @options, @block = field, options, block
|
153
|
+
end
|
154
|
+
|
155
|
+
def error_key
|
156
|
+
@options.fetch(:error) { :invalid }
|
157
|
+
end
|
158
|
+
|
159
|
+
def error_message
|
160
|
+
Formeze.translate(error_key, :scope => [:formeze, :errors], :default => 'is invalid')
|
161
|
+
end
|
162
|
+
|
163
|
+
def validates?(form)
|
164
|
+
@options.has_key?(:when) ? form.instance_eval(&@options[:when]) : true
|
165
|
+
end
|
166
|
+
|
167
|
+
def value?(form)
|
168
|
+
form.send(@field.name) =~ /\S/
|
169
|
+
end
|
170
|
+
|
171
|
+
def validate(form)
|
172
|
+
if validates?(form) && value?(form)
|
173
|
+
return_value = if @block.arity == 1
|
174
|
+
@block.call(form.send(@field.name))
|
175
|
+
else
|
176
|
+
form.instance_eval(&@block)
|
177
|
+
end
|
178
|
+
|
179
|
+
form.add_error(@field, error_message) unless return_value
|
136
180
|
end
|
137
181
|
end
|
138
182
|
end
|
@@ -164,7 +208,7 @@ module Formeze
|
|
164
208
|
include ArrayAttrAccessor
|
165
209
|
|
166
210
|
def fields
|
167
|
-
@fields ||=
|
211
|
+
@fields ||= FieldSet.new
|
168
212
|
end
|
169
213
|
|
170
214
|
def field(*args)
|
@@ -179,20 +223,12 @@ module Formeze
|
|
179
223
|
end
|
180
224
|
end
|
181
225
|
|
182
|
-
def
|
183
|
-
@
|
226
|
+
def validations
|
227
|
+
@validations ||= []
|
184
228
|
end
|
185
229
|
|
186
|
-
def
|
187
|
-
|
188
|
-
end
|
189
|
-
|
190
|
-
def errors
|
191
|
-
@errors ||= []
|
192
|
-
end
|
193
|
-
|
194
|
-
def error(message)
|
195
|
-
errors << message
|
230
|
+
def validates(field_name, options = {}, &block)
|
231
|
+
validations << Validation.new(fields[field_name], options, &block)
|
196
232
|
end
|
197
233
|
|
198
234
|
def parse(encoded_form_data)
|
@@ -236,23 +272,33 @@ module Formeze
|
|
236
272
|
end
|
237
273
|
|
238
274
|
values.each do |value|
|
239
|
-
field.validate(value, self)
|
240
|
-
error!("#{field.label} #{error}", field.name)
|
241
|
-
end
|
275
|
+
field.validate(value, self)
|
242
276
|
end
|
243
277
|
end
|
244
278
|
|
245
279
|
if defined?(Rails)
|
246
|
-
%w(utf8 authenticity_token).each
|
280
|
+
%w(utf8 authenticity_token).each do |key|
|
281
|
+
form_data.delete(key)
|
282
|
+
end
|
247
283
|
end
|
248
284
|
|
249
|
-
|
285
|
+
unless form_data.empty?
|
286
|
+
raise KeyError, "unexpected form keys: #{form_data.keys.sort.join(', ')}"
|
287
|
+
end
|
250
288
|
|
251
|
-
self.class.
|
252
|
-
|
289
|
+
self.class.validations.each do |validation|
|
290
|
+
validation.validate(self)
|
253
291
|
end
|
254
292
|
end
|
255
293
|
|
294
|
+
def add_error(field, message)
|
295
|
+
error = ValidationError.new("#{field.label} #{message}")
|
296
|
+
|
297
|
+
errors << error
|
298
|
+
|
299
|
+
field_errors[field.name] << error
|
300
|
+
end
|
301
|
+
|
256
302
|
def valid?
|
257
303
|
errors.empty?
|
258
304
|
end
|
@@ -273,13 +319,15 @@ module Formeze
|
|
273
319
|
field_errors[field_name]
|
274
320
|
end
|
275
321
|
|
276
|
-
def
|
322
|
+
def to_h
|
277
323
|
self.class.fields.inject({}) do |hash, field|
|
278
324
|
hash[field.name] = send(field.name)
|
279
325
|
hash
|
280
326
|
end
|
281
327
|
end
|
282
328
|
|
329
|
+
alias_method :to_hash, :to_h
|
330
|
+
|
283
331
|
private
|
284
332
|
|
285
333
|
def field_defined?(field)
|
@@ -295,14 +343,6 @@ module Formeze
|
|
295
343
|
def field_errors
|
296
344
|
@field_errors ||= Hash.new { |h, k| h[k] = [] }
|
297
345
|
end
|
298
|
-
|
299
|
-
def error!(message, field_name = nil)
|
300
|
-
error = ValidationError.new(message)
|
301
|
-
|
302
|
-
errors << error
|
303
|
-
|
304
|
-
field_errors[field_name] << error unless field_name.nil?
|
305
|
-
end
|
306
346
|
end
|
307
347
|
|
308
348
|
def self.scrub_methods
|
@@ -321,6 +361,10 @@ module Formeze
|
|
321
361
|
end
|
322
362
|
end
|
323
363
|
|
364
|
+
def self.translate(key, options)
|
365
|
+
defined?(I18n) ? I18n.translate(key, options) : options.fetch(:default)
|
366
|
+
end
|
367
|
+
|
324
368
|
def self.setup(form)
|
325
369
|
form.send :include, InstanceMethods
|
326
370
|
|
data/spec/formeze_spec.rb
CHANGED
@@ -38,8 +38,10 @@ describe 'FormWithField' do
|
|
38
38
|
proc { @form.parse('title=foo&title=bar') }.must_raise(Formeze::ValueError)
|
39
39
|
end
|
40
40
|
|
41
|
-
it 'raises an exception when
|
42
|
-
proc { @form.parse('title=Untitled&foo=bar') }.must_raise(Formeze::KeyError)
|
41
|
+
it 'raises an exception when the data contains unexpected keys' do
|
42
|
+
exception = proc { @form.parse('title=Untitled&foo=bar&baz=') }.must_raise(Formeze::KeyError)
|
43
|
+
|
44
|
+
exception.message.must_equal('unexpected form keys: baz, foo')
|
43
45
|
end
|
44
46
|
end
|
45
47
|
|
@@ -105,6 +107,12 @@ describe 'FormWithField after parsing valid input' do
|
|
105
107
|
end
|
106
108
|
end
|
107
109
|
|
110
|
+
describe 'to_h method' do
|
111
|
+
it 'returns a hash containing the field name and its value' do
|
112
|
+
@form.to_h.must_equal({:title => 'Untitled'})
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
108
116
|
describe 'to_hash method' do
|
109
117
|
it 'returns a hash containing the field name and its value' do
|
110
118
|
@form.to_hash.must_equal({:title => 'Untitled'})
|
@@ -227,23 +235,6 @@ describe 'FormWithFieldThatCanHaveMultipleLines after parsing input containing n
|
|
227
235
|
end
|
228
236
|
end
|
229
237
|
|
230
|
-
class FormWithCharacterLimitedField < Formeze::Form
|
231
|
-
field :title, :char_limit => 16
|
232
|
-
end
|
233
|
-
|
234
|
-
describe 'FormWithCharacterLimitedField after parsing input with too many characters' do
|
235
|
-
before do
|
236
|
-
@form = FormWithCharacterLimitedField.new
|
237
|
-
@form.parse('title=This+Title+Will+Be+Too+Long')
|
238
|
-
end
|
239
|
-
|
240
|
-
describe 'valid query method' do
|
241
|
-
it 'returns false' do
|
242
|
-
@form.valid?.must_equal(false)
|
243
|
-
end
|
244
|
-
end
|
245
|
-
end
|
246
|
-
|
247
238
|
class FormWithMaxLengthField < Formeze::Form
|
248
239
|
field :title, :maxlength => 16
|
249
240
|
end
|
@@ -509,16 +500,55 @@ describe 'FormWithHaltingCondition after parsing input with same_address set and
|
|
509
500
|
end
|
510
501
|
end
|
511
502
|
|
512
|
-
class
|
503
|
+
class FormWithOptionalKey < Formeze::Form
|
504
|
+
field :accept_terms, :values => %w(true), :key_required => false
|
505
|
+
end
|
506
|
+
|
507
|
+
describe 'FormWithOptionalKey after parsing input without the key' do
|
508
|
+
before do
|
509
|
+
@form = FormWithOptionalKey.new
|
510
|
+
@form.parse('')
|
511
|
+
end
|
512
|
+
|
513
|
+
describe 'valid query method' do
|
514
|
+
it 'returns true' do
|
515
|
+
@form.valid?.must_equal(true)
|
516
|
+
end
|
517
|
+
end
|
518
|
+
end
|
519
|
+
|
520
|
+
class FormWithOptionalFieldThatCanOnlyHaveSpecifiedValues < Formeze::Form
|
521
|
+
field :size, :required => false, :values => %w(S M L XL)
|
522
|
+
end
|
523
|
+
|
524
|
+
describe 'FormWithOptionalFieldThatCanOnlyHaveSpecifiedValues after parsing blank input' do
|
525
|
+
before do
|
526
|
+
@form = FormWithOptionalFieldThatCanOnlyHaveSpecifiedValues.new
|
527
|
+
@form.parse('size=')
|
528
|
+
end
|
529
|
+
|
530
|
+
describe 'valid query method' do
|
531
|
+
it 'returns true' do
|
532
|
+
@form.valid?.must_equal(true)
|
533
|
+
end
|
534
|
+
end
|
535
|
+
end
|
536
|
+
|
537
|
+
module EmailAddress
|
538
|
+
def self.valid?(address)
|
539
|
+
address.include?('@')
|
540
|
+
end
|
541
|
+
end
|
542
|
+
|
543
|
+
class FormWithCustomEmailValidation < Formeze::Form
|
513
544
|
field :email
|
514
545
|
|
515
|
-
|
516
|
-
error 'Email is invalid'
|
546
|
+
validates :email, &EmailAddress.method(:valid?)
|
517
547
|
end
|
518
548
|
|
519
|
-
describe '
|
549
|
+
describe 'FormWithCustomEmailValidation after parsing invalid input' do
|
520
550
|
before do
|
521
|
-
@form =
|
551
|
+
@form = FormWithCustomEmailValidation.new
|
522
552
|
@form.parse('email=alice')
|
523
553
|
end
|
524
554
|
|
@@ -527,33 +557,85 @@ describe 'FormWithCustomValidation after parsing invalid input' do
|
|
527
557
|
@form.valid?.must_equal(false)
|
528
558
|
end
|
529
559
|
end
|
560
|
+
|
561
|
+
describe 'errors method' do
|
562
|
+
it 'includes a generic error message for the named field' do
|
563
|
+
@form.errors.map(&:to_s).must_include('Email is invalid')
|
564
|
+
end
|
565
|
+
end
|
566
|
+
|
567
|
+
describe 'errors_on query method' do
|
568
|
+
it 'returns true when given the field name' do
|
569
|
+
@form.errors_on?(:email).must_equal(true)
|
570
|
+
end
|
571
|
+
end
|
530
572
|
end
|
531
573
|
|
532
|
-
|
533
|
-
|
574
|
+
describe 'FormWithCustomEmailValidation after parsing blank input' do
|
575
|
+
before do
|
576
|
+
@form = FormWithCustomEmailValidation.new
|
577
|
+
@form.parse('email=')
|
578
|
+
end
|
579
|
+
|
580
|
+
describe 'errors method' do
|
581
|
+
it 'will not include the custom validation error message' do
|
582
|
+
@form.errors.map(&:to_s).wont_include('Email is invalid')
|
583
|
+
end
|
584
|
+
end
|
534
585
|
end
|
535
586
|
|
536
|
-
|
587
|
+
class FormWithCustomPasswordConfirmationCheck < Formeze::Form
|
588
|
+
field :password
|
589
|
+
field :password_confirmation
|
590
|
+
|
591
|
+
validates :password_confirmation, :error => :does_not_match do
|
592
|
+
password_confirmation == password
|
593
|
+
end
|
594
|
+
end
|
595
|
+
|
596
|
+
describe 'FormWithCustomPasswordConfirmationCheck after parsing invalid input' do
|
537
597
|
before do
|
538
|
-
@form =
|
539
|
-
@form.parse('')
|
598
|
+
@form = FormWithCustomPasswordConfirmationCheck.new
|
599
|
+
@form.parse('password=foo&password_confirmation=bar')
|
540
600
|
end
|
541
601
|
|
542
602
|
describe 'valid query method' do
|
543
|
-
it 'returns
|
544
|
-
@form.valid?.must_equal(
|
603
|
+
it 'returns false' do
|
604
|
+
@form.valid?.must_equal(false)
|
605
|
+
end
|
606
|
+
end
|
607
|
+
|
608
|
+
describe 'errors method' do
|
609
|
+
it 'includes a generic error message for the named field' do
|
610
|
+
@form.errors.map(&:to_s).must_include('Password confirmation is invalid')
|
611
|
+
end
|
612
|
+
end
|
613
|
+
|
614
|
+
describe 'errors_on query method' do
|
615
|
+
it 'returns true when given the field name' do
|
616
|
+
@form.errors_on?(:password_confirmation).must_equal(true)
|
545
617
|
end
|
546
618
|
end
|
547
619
|
end
|
548
620
|
|
549
|
-
class
|
550
|
-
field :
|
621
|
+
class FormWithCustomMinimumSpendValidation < Formeze::Form
|
622
|
+
field :minimum_spend
|
623
|
+
|
624
|
+
field :fixed_discount, :required => false, :blank => nil
|
625
|
+
|
626
|
+
validates :minimum_spend, :when => :fixed_discount? do
|
627
|
+
minimum_spend.to_f > 0
|
628
|
+
end
|
629
|
+
|
630
|
+
def fixed_discount?
|
631
|
+
!fixed_discount.nil?
|
632
|
+
end
|
551
633
|
end
|
552
634
|
|
553
|
-
describe '
|
635
|
+
describe 'FormWithCustomMinimumSpendValidation after parsing valid input' do
|
554
636
|
before do
|
555
|
-
@form =
|
556
|
-
@form.parse('
|
637
|
+
@form = FormWithCustomMinimumSpendValidation.new
|
638
|
+
@form.parse('minimum_spend=0.00&fixed_discount=')
|
557
639
|
end
|
558
640
|
|
559
641
|
describe 'valid query method' do
|
@@ -561,6 +643,43 @@ describe 'FormWithOptionalFieldThatCanOnlyHaveSpecifiedValues after parsing blan
|
|
561
643
|
@form.valid?.must_equal(true)
|
562
644
|
end
|
563
645
|
end
|
646
|
+
|
647
|
+
describe 'errors method' do
|
648
|
+
it 'returns an empty array' do
|
649
|
+
@form.errors.must_be_empty
|
650
|
+
end
|
651
|
+
end
|
652
|
+
|
653
|
+
describe 'errors_on query method' do
|
654
|
+
it 'returns false when given the field name' do
|
655
|
+
@form.errors_on?(:minimum_spend).must_equal(false)
|
656
|
+
end
|
657
|
+
end
|
658
|
+
end
|
659
|
+
|
660
|
+
describe 'FormWithCustomMinimumSpendValidation after parsing invalid input' do
|
661
|
+
before do
|
662
|
+
@form = FormWithCustomMinimumSpendValidation.new
|
663
|
+
@form.parse('minimum_spend=0.00&fixed_discount=10%')
|
664
|
+
end
|
665
|
+
|
666
|
+
describe 'valid query method' do
|
667
|
+
it 'returns false' do
|
668
|
+
@form.valid?.must_equal(false)
|
669
|
+
end
|
670
|
+
end
|
671
|
+
|
672
|
+
describe 'errors method' do
|
673
|
+
it 'includes a generic error message for the named field' do
|
674
|
+
@form.errors.map(&:to_s).must_include('Minimum spend is invalid')
|
675
|
+
end
|
676
|
+
end
|
677
|
+
|
678
|
+
describe 'errors_on query method' do
|
679
|
+
it 'returns true when given the field name' do
|
680
|
+
@form.errors_on?(:minimum_spend).must_equal(true)
|
681
|
+
end
|
682
|
+
end
|
564
683
|
end
|
565
684
|
|
566
685
|
describe 'FormWithField on Rails' do
|
@@ -601,6 +720,22 @@ describe 'I18n integration' do
|
|
601
720
|
form.errors.first.to_s.must_equal('Title cannot be blank')
|
602
721
|
end
|
603
722
|
|
723
|
+
it 'provides i18n support for overriding the default custom validation error message' do
|
724
|
+
I18n.backend.store_translations :en, {:formeze => {:errors => {:invalid => 'is not valid'}}}
|
725
|
+
|
726
|
+
form = FormWithCustomEmailValidation.new
|
727
|
+
form.parse('email=alice')
|
728
|
+
form.errors.first.to_s.must_equal('Email is not valid')
|
729
|
+
end
|
730
|
+
|
731
|
+
it 'provides i18n support for specifying custom validation error messages' do
|
732
|
+
I18n.backend.store_translations :en, {:formeze => {:errors => {:does_not_match => 'does not match'}}}
|
733
|
+
|
734
|
+
form = FormWithCustomPasswordConfirmationCheck.new
|
735
|
+
form.parse('password=foo&password_confirmation=bar')
|
736
|
+
form.errors.first.to_s.must_equal('Password confirmation does not match')
|
737
|
+
end
|
738
|
+
|
604
739
|
it 'provides i18n support for specifying field labels globally' do
|
605
740
|
I18n.backend.store_translations :en, {:formeze => {:labels => {:title => 'TITLE'}}}
|
606
741
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: formeze
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-06-10 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
@@ -75,7 +75,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
75
75
|
version: '0'
|
76
76
|
requirements: []
|
77
77
|
rubyforge_project:
|
78
|
-
rubygems_version: 1.8.
|
78
|
+
rubygems_version: 1.8.25
|
79
79
|
signing_key:
|
80
80
|
specification_version: 3
|
81
81
|
summary: See description
|