allow_value: Fix compatibility with enum columns
When used against an attribute that's an enum, `allow_value` will raise an AttributeValueChangedError. This commit prevents that from happening.
This commit is contained in:
parent
335971a87c
commit
9e8603eb74
21
NEWS.md
21
NEWS.md
|
@ -1,5 +1,17 @@
|
|||
# HEAD
|
||||
|
||||
### Bug fixes
|
||||
|
||||
* Update `validate_numericality_of` so that submatchers are applied lazily
|
||||
instead of immediately. Previously, qualifiers were order-dependent, meaning
|
||||
that if you used `strict` before you used, say, `odd`, then `strict` wouldn't
|
||||
actually apply to `odd`. Now the order that you specify qualifiers doesn't
|
||||
matter.
|
||||
|
||||
* Fix `allow_value` so that it does not raise an AttributeChangedValueError
|
||||
(formerly CouldNotSetAttributeError) when used against an attribute that is an
|
||||
enum in an ActiveRecord model.
|
||||
|
||||
### Improvements
|
||||
|
||||
* Improve failure messages and descriptions of all matchers across the board so
|
||||
|
@ -7,15 +19,12 @@
|
|||
(You'll see a huge difference in the output of the numericality and uniqueness
|
||||
matchers in particular.)
|
||||
|
||||
* The CouldNotSetAttributeError that you have probably seen is now called
|
||||
AttributeChangedValueError.
|
||||
|
||||
* Matchers now raise an error if any attributes that the matcher is attempting
|
||||
to set do not exist on the model.
|
||||
|
||||
* Update `validate_numericality_of` so that submatchers are applied lazily
|
||||
instead of immediately. Previously, qualifiers were order-dependent, meaning
|
||||
that if you used `strict` before you used, say, `odd`, then `strict` wouldn't
|
||||
actually apply to `odd`. Now the order that you specify qualifiers doesn't
|
||||
matter.
|
||||
|
||||
* Update `validate_numericality_of` so that it doesn't always run all of the
|
||||
submatchers, but stops on the first one that fails. Since failure messages
|
||||
now contain information as to what value the matcher set on the attribute when
|
||||
|
|
|
@ -78,7 +78,7 @@ module Shoulda
|
|||
|
||||
@result_of_checking = successful_check
|
||||
|
||||
if attribute_changed_value? && !ignoring_interference_by_writer?
|
||||
if raise_attribute_changed_value_error?
|
||||
@result_of_setting = attribute_changed_value_error
|
||||
false
|
||||
else
|
||||
|
@ -156,6 +156,33 @@ module Shoulda
|
|||
!!@ignoring_interference_by_writer
|
||||
end
|
||||
|
||||
def raise_attribute_changed_value_error?
|
||||
attribute_changed_value? &&
|
||||
!(attribute_is_an_enum? && value_read_is_expected_for_an_enum?) &&
|
||||
!ignoring_interference_by_writer?
|
||||
end
|
||||
|
||||
def attribute_is_an_enum?
|
||||
enum_values.any?
|
||||
end
|
||||
|
||||
def value_read_is_expected_for_an_enum?
|
||||
enum_values.key?(value_read) &&
|
||||
enum_values[value_read] == value_written
|
||||
end
|
||||
|
||||
def enum_values
|
||||
defined_enums.fetch(attribute_name.to_s, {})
|
||||
end
|
||||
|
||||
def defined_enums
|
||||
if model.respond_to?(:defined_enums)
|
||||
model.defined_enums
|
||||
else
|
||||
{}
|
||||
end
|
||||
end
|
||||
|
||||
def successful_check
|
||||
SuccessfulCheck.new
|
||||
end
|
||||
|
@ -192,6 +219,10 @@ module Shoulda
|
|||
def active_resource_object?
|
||||
object.respond_to?(:known_attributes)
|
||||
end
|
||||
|
||||
def model
|
||||
object.class
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -641,4 +641,18 @@ value", but that attribute does not exist.
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
if active_record_supports_enum?
|
||||
context 'given an ActiveRecord model' do
|
||||
context 'where the attribute under test is an enum and the given value is a value in that enum' do
|
||||
it 'accepts' do
|
||||
model = define_model('Shipment', status: :integer) do
|
||||
enum status: { pending: 1, shipped: 2, delivered: 3 }
|
||||
end
|
||||
|
||||
expect(model.new).to allow_value(1).for(:status)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue