form_input 1.2.0 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -3
- data/README.md +34 -12
- data/example/example.rb +97 -0
- data/lib/form_input/core.rb +38 -14
- data/lib/form_input/version.rb +1 -1
- data/test/test_core.rb +56 -4
- data/test/test_types.rb +33 -7
- 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: c46667c81eb96ef6deeaf13501e06f6bc328b862
|
4
|
+
data.tar.gz: e6dc22529b1fdfead38c01c5bd2d6f5b2e1fc52a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 178de263faf14e4621298bfdee13025cd0852020178448f9370d4c27904c9a9a5bbad2c8fb250a55ee10051c370716f23b42eadeec89a4c157055aa12b444bf7
|
7
|
+
data.tar.gz: e62589e13773fd867abbd1bec66a66dad851bda8214968820348ac3566e612ffe48e702a93d1928b5f505c8b53b7d06591923a67969b19e1989979ec3bf2f275
|
data/CHANGELOG.md
CHANGED
@@ -1,12 +1,19 @@
|
|
1
|
+
= 1.3.0
|
2
|
+
|
3
|
+
* Further improvements for JSON payloads:
|
4
|
+
* Added set of methods for distinguishing between set and unset parameters.
|
5
|
+
* The `import` now properly handles parameters with `nil` and `false` values.
|
6
|
+
* The `to_data` method now returns all set parameters, regardless of their value.
|
7
|
+
|
1
8
|
= 1.2.0
|
2
9
|
|
3
10
|
* Few changes for easier import and export of JSON payloads:
|
4
|
-
* The import and the new from_data methods now support numeric, boolean, and nil values natively.
|
5
|
-
* Added to_data method which creates a hash of all non
|
11
|
+
* The `import` and the new `from_data` methods now support numeric, boolean, and `nil` values natively.
|
12
|
+
* Added `to_data` method which creates a hash of all non-`nil` parameters.
|
6
13
|
|
7
14
|
= 1.1.0
|
8
15
|
|
9
|
-
* Added report
|
16
|
+
* Added `report!` methods for late reporting of the most fundamental errors.
|
10
17
|
|
11
18
|
* Added support for multiple `check` and `test` validation callbacks.
|
12
19
|
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Form input
|
2
2
|
|
3
|
-
[![Gem Version](https://img.shields.io/gem/v/form_input.svg)](http://rubygems.org/gems/form_input) [![Build Status](https://travis-ci.org/raxoft/form_input.svg?branch=master)](http://travis-ci.org/raxoft/form_input) [![
|
3
|
+
[![Gem Version](https://img.shields.io/gem/v/form_input.svg)](http://rubygems.org/gems/form_input) [![Build Status](https://travis-ci.org/raxoft/form_input.svg?branch=master)](http://travis-ci.org/raxoft/form_input) [![Maintainability](https://api.codeclimate.com/v1/badges/ea19d227eb1285d59860/maintainability)](https://codeclimate.com/github/raxoft/form_input/maintainability) [![Coverage](https://api.codeclimate.com/v1/badges/ea19d227eb1285d59860/test_coverage)](https://codeclimate.com/github/raxoft/form_input/test_coverage)
|
4
4
|
|
5
5
|
Form input is a gem which helps dealing with web request input and with the creation of HTML forms.
|
6
6
|
|
@@ -794,16 +794,19 @@ to include parts of the URL as the form input:
|
|
794
794
|
|
795
795
|
``` ruby
|
796
796
|
get '/contact/:email' do
|
797
|
-
form = ContactForm.new( params )
|
798
|
-
form = ContactForm.new.import( params )
|
797
|
+
form = ContactForm.new( params ) # NEVER EVER DO THIS!
|
798
|
+
form = ContactForm.new.import( params ) # Do this instead (or use from_params).
|
799
|
+
...
|
799
800
|
end
|
800
801
|
```
|
801
802
|
|
802
803
|
Similarly, you want to use `import` when feeding form input with JSON data (see [JSON Helpers](#json-helpers) for details):
|
803
804
|
|
804
805
|
``` ruby
|
805
|
-
post '/api/v1/
|
806
|
-
form = ContactForm.new
|
806
|
+
post '/api/v1/contacts' do
|
807
|
+
form = ContactForm.new( json_data ) # NEVER EVER DO THIS!
|
808
|
+
form = ContactForm.new.import( json_data ) # Do this instead (or use from_data).
|
809
|
+
...
|
807
810
|
end
|
808
811
|
```
|
809
812
|
|
@@ -829,6 +832,14 @@ You can either clear the entire form, named parameters, or parameter subsets (wh
|
|
829
832
|
form.clear( form.disabled_params )
|
830
833
|
```
|
831
834
|
|
835
|
+
The `unset` method works the same way, except that it always requires an argument:
|
836
|
+
|
837
|
+
``` ruby
|
838
|
+
form.unset( :message )
|
839
|
+
form.unset( :name, :company )
|
840
|
+
form.unset( form.invalid_params )
|
841
|
+
```
|
842
|
+
|
832
843
|
Alternatively, you can create form copies with just a subset of parameters set:
|
833
844
|
|
834
845
|
``` ruby
|
@@ -1165,6 +1176,9 @@ In fact, the parameter has a dozen of simple boolean getters like this which you
|
|
1165
1176
|
p.empty? # Is the value nil or empty?
|
1166
1177
|
p.filled? # Is the value neither nil nor empty?
|
1167
1178
|
|
1179
|
+
p.set? # Was the parameter value set to something?
|
1180
|
+
p.unset? # Was the parameter value not set to anything?
|
1181
|
+
|
1168
1182
|
p.required? # Is the parameter required?
|
1169
1183
|
p.optional? # Is the parameter not required?
|
1170
1184
|
|
@@ -1193,6 +1207,8 @@ The following methods are available:
|
|
1193
1207
|
form.blank_params # Parameters with nil, empty, or blank value.
|
1194
1208
|
form.empty_params # Parameters with nil or empty value.
|
1195
1209
|
form.filled_params # Parameters with some non-empty value.
|
1210
|
+
form.set_params # Parameters whose value was set to something.
|
1211
|
+
form.unset_params # Parameters whose value was not set to anything.
|
1196
1212
|
form.required_params # Parameters which are required and have to be filled.
|
1197
1213
|
form.optional_params # Parameters which are not required and can be nil or empty.
|
1198
1214
|
form.disabled_params # Parameters which are disabled and shall be rendered as such.
|
@@ -1349,8 +1365,9 @@ The only difference is that the [input filter](#input-filter) is not run in such
|
|
1349
1365
|
The [input transform](#input-transform) is run as usual,
|
1350
1366
|
and so are all the [validation methods](#errors-and-validation).
|
1351
1367
|
|
1352
|
-
Among other things this means that you can declare a parameter as integer using the `INTEGER_ARGS` macro
|
1368
|
+
Among other things this means that you can declare a parameter as integer using the `INTEGER_ARGS` macro
|
1353
1369
|
and pass in the value as either string or integer, and you end up with integer in both cases, which is pretty convenient.
|
1370
|
+
Of course, this works similarly for `FLOAT_ARGS` and `BOOL_ARGS`, too:
|
1354
1371
|
|
1355
1372
|
``` ruby
|
1356
1373
|
class NumericInput < FormInput
|
@@ -1363,10 +1380,11 @@ and pass in the value as either string or integer, and you end up with integer i
|
|
1363
1380
|
```
|
1364
1381
|
|
1365
1382
|
Another difference when dealing with JSON data is that
|
1366
|
-
the empty strings have completely different significance than in case of web forms.
|
1367
|
-
For this reason, the result of the `to_data` method includes
|
1383
|
+
the empty strings have completely different significance than in the case of the web forms.
|
1384
|
+
For this reason, the result of the `to_data` method includes any set parameters,
|
1385
|
+
even if the values are empty strings, arrays, or hashes
|
1368
1386
|
(unlike the `to_hash` and `to_params` methods).
|
1369
|
-
|
1387
|
+
Even the `nil` values are included for parameters which were explicitly set to `nil`:
|
1370
1388
|
|
1371
1389
|
``` ruby
|
1372
1390
|
class OptionalInput < FormInput
|
@@ -1376,6 +1394,7 @@ The `nil` values are still filtered out, though.
|
|
1376
1394
|
end
|
1377
1395
|
|
1378
1396
|
OptionalInput.from_data( string: '' ).to_data # { string: '' }
|
1397
|
+
OptionalInput.from_data( string: nil ).to_data # { string: nil }
|
1379
1398
|
OptionalInput.from_data( array: [] ).to_data # { array: [] }
|
1380
1399
|
OptionalInput.from_data( hash: {} ).to_data # { hash: {} }
|
1381
1400
|
```
|
@@ -1384,19 +1403,22 @@ The whole JSON processing may in the end look something like this:
|
|
1384
1403
|
|
1385
1404
|
``` ruby
|
1386
1405
|
require 'oj'
|
1406
|
+
|
1387
1407
|
def json_data
|
1388
|
-
data = Oj.load( request.body, symbolize_keys: true )
|
1408
|
+
data = Oj.load( request.body, mode: :strict, symbolize_keys: true )
|
1389
1409
|
halt( 422, 'Invalid data' ) unless Hash === data
|
1390
1410
|
data
|
1391
1411
|
rescue Oj::Error
|
1392
1412
|
halt( 422, 'Invalid JSON' )
|
1393
1413
|
end
|
1394
1414
|
|
1395
|
-
post '/api/v1/
|
1415
|
+
post '/api/v1/contacts' do
|
1396
1416
|
input = ContactForm.from_data( json_data )
|
1397
1417
|
halt( 422, "Invalid data: #{input.error_messages.first}" ) unless input.valid?
|
1398
1418
|
# Somehow use the input.
|
1399
|
-
Contact.create( input.to_data )
|
1419
|
+
entry = Contact.create( input.to_data )
|
1420
|
+
content_type :json
|
1421
|
+
[ 201, Oj.dump( entry.to_hash ) ]
|
1400
1422
|
end
|
1401
1423
|
```
|
1402
1424
|
|
data/example/example.rb
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# Simple but functional example FormInput application for Sinatra.
|
4
|
+
#
|
5
|
+
# You will need the following gems:
|
6
|
+
# gem install sinatra sinatra-partial slim form_input
|
7
|
+
#
|
8
|
+
# Then just run it like this:
|
9
|
+
# ruby example.rb
|
10
|
+
|
11
|
+
require 'sinatra'
|
12
|
+
require 'sinatra/partial'
|
13
|
+
require 'slim/smart'
|
14
|
+
require 'form_input'
|
15
|
+
|
16
|
+
# The example form. Feel free to experiment with changing this section to whatever you want to test.
|
17
|
+
|
18
|
+
class ExampleForm < FormInput
|
19
|
+
param! :email, 'Email address', EMAIL_ARGS
|
20
|
+
param! :name, 'Name'
|
21
|
+
param :company, 'Company'
|
22
|
+
param! :message, 'Message', 1000, type: :textarea, size: 6, filter: ->{ rstrip }
|
23
|
+
end
|
24
|
+
|
25
|
+
# Support for snippets.
|
26
|
+
|
27
|
+
set :partial_template_engine, :slim
|
28
|
+
helpers do
|
29
|
+
def snippet( name, opts = {}, **locals )
|
30
|
+
partial( "snippets/#{name}", opts.merge( locals: locals ) )
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# The whole application itself.
|
35
|
+
|
36
|
+
get '/' do
|
37
|
+
@form = ExampleForm.new( request )
|
38
|
+
slim :form
|
39
|
+
end
|
40
|
+
|
41
|
+
post '/' do
|
42
|
+
@form = ExampleForm.new( request )
|
43
|
+
return slim :form unless @form.valid? and params[:action] == 'post'
|
44
|
+
logger.info "These data were successfully posted: #{@form.to_hash.inspect}"
|
45
|
+
slim :post
|
46
|
+
end
|
47
|
+
|
48
|
+
# Inline templates follow.
|
49
|
+
|
50
|
+
__END__
|
51
|
+
|
52
|
+
@@ layout
|
53
|
+
doctype html
|
54
|
+
html
|
55
|
+
head
|
56
|
+
title = @title
|
57
|
+
meta charset='utf-8'
|
58
|
+
meta name='viewport' content='width=device-width, initial-scale=1, shrink-to-fit=no'
|
59
|
+
link rel='stylesheet' href='https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css' integrity='sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu' crossorigin='anonymous'
|
60
|
+
css:
|
61
|
+
label { width: 100%; }
|
62
|
+
body.container == yield
|
63
|
+
|
64
|
+
@@ form
|
65
|
+
.panel.panel-default
|
66
|
+
.panel-heading
|
67
|
+
= @title = "Example Form"
|
68
|
+
.panel-body
|
69
|
+
form method='post' action=request.path
|
70
|
+
fieldset
|
71
|
+
== snippet :form_panel, params: @form.params
|
72
|
+
button.btn.btn-default type='submit' name='action' value='post' Submit
|
73
|
+
- unless @form.empty?
|
74
|
+
.panel-footer
|
75
|
+
== partial :dump
|
76
|
+
|
77
|
+
@@ post
|
78
|
+
.panel.panel-default
|
79
|
+
.panel-heading
|
80
|
+
= @title = "Congratulations!"
|
81
|
+
All inputs are valid.
|
82
|
+
.panel-body
|
83
|
+
== partial :dump
|
84
|
+
form method='post' action=request.path
|
85
|
+
== snippet :form_hidden, params: @form.params
|
86
|
+
button.btn.btn-default type='submit' Go back
|
87
|
+
a.btn.btn-default< href=request.path Start over
|
88
|
+
|
89
|
+
@@ dump
|
90
|
+
p These are the filled form values:
|
91
|
+
dl.dl-horizontal
|
92
|
+
- for p in @form.filled_params
|
93
|
+
dt = p.form_title
|
94
|
+
dd
|
95
|
+
code = p.value.inspect
|
96
|
+
|
97
|
+
// EOF //
|
data/lib/form_input/core.rb
CHANGED
@@ -162,6 +162,16 @@ class FormInput
|
|
162
162
|
not empty?
|
163
163
|
end
|
164
164
|
|
165
|
+
# Test if value of given parameter was set.
|
166
|
+
def set?
|
167
|
+
form ? form.instance_variable_defined?( "@#{name}" ) : false
|
168
|
+
end
|
169
|
+
|
170
|
+
# Test if value of given parameter is not set.
|
171
|
+
def unset?
|
172
|
+
not set?
|
173
|
+
end
|
174
|
+
|
165
175
|
# Get the proper name for use in form names, adding [] to array and [key] to hash parameters.
|
166
176
|
def form_name( key = nil )
|
167
177
|
if array?
|
@@ -835,8 +845,10 @@ class FormInput
|
|
835
845
|
# Import parameter values from given request or hash. Applies parameter input filters and transforms as well.
|
836
846
|
# Returns self for chaining.
|
837
847
|
def import( request )
|
848
|
+
hash = request.respond_to?( :params ) ? request.params : request.to_hash
|
838
849
|
for name, param in @params
|
839
|
-
|
850
|
+
value = hash.fetch( param.code ) { hash.fetch( param.code.to_s, self ) }
|
851
|
+
unless value == self
|
840
852
|
value = sanitize_value( value, param.filter )
|
841
853
|
if transform = param.transform
|
842
854
|
value = value.instance_exec( &transform )
|
@@ -856,12 +868,20 @@ class FormInput
|
|
856
868
|
self
|
857
869
|
end
|
858
870
|
|
871
|
+
# Unset values of given parameters. Both names and parameters are accepted.
|
872
|
+
# Returns self for chaining.
|
873
|
+
def unset( name, *names )
|
874
|
+
clear( name, *names )
|
875
|
+
end
|
876
|
+
|
859
877
|
# Clear all/given parameter values. Both names and parameters are accepted.
|
860
878
|
# Returns self for chaining.
|
861
879
|
def clear( *names )
|
862
880
|
names = names.empty? ? params_names : validate_names( names )
|
863
881
|
for name in names
|
882
|
+
# Set the value to nil first so it triggers anything necessary.
|
864
883
|
self[ name ] = nil
|
884
|
+
remove_instance_variable( "@#{name}" )
|
865
885
|
end
|
866
886
|
self
|
867
887
|
end
|
@@ -883,7 +903,7 @@ class FormInput
|
|
883
903
|
end
|
884
904
|
|
885
905
|
# Return all non-empty parameters as a hash.
|
886
|
-
# See also #to_data, which creates a hash of
|
906
|
+
# See also #to_data, which creates a hash of set parameters,
|
887
907
|
# and #url_params, which creates a hash suitable for url output.
|
888
908
|
def to_hash
|
889
909
|
result = {}
|
@@ -892,13 +912,13 @@ class FormInput
|
|
892
912
|
end
|
893
913
|
alias to_h to_hash
|
894
914
|
|
895
|
-
# Return all
|
915
|
+
# Return all set parameters as a hash.
|
896
916
|
# Note that the keys are external names of the parameters (should they differ),
|
897
917
|
# so the keys created by `from_data(data).to_data` remain consistent.
|
898
918
|
# See also #to_hash, which creates a hash of non-empty parameters.
|
899
919
|
def to_data
|
900
920
|
result = {}
|
901
|
-
|
921
|
+
set_params.each{ |x| result[ x.code ] = x.value }
|
902
922
|
result
|
903
923
|
end
|
904
924
|
|
@@ -914,11 +934,7 @@ class FormInput
|
|
914
934
|
|
915
935
|
# Create copy of itself, with given parameters unset. Both names and parameters are accepted.
|
916
936
|
def except( *names )
|
917
|
-
|
918
|
-
for name in validate_names( names )
|
919
|
-
result[ name ] = nil
|
920
|
-
end
|
921
|
-
result
|
937
|
+
dup.clear( names )
|
922
938
|
end
|
923
939
|
|
924
940
|
# Create copy of itself, with only given parameters set. Both names and parameters are accepted.
|
@@ -926,11 +942,7 @@ class FormInput
|
|
926
942
|
# It would be easier to create new instance here and only copy selected values,
|
927
943
|
# but we want to use dup instead of new here, as the derived form can use
|
928
944
|
# different parameters in its construction.
|
929
|
-
|
930
|
-
for name in params_names - validate_names( names )
|
931
|
-
result[ name ] = nil
|
932
|
-
end
|
933
|
-
result
|
945
|
+
dup.clear( params_names - validate_names( names ) )
|
934
946
|
end
|
935
947
|
|
936
948
|
# Parameter lists.
|
@@ -990,6 +1002,18 @@ class FormInput
|
|
990
1002
|
end
|
991
1003
|
alias filled_parameters filled_params
|
992
1004
|
|
1005
|
+
# Get list of parameters whose values were set.
|
1006
|
+
def set_params
|
1007
|
+
params.select{ |x| x.set? }
|
1008
|
+
end
|
1009
|
+
alias set_parameters set_params
|
1010
|
+
|
1011
|
+
# Get list of parameters whose values were not set.
|
1012
|
+
def unset_params
|
1013
|
+
params.select{ |x| x.unset? }
|
1014
|
+
end
|
1015
|
+
alias unset_parameters unset_params
|
1016
|
+
|
993
1017
|
# Get list of required parameters.
|
994
1018
|
def required_params
|
995
1019
|
params.select{ |x| x.required? }
|
data/lib/form_input/version.rb
CHANGED
data/test/test_core.rb
CHANGED
@@ -782,6 +782,9 @@ describe FormInput do
|
|
782
782
|
names( f.empty_params ).should == [ :age, :rate, :password, :opts, :on ]
|
783
783
|
names( f.blank_params ).should == [ :email, :age, :rate, :password, :opts, :on ]
|
784
784
|
|
785
|
+
names( f.set_params ).should == [ :query, :email, :text, :password ]
|
786
|
+
names( f.unset_params ).should == [ :age, :rate, :opts, :on ]
|
787
|
+
|
785
788
|
names( f.tagged_params ).should == [ :age, :rate ]
|
786
789
|
names( f.untagged_params ).should == [ :query, :email, :text, :password, :opts, :on ]
|
787
790
|
|
@@ -857,6 +860,8 @@ describe FormInput do
|
|
857
860
|
p.should.not.be.blank
|
858
861
|
p.should.not.be.empty
|
859
862
|
p.should.be.filled
|
863
|
+
p.should.be.set
|
864
|
+
p.should.not.be.unset
|
860
865
|
p.should.be.valid
|
861
866
|
p.should.not.be.invalid
|
862
867
|
p.should.be.required
|
@@ -890,6 +895,8 @@ describe FormInput do
|
|
890
895
|
p.should.be.blank
|
891
896
|
p.should.not.be.empty
|
892
897
|
p.should.be.filled
|
898
|
+
p.should.be.set
|
899
|
+
p.should.not.be.unset
|
893
900
|
p.should.not.be.valid
|
894
901
|
p.should.be.invalid
|
895
902
|
p.should.not.be.required
|
@@ -914,6 +921,8 @@ describe FormInput do
|
|
914
921
|
p.should.be.blank
|
915
922
|
p.should.be.empty
|
916
923
|
p.should.not.be.filled
|
924
|
+
p.should.not.be.set
|
925
|
+
p.should.be.unset
|
917
926
|
p.should.be.disabled
|
918
927
|
p.should.not.be.enabled
|
919
928
|
p[ :tag ].should == :mix
|
@@ -942,6 +951,8 @@ describe FormInput do
|
|
942
951
|
p.should.be.blank
|
943
952
|
p.should.be.empty
|
944
953
|
p.should.not.be.filled
|
954
|
+
p.should.not.be.set
|
955
|
+
p.should.be.unset
|
945
956
|
p.should.be.array
|
946
957
|
p.should.not.be.hash
|
947
958
|
p.should.not.be.scalar
|
@@ -953,6 +964,8 @@ describe FormInput do
|
|
953
964
|
p.should.be.blank
|
954
965
|
p.should.be.empty
|
955
966
|
p.should.not.be.filled
|
967
|
+
p.should.not.be.set
|
968
|
+
p.should.be.unset
|
956
969
|
p.should.not.be.array
|
957
970
|
p.should.be.hash
|
958
971
|
p.should.not.be.scalar
|
@@ -990,6 +1003,8 @@ describe FormInput do
|
|
990
1003
|
f.except( [ :email, :query ] ).url_query.should == "text=foo"
|
991
1004
|
f.except( [] ).url_query.should == "q=x&email=a%40b&text=foo"
|
992
1005
|
|
1006
|
+
f.except( :email ).to_data.should == { q: 'x', text: 'foo' }
|
1007
|
+
|
993
1008
|
f.only( :email ).url_query.should == "email=a%40b"
|
994
1009
|
f.only( :email, :query ).url_query.should == "q=x&email=a%40b"
|
995
1010
|
f.only().url_query.should == ""
|
@@ -997,15 +1012,34 @@ describe FormInput do
|
|
997
1012
|
f.only( [ :email, :query ] ).url_query.should == "q=x&email=a%40b"
|
998
1013
|
f.only( [] ).url_query.should == ""
|
999
1014
|
|
1015
|
+
f.only( :email ).to_data.should == { email: 'a@b' }
|
1016
|
+
|
1017
|
+
d = f.dup
|
1018
|
+
d.unset( :text )
|
1019
|
+
d.should.not.be.empty
|
1020
|
+
d.url_query.should == "q=x&email=a%40b"
|
1021
|
+
d.to_data.should == { q: 'x', email: 'a@b' }
|
1022
|
+
d.unset( d.required_params )
|
1023
|
+
d.should.not.be.empty
|
1024
|
+
d.url_query.should == "email=a%40b"
|
1025
|
+
d.to_data.should == { email: 'a@b' }
|
1026
|
+
d.unset( [] )
|
1027
|
+
d.should.not.be.empty
|
1028
|
+
d.url_query.should == "email=a%40b"
|
1029
|
+
d.to_data.should == { email: 'a@b' }
|
1030
|
+
|
1000
1031
|
f.clear( :text )
|
1001
1032
|
f.should.not.be.empty
|
1002
1033
|
f.url_query.should == "q=x&email=a%40b"
|
1034
|
+
f.to_data.should == { q: 'x', email: 'a@b' }
|
1003
1035
|
f.clear( f.required_params )
|
1004
1036
|
f.should.not.be.empty
|
1005
1037
|
f.url_query.should == "email=a%40b"
|
1038
|
+
f.to_data.should == { email: 'a@b' }
|
1006
1039
|
f.clear
|
1007
1040
|
f.should.be.empty
|
1008
1041
|
f.url_query.should == ""
|
1042
|
+
f.to_data.should == {}
|
1009
1043
|
|
1010
1044
|
f = TestForm.new( { age: 2, query: "x" }, { rate: 1, query: "y" } )
|
1011
1045
|
f.url_query.should == "q=y&age=2&rate=1"
|
@@ -1052,6 +1086,8 @@ describe FormInput do
|
|
1052
1086
|
f.named_params( :typo, :missing ).should == [ nil, nil ]
|
1053
1087
|
|
1054
1088
|
->{ f.set( typo: 10 ) }.should.raise( NoMethodError )
|
1089
|
+
->{ f.unset() }.should.raise( ArgumentError )
|
1090
|
+
->{ f.unset( :typo ) }.should.raise( ArgumentError )
|
1055
1091
|
->{ f.clear( :typo ) }.should.raise( ArgumentError )
|
1056
1092
|
->{ f.except( :typo ) }.should.raise( ArgumentError )
|
1057
1093
|
->{ f.except( [ :typo ] ) }.should.raise( ArgumentError )
|
@@ -1109,6 +1145,7 @@ describe FormInput do
|
|
1109
1145
|
f = TestForm.new( query: true, age: 3, rate: 0.35, text: false, opts: [], on: {} )
|
1110
1146
|
->{ f.validate }.should.not.raise
|
1111
1147
|
f.to_hash.should == { query: true, age: 3, rate: 0.35, text: false }
|
1148
|
+
f.to_data.should == { q: true, age: 3, rate: 0.35, text: false, opts: [], on: {} }
|
1112
1149
|
f.url_params.should == { q: "true", age: "3", rate: "0.35", text: "false" }
|
1113
1150
|
f.url_query.should == "q=true&age=3&rate=0.35&text=false"
|
1114
1151
|
names( f.incorrect_params ).should == [ :query, :rate, :text ]
|
@@ -1116,6 +1153,7 @@ describe FormInput do
|
|
1116
1153
|
f = TestForm.new( opts: 1 )
|
1117
1154
|
->{ f.validate }.should.not.raise
|
1118
1155
|
f.to_hash.should == { opts: 1 }
|
1156
|
+
f.to_data.should == { opts: 1 }
|
1119
1157
|
f.url_params.should == { opts: [ "1" ] }
|
1120
1158
|
f.url_query.should == "opts[]=1"
|
1121
1159
|
names( f.incorrect_params ).should == [ :opts ]
|
@@ -1123,6 +1161,7 @@ describe FormInput do
|
|
1123
1161
|
f = TestForm.new( opts: [ 2.5, true ] )
|
1124
1162
|
->{ f.validate }.should.not.raise
|
1125
1163
|
f.to_hash.should == { opts: [ 2.5, true ] }
|
1164
|
+
f.to_data.should == { opts: [ 2.5, true ] }
|
1126
1165
|
f.url_params.should == { opts: [ "2.5", "true" ] }
|
1127
1166
|
f.url_query.should == "opts[]=2.5&opts[]=true"
|
1128
1167
|
names( f.incorrect_params ).should == []
|
@@ -1130,6 +1169,7 @@ describe FormInput do
|
|
1130
1169
|
f = TestForm.new( opts: { "foo" => 10, true => false } )
|
1131
1170
|
->{ f.validate }.should.not.raise
|
1132
1171
|
f.to_hash.should == { opts: { "foo" => 10, true => false } }
|
1172
|
+
f.to_data.should == { opts: { "foo" => 10, true => false } }
|
1133
1173
|
f.url_params.should == { opts: [ '["foo", 10]', '[true, false]' ] }
|
1134
1174
|
f.url_query.should == "opts[]=%5B%22foo%22%2C+10%5D&opts[]=%5Btrue%2C+false%5D"
|
1135
1175
|
names( f.incorrect_params ).should == [ :opts ]
|
@@ -1137,6 +1177,7 @@ describe FormInput do
|
|
1137
1177
|
f = TestForm.new( on: 1 )
|
1138
1178
|
->{ f.validate }.should.not.raise
|
1139
1179
|
f.to_hash.should == { on: 1 }
|
1180
|
+
f.to_data.should == { on: 1 }
|
1140
1181
|
f.url_params.should == { on: { "1" => "" } }
|
1141
1182
|
f.url_query.should == "on[1]="
|
1142
1183
|
names( f.incorrect_params ).should == [ :on ]
|
@@ -1144,6 +1185,7 @@ describe FormInput do
|
|
1144
1185
|
f = TestForm.new( on: { 0 => 1, 2 => 3.4 } )
|
1145
1186
|
->{ f.validate }.should.not.raise
|
1146
1187
|
f.to_hash.should == { on: { 0 => 1, 2 => 3.4 } }
|
1188
|
+
f.to_data.should == { on: { 0 => 1, 2 => 3.4 } }
|
1147
1189
|
f.url_params.should == { on: { "0" => "1", "2" => "3.4" } }
|
1148
1190
|
f.url_query.should == "on[0]=1&on[2]=3.4"
|
1149
1191
|
names( f.incorrect_params ).should == []
|
@@ -1151,6 +1193,7 @@ describe FormInput do
|
|
1151
1193
|
f = TestForm.new( on: [ [ 10, 20 ], [ true, false ] ] )
|
1152
1194
|
->{ f.validate }.should.not.raise
|
1153
1195
|
f.to_hash.should == { on: [ [ 10, 20 ], [ true, false ] ] }
|
1196
|
+
f.to_data.should == { on: [ [ 10, 20 ], [ true, false ] ] }
|
1154
1197
|
f.url_params.should == { on: { "10" => "20", "true" => "false" } }
|
1155
1198
|
f.url_query.should == "on[10]=20&on[true]=false"
|
1156
1199
|
names( f.incorrect_params ).should == [ :on ]
|
@@ -1158,6 +1201,7 @@ describe FormInput do
|
|
1158
1201
|
f = TestForm.new( on: [ 1, true, false ] )
|
1159
1202
|
->{ f.validate }.should.not.raise
|
1160
1203
|
f.to_hash.should == { on: [ 1, true, false ] }
|
1204
|
+
f.to_data.should == { on: [ 1, true, false ] }
|
1161
1205
|
f.url_params.should == { on: { "1" => "", "true" => "", "false" => "" } }
|
1162
1206
|
f.url_query.should == "on[1]=&on[true]=&on[false]="
|
1163
1207
|
names( f.incorrect_params ).should == [ :on ]
|
@@ -1172,6 +1216,7 @@ describe FormInput do
|
|
1172
1216
|
f.error_messages.should == [ "q must use valid encoding" ]
|
1173
1217
|
f.param( :query ).should.not.be.blank
|
1174
1218
|
f.to_hash.should == { query: s }
|
1219
|
+
f.to_data.should == { q: s }
|
1175
1220
|
f.url_params.should == { q: s }
|
1176
1221
|
f.url_query.should == "q=%FF"
|
1177
1222
|
|
@@ -1181,6 +1226,7 @@ describe FormInput do
|
|
1181
1226
|
f.error_messages.should == [ "q must use valid encoding" ]
|
1182
1227
|
f.param( :query ).should.not.be.blank
|
1183
1228
|
f.to_hash.should == { query: s.dup.force_encoding( 'BINARY' ) }
|
1229
|
+
f.to_data.should == { q: s.dup.force_encoding( 'BINARY' ) }
|
1184
1230
|
f.url_params.should == { q: s.dup.force_encoding( 'BINARY' ) }
|
1185
1231
|
f.url_query.should == "q=%FF"
|
1186
1232
|
end
|
@@ -1208,10 +1254,11 @@ describe FormInput do
|
|
1208
1254
|
opts: [],
|
1209
1255
|
on: {},
|
1210
1256
|
}
|
1211
|
-
f = TestForm.from_data(data)
|
1257
|
+
f = TestForm.from_data( data )
|
1212
1258
|
f.to_data.should == data
|
1213
1259
|
|
1214
|
-
|
1260
|
+
data[ :password ] = nil
|
1261
|
+
f = TestForm.from_data( data )
|
1215
1262
|
f.to_data.should == data
|
1216
1263
|
|
1217
1264
|
f.to_hash.should == {
|
@@ -1220,8 +1267,6 @@ describe FormInput do
|
|
1220
1267
|
age: 10,
|
1221
1268
|
rate: 0.5,
|
1222
1269
|
}
|
1223
|
-
f.valid?(:age).should.be.true # has filter and correct class
|
1224
|
-
f.valid?(:rate).should.be.false # has no filter and class
|
1225
1270
|
end
|
1226
1271
|
|
1227
1272
|
should 'make it easy to create URLs' do
|
@@ -1370,6 +1415,13 @@ describe FormInput do
|
|
1370
1415
|
f.dup.validate?.should.be.valid
|
1371
1416
|
f.validate.should.be.valid
|
1372
1417
|
f.validate!.should.be.valid
|
1418
|
+
|
1419
|
+
f.unset( :query ).should.equal f
|
1420
|
+
f.should.be.invalid
|
1421
|
+
f.validate?.should.be.invalid
|
1422
|
+
f.dup.validate?.should.be.invalid
|
1423
|
+
f.validate.should.be.invalid
|
1424
|
+
f.validate!.should.be.invalid
|
1373
1425
|
end
|
1374
1426
|
|
1375
1427
|
should 'support some custom error messages' do
|
data/test/test_types.rb
CHANGED
@@ -7,41 +7,40 @@ require 'form_input/types'
|
|
7
7
|
require 'rack/test'
|
8
8
|
|
9
9
|
class TestBasicTypesForm < FormInput
|
10
|
-
|
11
10
|
param :int, INTEGER_ARGS
|
12
11
|
param :float, FLOAT_ARGS
|
13
12
|
param :bool, BOOL_ARGS
|
14
13
|
param :checkbox, CHECKBOX_ARGS
|
14
|
+
end
|
15
15
|
|
16
|
+
class TestJSONTypesForm < FormInput
|
17
|
+
param :str
|
18
|
+
param :int, INTEGER_ARGS
|
19
|
+
param :float, FLOAT_ARGS
|
20
|
+
param :bool, BOOL_ARGS
|
16
21
|
end
|
17
22
|
|
18
23
|
class TestAddressTypesForm < FormInput
|
19
|
-
|
20
24
|
param :email, EMAIL_ARGS
|
21
25
|
param :zip, ZIP_ARGS
|
22
26
|
param :phone, PHONE_ARGS
|
23
|
-
|
24
27
|
end
|
25
28
|
|
26
29
|
class TestTimeTypesForm < FormInput
|
27
|
-
|
28
30
|
param :time, TIME_ARGS
|
29
31
|
param :us_date, US_DATE_ARGS
|
30
32
|
param :uk_date, UK_DATE_ARGS
|
31
33
|
param :eu_date, EU_DATE_ARGS
|
32
34
|
param :hours, HOURS_ARGS
|
33
|
-
|
34
35
|
end
|
35
36
|
|
36
37
|
class TestPrunedTypesForm < FormInput
|
37
|
-
|
38
38
|
param :str, PRUNED_ARGS
|
39
39
|
param :int, INTEGER_ARGS, PRUNED_ARGS
|
40
40
|
array :arr, PRUNED_ARGS
|
41
41
|
array :int_arr, INTEGER_ARGS, PRUNED_ARGS
|
42
42
|
hash :hsh, PRUNED_ARGS
|
43
43
|
hash :int_hsh, INTEGER_ARGS, PRUNED_ARGS
|
44
|
-
|
45
44
|
end
|
46
45
|
|
47
46
|
class Bacon::Context
|
@@ -131,6 +130,33 @@ describe FormInput do
|
|
131
130
|
f.url_query.should == "int=a&float=b&bool=false&checkbox=true"
|
132
131
|
end
|
133
132
|
|
133
|
+
should 'provide presets for standard JSON types' do
|
134
|
+
f = TestJSONTypesForm.from_data( {} )
|
135
|
+
f.should.be.valid
|
136
|
+
f.to_data.should == {}
|
137
|
+
|
138
|
+
f = TestJSONTypesForm.from_data( str: "foo", int: "0123", float: "0123.456", bool: "true" )
|
139
|
+
f.should.be.valid
|
140
|
+
f.to_data.should == { str: 'foo', int: 123, float: 123.456, bool: true }
|
141
|
+
|
142
|
+
f = TestJSONTypesForm.from_data( str: nil, int: 123, float: 123.456, bool: true )
|
143
|
+
f.should.be.valid
|
144
|
+
f.to_data.should == { str: nil, int: 123, float: 123.456, bool: true }
|
145
|
+
|
146
|
+
f = TestJSONTypesForm.from_data( bool: "false" )
|
147
|
+
f.should.be.valid
|
148
|
+
f.to_data.should == { bool: false }
|
149
|
+
|
150
|
+
f = TestJSONTypesForm.from_data( bool: false )
|
151
|
+
f.should.be.valid
|
152
|
+
f.to_data.should == { bool: false }
|
153
|
+
|
154
|
+
f = TestJSONTypesForm.from_data( int: "a", float: "b", bool: "c" )
|
155
|
+
f.should.be.invalid
|
156
|
+
names( f.invalid_params ).should == [ :int, :float ]
|
157
|
+
f.to_data.should == { int: "a", float: "b", bool: false }
|
158
|
+
end
|
159
|
+
|
134
160
|
should 'provide presets for address parameter types' do
|
135
161
|
f = TestAddressTypesForm.new( request( "?email=me@1.com&zip=12345&phone=123%20456%20789" ) )
|
136
162
|
f.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.3.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: 2019-
|
11
|
+
date: 2019-07-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rack
|
@@ -94,6 +94,7 @@ files:
|
|
94
94
|
- example/controllers/ramaze/profile.rb
|
95
95
|
- example/controllers/sinatra/press_release.rb
|
96
96
|
- example/controllers/sinatra/profile.rb
|
97
|
+
- example/example.rb
|
97
98
|
- example/forms/change_password_form.rb
|
98
99
|
- example/forms/login_form.rb
|
99
100
|
- example/forms/lost_password_form.rb
|