Skip to content

Commit

Permalink
Numericality validation of virtual attributes
Browse files Browse the repository at this point in the history
Commit #18b2859d2522a4866c398b9a32ebc3de4ec79389 broke numericality
validation of virtual attributes in ActiveRecord models. This commit
added a `column_type` method that assumes if `columns_hash` is a thing
then our attribute would be present within it. This is not true for
virtual attributes and leads to:
```
     NoMethodError:
           undefined method `type' for nil:NilClass
         # /Users/bdmac/.gem/ruby/2.2.2/gems/shoulda-matchers-3.0.1/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb:442:in
         # `column_type'
```

This adds a check to `column_type` to return nil instead of throwing an
exception if a specified attribute does not exist in the `columns_hash`
because it is virtual.
  • Loading branch information
bdmac committed Oct 28, 2015
1 parent b28b0e1 commit a12fe86
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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
Expand All @@ -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

0 comments on commit a12fe86

Please sign in to comment.