diff --git a/Gemfile.lock b/Gemfile.lock index 301191c..3e298ab 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - decanter (4.0.4) + decanter (4.1.0) actionpack (>= 4.2.10) activesupport rails-html-sanitizer (>= 1.0.4) diff --git a/README.md b/README.md index 8ebd332..82ae997 100644 --- a/README.md +++ b/README.md @@ -185,6 +185,12 @@ input :start_date, :date, parse_format: '%Y-%m-%d' | `DateParser`| `parse_format` | `'%m/%d/%Y'`| Accepts any format string accepted by Ruby's `strftime` method | `DateTimeParser` | `parse_format` | `'%m/%d/%Y %I:%M:%S %p'` | Accepts any format string accepted by Ruby's `strftime` method +`:boolean` will parse values of `true` and `1` as truthy. If another value is expected to be truthy, use the option `truth_value` to assign a custom truthy case. + +```ruby +input :checkbox, :boolean, truth_value: 'yes' +``` + ### Exceptions By default, `Decanter#decant` will raise an exception when unexpected parameters are passed. To override this behavior, you can change the strict mode option to one of: diff --git a/lib/decanter/parser/boolean_parser.rb b/lib/decanter/parser/boolean_parser.rb index 5ac6ca4..0c8bd65 100644 --- a/lib/decanter/parser/boolean_parser.rb +++ b/lib/decanter/parser/boolean_parser.rb @@ -5,6 +5,19 @@ class BooleanParser < ValueParser allow TrueClass, FalseClass parser do |val, options| + normalized_val = normalize(val) + next if normalized_val.nil? + + true_values = ['1', 'true'] + + option_val = options.fetch(:true_value, nil) + normalized_option = normalize(option_val) + + true_values << normalized_option if normalized_option + true_values.find {|tv| !!/#{tv}/i.match(normalized_val)}.present? + end + + def self.normalize(value) raise Decanter::ParseError.new 'Expects a single value' if val.is_a? Array next if (val.nil? || val === '') [1, '1'].include?(val) || !!/^true$/i.match?(val.to_s) diff --git a/lib/decanter/version.rb b/lib/decanter/version.rb index 09aa6a1..41bd3a3 100644 --- a/lib/decanter/version.rb +++ b/lib/decanter/version.rb @@ -1,3 +1,3 @@ module Decanter - VERSION = '4.0.4'.freeze + VERSION = '4.1.0'.freeze end diff --git a/spec/decanter/parser/boolean_parser_spec.rb b/spec/decanter/parser/boolean_parser_spec.rb index 3f0493c..f950c3b 100644 --- a/spec/decanter/parser/boolean_parser_spec.rb +++ b/spec/decanter/parser/boolean_parser_spec.rb @@ -12,7 +12,6 @@ ['boolean', true], ['string', 'true'], ['string', 'True'], - ['string', 'truE'] ] falses = [ @@ -20,8 +19,22 @@ ['number', 2], ['string', '2'], ['boolean', false], - ['string', 'tru'], - ['string', 'not true'] + ] + + trues_with_options = [ + ['string', 'yes', 'string', 'yes'], + ['string', 'Yes', 'string', 'yes'], + ['string', 'is true', 'string', 'is true'], + ['string', 'is truE', 'string', 'is True'], + ['number', 3, 'number', 3], + ['number', 3, 'string', '3'], + ['string', '3', 'number', 3], + ['string', 'false', 'string', 'false'], + ['string', 'false', 'string', 'False'], + ] + + falses_with_options = [ + ['string', 'yes', 'string', ''] ] let(:name) { :foo } @@ -62,5 +75,33 @@ .to raise_error(Decanter::ParseError) end end + + context 'returns true with options for' do + trues_with_options.each do |cond| + it "#{cond[0]}: #{cond[1]}, option: {#{cond[2]}: #{cond[3]}}" do + expect(parser.parse(name, cond[1], true_value: cond[3])).to match({name => true}) + end + end + end + + context 'returns false with options for' do + falses_with_options.each do |cond| + it "#{cond[0]}: #{cond[1]}, option: {#{cond[2]}: #{cond[3]}}" do + expect(parser.parse(name, cond[1], true_value: cond[3])).to match({name => false}) + end + end + end + + context 'with empty string and empty options' do + it 'returns nil' do + expect(parser.parse(name, '', true_value: '')).to match({name => nil}) + end + end + + context 'with nil and nil options' do + it 'returns nil' do + expect(parser.parse(name, nil, true_value: nil)).to match({name => nil}) + end + end end end