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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4014e07ca32e3c7a76ee15db0dfe478a4103d123
4
- data.tar.gz: 83224f22dc199d2a3f1bf4d46011f616195d33ca
3
+ metadata.gz: c46667c81eb96ef6deeaf13501e06f6bc328b862
4
+ data.tar.gz: e6dc22529b1fdfead38c01c5bd2d6f5b2e1fc52a
5
5
  SHA512:
6
- metadata.gz: 82f8812fbd77215e7a058f1585bc7b2ee2a5082215d4247ae865b8ced6e2c739c39e836741482ebf4cb089fe57b6c330f8b19726d8998ed8cfca48910faf92ba
7
- data.tar.gz: e2e6853f4eb58193d11aa22696164844130c5c653df6b872372a40bfa1d790a8b61cf45bd287046cf7c375c14326709c49d907ba51e5779f0d3a72ad9ff12152
6
+ metadata.gz: 178de263faf14e4621298bfdee13025cd0852020178448f9370d4c27904c9a9a5bbad2c8fb250a55ee10051c370716f23b42eadeec89a4c157055aa12b444bf7
7
+ data.tar.gz: e62589e13773fd867abbd1bec66a66dad851bda8214968820348ac3566e612ffe48e702a93d1928b5f505c8b53b7d06591923a67969b19e1989979ec3bf2f275
@@ -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-nil parameters.
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! methods for late reporting of the most fundamental errors.
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) [![Dependency Status](https://img.shields.io/gemnasium/raxoft/form_input.svg)](https://gemnasium.com/raxoft/form_input) [![Code Climate](https://img.shields.io/codeclimate/github/raxoft/form_input.svg)](https://codeclimate.com/github/raxoft/form_input) [![Coverage](https://img.shields.io/codeclimate/coverage/github/raxoft/form_input.svg)](https://codeclimate.com/github/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 ) # NEVER EVER DO THIS!
798
- form = ContactForm.new.import( params ) # Do this instead if you need to.
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/contact' do
806
- form = ContactForm.new.import( json_data )
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 even empty strings, arrays, and hashes
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
- The `nil` values are still filtered out, though.
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/contact' do
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
 
@@ -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 //
@@ -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
- if value = request[ param.code ]
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 non-nil parameters,
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 non-nil parameters as a hash.
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
- params.each{ |x| result[ x.code ] = x.value unless x.value.nil? }
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
- result = dup
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
- result = dup
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? }
@@ -3,7 +3,7 @@
3
3
  class FormInput
4
4
  module Version
5
5
  MAJOR = 1
6
- MINOR = 2
6
+ MINOR = 3
7
7
  PATCH = 0
8
8
  STRING = [ MAJOR, MINOR, PATCH ].join( '.' ).freeze
9
9
  end
@@ -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
- f = TestForm.from_data(data.merge(password: nil))
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
@@ -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.2.0
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-06-21 00:00:00.000000000 Z
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