diff --git a/lib/shoulda/matchers/active_model/validate_inclusion_of_matcher.rb b/lib/shoulda/matchers/active_model/validate_inclusion_of_matcher.rb index 9bb63251b..32e356418 100644 --- a/lib/shoulda/matchers/active_model/validate_inclusion_of_matcher.rb +++ b/lib/shoulda/matchers/active_model/validate_inclusion_of_matcher.rb @@ -302,11 +302,6 @@ def in_range(range) self end - def allow_blank(allow_blank = true) - @options[:allow_blank] = allow_blank - self - end - def allow_nil(allow_nil = true) @options[:allow_nil] = allow_nil self @@ -362,20 +357,11 @@ def matches_for_range? def matches_for_array? allows_all_values_in_array? && - allows_blank_value? && + allow_blank_matches? && allows_nil_value? && disallows_value_outside_of_array? end - def allows_blank_value? - if @options.key?(:allow_blank) - blank_values = ['', ' ', "\n", "\r", "\t", "\f"] - @options[:allow_blank] == blank_values.all? { |value| allows_value_of(value) } - else - true - end - end - def allows_nil_value? if @options.key?(:allow_nil) @options[:allow_nil] == allows_value_of(nil) diff --git a/lib/shoulda/matchers/active_model/validate_length_of_matcher.rb b/lib/shoulda/matchers/active_model/validate_length_of_matcher.rb index 422de8932..c8a479df5 100644 --- a/lib/shoulda/matchers/active_model/validate_length_of_matcher.rb +++ b/lib/shoulda/matchers/active_model/validate_length_of_matcher.rb @@ -216,6 +216,27 @@ module ActiveModel # with_long_message('Secret key must be less than 100 characters') # end # + # ##### allow_blank + # + # Use `allow_blank` to assert that the attribute allows blank. + # + # class User + # include ActiveModel::Model + # attr_accessor :bio + # + # validates_length_of :bio, minimum: 15, allow_blank: true + # end + # + # # RSpec + # describe User do + # it { should validate_length_of(:bio).is_at_least(15).allow_blank } + # end + # + # # Test::Unit + # class UserTest < ActiveSupport::TestCase + # should validate_length_of(:bio).is_at_least(15).allow_blank + # end + # # @return [ValidateLengthOfMatcher] # def validate_length_of(attr) @@ -293,7 +314,7 @@ def description def matches?(subject) super(subject) translate_messages! - lower_bound_matches? && upper_bound_matches? + lower_bound_matches? && upper_bound_matches? && allow_blank_matches? end private diff --git a/lib/shoulda/matchers/active_model/validation_matcher.rb b/lib/shoulda/matchers/active_model/validation_matcher.rb index 0ac6fa88c..02b140ba2 100644 --- a/lib/shoulda/matchers/active_model/validation_matcher.rb +++ b/lib/shoulda/matchers/active_model/validation_matcher.rb @@ -19,6 +19,11 @@ def on(context) self end + def allow_blank + @options[:allow_blank] = true + self + end + def strict @strict = true self @@ -95,6 +100,15 @@ def disallow_value_matcher(value, message) def strict? @strict end + + def allow_blank_matches? + if @options.key?(:allow_blank) + blank_values = ['', ' ', "\n", "\r", "\t", "\f"] + @options[:allow_blank] == blank_values.all? { |value| allows_value_of(value) } + else + true + end + end end end end diff --git a/spec/unit/shoulda/matchers/active_model/validate_length_of_matcher_spec.rb b/spec/unit/shoulda/matchers/active_model/validate_length_of_matcher_spec.rb index f7330d35a..118846759 100644 --- a/spec/unit/shoulda/matchers/active_model/validate_length_of_matcher_spec.rb +++ b/spec/unit/shoulda/matchers/active_model/validate_length_of_matcher_spec.rb @@ -161,6 +161,27 @@ end end + context 'qualified with allow_blank' do + context 'and validating with allow_blank' do + it 'accepts' do + expect(validating_length(minimum: 2, allow_blank: true)). + to validate_length_of(:attr).is_at_least(2).allow_blank + end + end + + context 'and not validating with allow_blank' do + it 'rejects' do + assertion = lambda do + expect(validating_length(minimum: 2)). + to validate_length_of(:attr).is_at_least(2).allow_blank + end + expect(&assertion).to fail_with_message_including( + %[Did not expect errors when attr is set to ""] + ) + end + end + end + def validating_length(options = {}) define_model(:example, attr: :string) do validates_length_of :attr, options