diff --git a/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb b/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb index 9d3d0f787..e066f482f 100644 --- a/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb +++ b/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb @@ -438,7 +438,8 @@ def given_numeric_column? private def column_type - if @subject.class.respond_to?(:columns_hash) + if @subject.class.respond_to?(:columns_hash) && + @subject.class.columns_hash[@attribute.to_s] @subject.class.columns_hash[@attribute.to_s].type end end diff --git a/spec/unit/shoulda/matchers/active_model/validate_numericality_of_matcher_spec.rb b/spec/unit/shoulda/matchers/active_model/validate_numericality_of_matcher_spec.rb index 31d2d8af3..eb5e99b5b 100644 --- a/spec/unit/shoulda/matchers/active_model/validate_numericality_of_matcher_spec.rb +++ b/spec/unit/shoulda/matchers/active_model/validate_numericality_of_matcher_spec.rb @@ -127,6 +127,13 @@ def default_validation_values expect(record).to validate_numericality end + context 'when the attribute is a virtual' do + it 'accepts' do + record = build_record_validating_numericality_of_virtual_attribute + expect(record).to validate_virtual_attribute_numericality + end + end + context 'when the column is an integer column' do it 'raises an IneffectiveTestError' do record = build_record_validating_numericality( @@ -224,6 +231,15 @@ def default_validation_values expect(record).to validate_numericality.odd end + context 'when the attribute is a virtual' do + it 'accepts' do + record = build_record_validating_numericality_of_virtual_attribute( + odd: true, + ) + expect(record).to validate_virtual_attribute_numericality.odd + end + end + context 'when the column is an integer column' do it 'accepts (and does not raise an error)' do record = build_record_validating_numericality( @@ -278,6 +294,15 @@ def default_validation_values expect(record).to validate_numericality.even end + context 'when the attribute is a virtual' do + it 'accepts' do + record = build_record_validating_numericality_of_virtual_attribute( + even: true, + ) + expect(record).to validate_virtual_attribute_numericality.even + end + end + context 'when the column is an integer column' do it 'accepts (and does not raise an error)' do record = build_record_validating_numericality( @@ -332,6 +357,16 @@ def default_validation_values expect(record).to validate_numericality.is_less_than_or_equal_to(18) end + context 'when the attribute is a virtual' do + it 'accepts' do + record = build_record_validating_numericality_of_virtual_attribute( + less_than_or_equal_to: 18, + ) + expect(record).to validate_virtual_attribute_numericality. + is_less_than_or_equal_to(18) + end + end + context 'when the column is an integer column' do it 'accepts (and does not raise an error)' do record = build_record_validating_numericality( @@ -390,6 +425,16 @@ def default_validation_values is_less_than(18) end + context 'when the attribute is a virtual' do + it 'accepts' do + record = build_record_validating_numericality_of_virtual_attribute( + less_than: 18, + ) + expect(record).to validate_virtual_attribute_numericality. + is_less_than(18) + end + end + context 'when the column is an integer column' do it 'accepts (and does not raise an error)' do record = build_record_validating_numericality( @@ -446,6 +491,16 @@ def default_validation_values expect(record).to validate_numericality.is_equal_to(18) end + context 'when the attribute is a virtual' do + it 'accepts' do + record = build_record_validating_numericality_of_virtual_attribute( + equal_to: 18, + ) + expect(record).to validate_virtual_attribute_numericality. + is_equal_to(18) + end + end + context 'when the column is an integer column' do it 'accepts (and does not raise an error)' do record = build_record_validating_numericality( @@ -504,6 +559,16 @@ def default_validation_values is_greater_than_or_equal_to(18) end + context 'when the attribute is a virtual' do + it 'accepts' do + record = build_record_validating_numericality_of_virtual_attribute( + greater_than_or_equal_to: 18, + ) + expect(record).to validate_virtual_attribute_numericality. + is_greater_than_or_equal_to(18) + end + end + context 'when the column is an integer column' do it 'accepts (and does not raise an error)' do record = build_record_validating_numericality( @@ -568,6 +633,16 @@ def default_validation_values is_greater_than(18) end + context 'when the attribute is a virtual' do + it 'accepts' do + record = build_record_validating_numericality_of_virtual_attribute( + greater_than: 18, + ) + expect(record).to validate_virtual_attribute_numericality. + is_greater_than(18) + end + end + context 'when the column is an integer column' do it 'accepts (and does not raise an error)' do record = build_record_validating_numericality( @@ -1141,6 +1216,21 @@ def define_model_validating_numericality(options = {}) end end + def define_model_validating_numericality_of_virtual_attribute(options = {}) + virtual_attr = options.delete(:virtual_attribute) do + virtual_attribute_name + end + + define_model 'Example' do |model| + model.send(:attr_accessor, virtual_attr) + model.validates_numericality_of(virtual_attr, options) + end + end + + def build_record_validating_numericality_of_virtual_attribute(options = {}) + define_model_validating_numericality_of_virtual_attribute(options).new + end + def build_record_validating_numericality(options = {}) define_model_validating_numericality(options).new end @@ -1157,7 +1247,15 @@ def validate_numericality validate_numericality_of(attribute_name) end + def validate_virtual_attribute_numericality + validate_numericality_of(virtual_attribute_name) + end + def attribute_name :attr end + + def virtual_attribute_name + :virtual_attr + end end