form_input 1.0.0 → 1.1.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/CHANGELOG.md +9 -0
- data/LICENSE +1 -1
- data/README.md +27 -12
- data/form_input.gemspec +1 -1
- data/lib/form_input/core.rb +30 -7
- data/lib/form_input/steps.rb +4 -4
- data/lib/form_input/version.rb +1 -1
- data/test/helper.rb +5 -6
- data/test/test_core.rb +62 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d7eb22ab0a9fbdbf797fd70548c4caed7201b4e7
|
4
|
+
data.tar.gz: d8fd5dbc4f0e7a10238aedddb889c37163e419f6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5d8ccd8693068596ca26d4d6b15ddfbd5434b558062de2371a154c1b5e562712792065ba4ec32bc937bcd4870cac1a4f4bab4e428409f02d75303d8707c9e9ad
|
7
|
+
data.tar.gz: 7df1a5feca9a80307e1f1fbeb6f5a1e840775743cf96136a45e723a7cd434117563b297d57264cb5169dab8534cc125ea5af3a0009a99cb6123d4e7ce4024946
|
data/CHANGELOG.md
ADDED
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -171,7 +171,7 @@ The following two declarations are therefore the same:
|
|
171
171
|
```
|
172
172
|
|
173
173
|
Parameters support many more parameter options,
|
174
|
-
and we will discuss each in turn as we go.
|
174
|
+
and we will discuss each one in turn as we go.
|
175
175
|
Comprehensive summary for an avid reader is however available in [Parameter Options](#parameter-options).
|
176
176
|
|
177
177
|
The value of each parameter is a string by default (or `nil` if the parameter is not set at all).
|
@@ -643,6 +643,10 @@ The advantage of the `:test` callback is that it works the same way regardless o
|
|
643
643
|
scalar or not,
|
644
644
|
so it is preferable to use it
|
645
645
|
if you plan to factor this into a `COUNTRY_ARGS` helper which works with both kinds of parameters.
|
646
|
+
If you do this,
|
647
|
+
you should also know that each parameter can support multiple `:check` and `:test` callbacks,
|
648
|
+
and when the parameter options are merged together, all of them are preserved by default
|
649
|
+
(unless you set it to `nil`, which resets all previously defined ones).
|
646
650
|
|
647
651
|
In either case, the `report` method is used to report any problems about the parameter,
|
648
652
|
which marks the parameter as invalid at the same time.
|
@@ -951,14 +955,22 @@ and let them report any belated additional errors which might get detected durin
|
|
951
955
|
for example:
|
952
956
|
|
953
957
|
``` ruby
|
954
|
-
form.report( :email, "Email is already taken" ) unless unique_email?( form.email )
|
958
|
+
form.report( :email, "Email address is already taken" ) unless unique_email?( form.email )
|
955
959
|
```
|
956
960
|
|
957
|
-
|
961
|
+
If you want the error message to have priority over anything else what might have been reported before,
|
962
|
+
you can use the `report!` method instead:
|
963
|
+
|
964
|
+
``` ruby
|
965
|
+
form.filled_params.each{ |p| p.report!( "Fill only one of these" ) } unless form.filled_params.one?
|
966
|
+
```
|
967
|
+
|
968
|
+
As we have already seen [before](#array-and-hash-parameters), it is common to use the `report`
|
958
969
|
method from within the `:check` or `:test` callback of the parameter itself as well:
|
959
970
|
|
960
971
|
``` ruby
|
961
|
-
check: ->{ report( "%p is
|
972
|
+
check: ->{ report( "%p is odd number" ) unless value.to_i.even? }
|
973
|
+
test: ->( value ){ report( "%p contain odd number" ) unless value.to_i.even? }
|
962
974
|
```
|
963
975
|
|
964
976
|
In this case the `%p` string is replaced by the `title` of the parameter.
|
@@ -1119,13 +1131,17 @@ so you can get back to it using the `form` method if you need to:
|
|
1119
1131
|
fail unless p.form.valid?
|
1120
1132
|
```
|
1121
1133
|
|
1122
|
-
As we have seen, you can report errors about the parameter using its `report`
|
1134
|
+
As we have seen, you can report errors about the parameter using its `report` or `report!` methods.
|
1123
1135
|
You can ask it about all its errors or just the first error using the `errors` or `error` methods, respectively:
|
1124
1136
|
|
1125
1137
|
``` ruby
|
1126
1138
|
p.report( "This is invalid" )
|
1127
1139
|
p.errors # [ "This is invalid" ]
|
1128
1140
|
p.error # "This is invalid"
|
1141
|
+
|
1142
|
+
p.report!( "Do not fill this!" )
|
1143
|
+
p.errors # [ "Do not fill this!", "This is invalid" ]
|
1144
|
+
p.error # "Do not fill this!"
|
1129
1145
|
```
|
1130
1146
|
|
1131
1147
|
You can also simply ask whether the parameter is valid or not by using the `valid?` and `invalid?` methods.
|
@@ -1398,7 +1414,7 @@ you will eventually want to extend it further to better fit your project.
|
|
1398
1414
|
To do this, it's common to define the `Form` class inherited from `FormInput`,
|
1399
1415
|
put various helpers there, and base your own forms on that.
|
1400
1416
|
This is also the place where you can include your own `FormInput` types extensions.
|
1401
|
-
This chapter shows some ideas you may want to
|
1417
|
+
This chapter shows some ideas you may want to build upon to get you started.
|
1402
1418
|
|
1403
1419
|
Adding custom boolean getters which you may need:
|
1404
1420
|
|
@@ -1488,9 +1504,9 @@ This is a brief but comprehensive summary of all parameter options:
|
|
1488
1504
|
See [Output Format](#output-format).
|
1489
1505
|
* `:class` - object type (or array thereof) which the input filter is expected to convert the input value into.
|
1490
1506
|
See [Input Filter](#input-filter).
|
1491
|
-
* `:check` - optional callback used to perform arbitrary checks when testing the parameter validity.
|
1507
|
+
* `:check` - optional callback (or array thereof) used to perform arbitrary checks when testing the parameter validity.
|
1492
1508
|
See [Errors and Validation](#errors-and-validation).
|
1493
|
-
* `:test` - optional callback used to perform arbitrary tests when testing validity of each parameter value.
|
1509
|
+
* `:test` - optional callback (or array thereof) used to perform arbitrary tests when testing validity of each parameter value.
|
1494
1510
|
See [Errors and Validation](#errors-and-validation).
|
1495
1511
|
* `:min_key` - minimum allowed value for keys of hash parameters. Defaults to 0.
|
1496
1512
|
* `:max_key` - maximum allowed value for keys of hash parameters. Defaults to 2<sup>64</sup>-1.
|
@@ -1554,8 +1570,7 @@ For example, this is a `snippet` helper based on [Sinatra]'s partials:
|
|
1554
1570
|
|
1555
1571
|
``` ruby
|
1556
1572
|
# Render partial, our style.
|
1557
|
-
def snippet( name, opts = {}, locals
|
1558
|
-
opts, locals = {}, opts unless locals
|
1573
|
+
def snippet( name, opts = {}, **locals )
|
1559
1574
|
partial( "snippets/#{name}", opts.merge( locals: locals ) )
|
1560
1575
|
end
|
1561
1576
|
```
|
@@ -2683,7 +2698,7 @@ you can override it by setting the `:plural` parameter option to `true` or `'p'`
|
|
2683
2698
|
and to `false` or `'s'` for singular, respectively:
|
2684
2699
|
|
2685
2700
|
``` ruby
|
2686
|
-
param :keywords, "Keywords, plural: true
|
2701
|
+
param :keywords, "Keywords", plural: true
|
2687
2702
|
array :countries, "List of countries", plural: false
|
2688
2703
|
```
|
2689
2704
|
|
@@ -2959,7 +2974,7 @@ might look like:
|
|
2959
2974
|
|
2960
2975
|
The `pt` method is usable only in the parameter context.
|
2961
2976
|
It works similar to the `ft` method,
|
2962
|
-
except that all translations are automatically looked up in the parameter's own
|
2977
|
+
except that all translations are automatically looked up in the parameter's own `forms.<form_translation_name>.<parameter_name>` namespace,
|
2963
2978
|
rather than the global namespace.
|
2964
2979
|
|
2965
2980
|
``` ruby
|
data/form_input.gemspec
CHANGED
@@ -21,7 +21,7 @@ EOT
|
|
21
21
|
s.homepage = 'https://github.com/raxoft/form_input'
|
22
22
|
s.license = 'MIT'
|
23
23
|
|
24
|
-
s.files = %w[ LICENSE README.md Rakefile .yardopts form_input.gemspec ] + Dir[ '{lib,test,example}/**/*.{rb,yml,txt,slim}' ]
|
24
|
+
s.files = %w[ LICENSE README.md CHANGELOG.md Rakefile .yardopts form_input.gemspec ] + Dir[ '{lib,test,example}/**/*.{rb,yml,txt,slim}' ]
|
25
25
|
|
26
26
|
s.required_ruby_version = '>= 2.0.0'
|
27
27
|
s.add_runtime_dependency 'rack', '>= 1.5', '< 3.0'
|
data/lib/form_input/core.rb
CHANGED
@@ -49,6 +49,9 @@ class FormInput
|
|
49
49
|
match_msg: "%p like this is not valid",
|
50
50
|
}
|
51
51
|
|
52
|
+
# Parameter options which can be merged together into an array when multiple option hashes are merged.
|
53
|
+
MERGEABLE_OPTIONS = [ :check, :test ]
|
54
|
+
|
52
55
|
# Form parameter.
|
53
56
|
class Parameter
|
54
57
|
|
@@ -336,12 +339,22 @@ class FormInput
|
|
336
339
|
|
337
340
|
# Report an error concerning this parameter.
|
338
341
|
# String %p in the message is automatically replaced with error title.
|
342
|
+
# In case of multiple errors, the message is added to the end of the list, making it less important than the other errors.
|
339
343
|
# Returns self for chaining.
|
340
344
|
def report( msg, *args )
|
341
345
|
form.report( name, format_error_message( msg, *args ) ) if form
|
342
346
|
self
|
343
347
|
end
|
344
348
|
|
349
|
+
# Report an error concerning this parameter.
|
350
|
+
# String %p in the message is automatically replaced with error title.
|
351
|
+
# In case of multiple errors, the message is added to the beginning of the list, making it more important than the other errors.
|
352
|
+
# Returns self for chaining.
|
353
|
+
def report!( msg, *args )
|
354
|
+
form.report!( name, format_error_message( msg, *args ) ) if form
|
355
|
+
self
|
356
|
+
end
|
357
|
+
|
345
358
|
end
|
346
359
|
|
347
360
|
include LocaleMethods
|
@@ -373,10 +386,10 @@ class FormInput
|
|
373
386
|
validate_value( value )
|
374
387
|
end
|
375
388
|
|
376
|
-
# Finally, invoke the custom check
|
389
|
+
# Finally, invoke the custom check callbacks if there are any.
|
377
390
|
|
378
|
-
if
|
379
|
-
instance_exec( &
|
391
|
+
if checks = opts[ :check ]
|
392
|
+
[ *checks ].each{ |x| instance_exec( &x ) }
|
380
393
|
end
|
381
394
|
end
|
382
395
|
|
@@ -512,10 +525,10 @@ class FormInput
|
|
512
525
|
return
|
513
526
|
end
|
514
527
|
|
515
|
-
# Finally, invoke the custom
|
528
|
+
# Finally, invoke the custom callbacks if there are any.
|
516
529
|
|
517
|
-
if
|
518
|
-
instance_exec( value, &
|
530
|
+
if tests = opts[ :test ]
|
531
|
+
[ *tests ].each{ |x| instance_exec( value, &x ) }
|
519
532
|
return unless valid?
|
520
533
|
end
|
521
534
|
|
@@ -662,7 +675,7 @@ class FormInput
|
|
662
675
|
size = args.shift if args.first.is_a? Numeric
|
663
676
|
|
664
677
|
opts = {}
|
665
|
-
opts.merge!( args.shift ) while args.first.is_a? Hash
|
678
|
+
opts.merge!( args.shift ){ |k, o, n| ( n && MERGEABLE_OPTIONS.include?( k ) ) ? [ *o, *n ] : n } while args.first.is_a? Hash
|
666
679
|
|
667
680
|
fail ArgumentError, "invalid arguments #{args}" unless args.empty?
|
668
681
|
|
@@ -1099,6 +1112,7 @@ class FormInput
|
|
1099
1112
|
end
|
1100
1113
|
|
1101
1114
|
# Remember error concerning given parameter.
|
1115
|
+
# In case of multiple errors, the message is added to the end of the list, making it less important than the other errors.
|
1102
1116
|
# Returns self for chaining.
|
1103
1117
|
def report( name, msg )
|
1104
1118
|
validate?
|
@@ -1106,6 +1120,15 @@ class FormInput
|
|
1106
1120
|
self
|
1107
1121
|
end
|
1108
1122
|
|
1123
|
+
# Remember error concerning given parameter.
|
1124
|
+
# In case of multiple errors, the message is added to the beginning of the list, making it more important than the other errors.
|
1125
|
+
# Returns self for chaining.
|
1126
|
+
def report!( name, msg )
|
1127
|
+
validate?
|
1128
|
+
( @errors[ name ] ||= [] ).unshift( msg.to_s.dup.freeze )
|
1129
|
+
self
|
1130
|
+
end
|
1131
|
+
|
1109
1132
|
# Get list of errors for given parameter. Returns empty list if there were no errors.
|
1110
1133
|
def errors_for( name )
|
1111
1134
|
errors[ name ] || []
|
data/lib/form_input/steps.rb
CHANGED
@@ -338,22 +338,22 @@ class FormInput
|
|
338
338
|
finished_step?( step ) and incorrect_step?( step )
|
339
339
|
end
|
340
340
|
|
341
|
-
# Get steps which
|
341
|
+
# Get steps which shall be displayed as correct.
|
342
342
|
def good_steps
|
343
343
|
steps.select{ |step| good_step?( step ) }
|
344
344
|
end
|
345
345
|
|
346
|
-
# Get steps which
|
346
|
+
# Get steps which shall be displayed as incorrect.
|
347
347
|
def bad_steps
|
348
348
|
steps.select{ |step| bad_step?( step ) }
|
349
349
|
end
|
350
350
|
|
351
|
-
# Test if given/current step
|
351
|
+
# Test if given/current step shall be displayed as correct.
|
352
352
|
def good_step?( step = self.step )
|
353
353
|
complete_step?( step ) and filled_step?( step ) and regular_step?( step )
|
354
354
|
end
|
355
355
|
|
356
|
-
# Test if given/current step
|
356
|
+
# Test if given/current step shall be displayed as incorrect.
|
357
357
|
def bad_step?( step = self.step )
|
358
358
|
incomplete_step?( step )
|
359
359
|
end
|
data/lib/form_input/version.rb
CHANGED
data/test/helper.rb
CHANGED
@@ -6,16 +6,15 @@ def jruby?
|
|
6
6
|
defined?( RUBY_ENGINE ) and RUBY_ENGINE == 'jruby'
|
7
7
|
end
|
8
8
|
|
9
|
-
if ENV[ 'COVERAGE' ]
|
10
|
-
require 'simplecov'
|
11
|
-
SimpleCov.start
|
12
|
-
end
|
13
|
-
|
14
9
|
begin
|
15
10
|
require 'codeclimate-test-reporter'
|
16
|
-
CodeClimate::TestReporter.start
|
17
11
|
ENV[ 'COVERAGE' ] = 'on'
|
18
12
|
rescue LoadError
|
19
13
|
end unless jruby?
|
20
14
|
|
15
|
+
if ENV[ 'COVERAGE' ]
|
16
|
+
require 'simplecov'
|
17
|
+
SimpleCov.start
|
18
|
+
end
|
19
|
+
|
21
20
|
# EOF #
|
data/test/test_core.rb
CHANGED
@@ -380,6 +380,55 @@ describe FormInput do
|
|
380
380
|
f.error_messages.should == [ "s may have at most 5 characters" ]
|
381
381
|
end
|
382
382
|
|
383
|
+
should 'support reasonable option merging' do
|
384
|
+
c = Class.new( FormInput )
|
385
|
+
c.param :p, { max_size: 2 }, { min_size: 2, max_size: 3 }, { max_size: 4 }
|
386
|
+
c[ :p ][ :min_size ].should == 2
|
387
|
+
c[ :p ][ :max_size ].should == 4
|
388
|
+
|
389
|
+
c = Class.new( FormInput )
|
390
|
+
c.param :p, { tag: :foo }, { tag: :bar }, { tags: [ :x, :y ] }
|
391
|
+
c.param :q, { tag: :foo }, { tag: :bar }, { tag: nil }, { tags: [ :x, :y ] }
|
392
|
+
c.param :r, { tag: :foo }, { tag: :bar }, { tags: [ :x, :y ] }, { tags: nil }
|
393
|
+
c[ :p ].tags.should == [ :bar, :x, :y ]
|
394
|
+
c[ :q ].tags.should == [ :x, :y ]
|
395
|
+
c[ :r ].tags.should == [ :bar ]
|
396
|
+
|
397
|
+
c = Class.new( FormInput )
|
398
|
+
c.param :p, { tags: :foo }, { tags: :bar }, { tags: [ :x, :y ] }
|
399
|
+
c.param :q, { tags: :foo }, { tags: :bar }, { tags: nil }, { tags: [ :x, :y ] }
|
400
|
+
c.param :r, { tags: :foo }, { tags: :bar }, { tags: [ :x, :y ] }, { tags: nil }
|
401
|
+
c[ :p ].tags.should == [ :x, :y ]
|
402
|
+
c[ :q ].tags.should == [ :x, :y ]
|
403
|
+
c[ :r ].tags.should == []
|
404
|
+
|
405
|
+
c = Class.new( FormInput )
|
406
|
+
c.param :p, { check: ->{ report( "A" ) } }, { check: ->{ report( "B" ) } }
|
407
|
+
c.param :q, { check: ->{ report( "A" ) } }, { check: nil }, { check: ->{ report( "B" ) } }
|
408
|
+
c.param :r, { check: ->{ report( "A" ) } }, { check: ->{ report( "B" ) } }, { check: nil }
|
409
|
+
c.new( p: "x" ).errors_for( :p ).should == [ "A", "B" ]
|
410
|
+
c.new( q: "x" ).errors_for( :q ).should == [ "B" ]
|
411
|
+
c.new( r: "x" ).errors_for( :q ).should == []
|
412
|
+
|
413
|
+
c = Class.new( FormInput )
|
414
|
+
c.param :p, { test: ->( value ){ report( "A" ) } }, { test: ->( value ){ report( "B" ) } }
|
415
|
+
c.param :q, { test: ->( value ){ report( "A" ) } }, { test: nil }, { test: ->( value ){ report( "B" ) } }
|
416
|
+
c.param :r, { test: ->( value ){ report( "A" ) } }, { test: ->( value ){ report( "B" ) } }, { test: nil }
|
417
|
+
c.new( p: "x" ).errors_for( :p ).should == [ "A", "B" ]
|
418
|
+
c.new( q: "x" ).errors_for( :q ).should == [ "B" ]
|
419
|
+
c.new( r: "x" ).errors_for( :q ).should == []
|
420
|
+
|
421
|
+
for name in [:reject, :match, :match_key]
|
422
|
+
c = Class.new( FormInput )
|
423
|
+
c.param :p, { name => /\d/ }, { name => /[A-Z]/ }
|
424
|
+
c.param :q, { name => /\d/ }, { name => nil }, { name => /[A-Z]/ }
|
425
|
+
c.param :r, { name => /\d/ }, { name => /[A-Z]/ }, { name => nil }
|
426
|
+
c[ :p ][ name ].should == /[A-Z]/
|
427
|
+
c[ :q ][ name ].should == /[A-Z]/
|
428
|
+
c[ :r ][ name ].should == nil
|
429
|
+
end
|
430
|
+
end
|
431
|
+
|
383
432
|
should 'convert to/from internal value format' do
|
384
433
|
c = Class.new( FormInput )
|
385
434
|
c.param :str
|
@@ -1224,6 +1273,19 @@ describe FormInput do
|
|
1224
1273
|
f[].errors_for( :password ).should == [ "bad" ]
|
1225
1274
|
f[].error_for( :password ).should == "bad"
|
1226
1275
|
|
1276
|
+
f = TestForm.new.report!( :query, "important" ).report( :query, "less important" )
|
1277
|
+
f.errors.should == { query: [ "important", "q is required", "less important" ] }
|
1278
|
+
f.error_messages.should == [ "important" ]
|
1279
|
+
f.errors_for( :query ).should == [ "important", "q is required", "less important" ]
|
1280
|
+
f.error_for( :query ).should == "important"
|
1281
|
+
|
1282
|
+
f = TestForm.new
|
1283
|
+
f.param( :query ).report( "less important" ).report!( "important" )
|
1284
|
+
f.errors.should == { query: [ "important", "q is required", "less important" ] }
|
1285
|
+
f.error_messages.should == [ "important" ]
|
1286
|
+
f.errors_for( :query ).should == [ "important", "q is required", "less important" ]
|
1287
|
+
f.error_for( :query ).should == "important"
|
1288
|
+
|
1227
1289
|
f = TestForm.new
|
1228
1290
|
f.should.be.invalid
|
1229
1291
|
f.set( query: "x" ).should.be.valid
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: form_input
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Patrik Rak
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-03-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rack
|
@@ -86,6 +86,7 @@ extensions: []
|
|
86
86
|
extra_rdoc_files: []
|
87
87
|
files:
|
88
88
|
- ".yardopts"
|
89
|
+
- CHANGELOG.md
|
89
90
|
- LICENSE
|
90
91
|
- README.md
|
91
92
|
- Rakefile
|