Handle ensure_inclusion_of for boolean columns
Currently, using `ensure_inclusion_of` against a boolean column doesn't
work. We can assert that the column allows boolean values, but what
about values that should be rejected? Well, it depends on what you give
to `ensure_inclusion_of`. Here's how it works now:
* `ensure_inclusion_of(:attr).in_array([true])` asserts that false is
rejected
* `ensure_inclusion_of(:attr).in_array([false])` asserts that true is
rejected
* `ensure_inclusion_of(:attr).in_array([true, false])` does not assert
that anything is rejected, instead informing the developer how
this sort of expectation is not fully testable (anything other than
true, false, or nil will be converted to false).
* `ensure_inclusion_of(:attr).in_array([nil])`, when the column is
nullable, does not assert that anything is rejected, either, also
printing a warning
* `ensure_inclusion_of(:attr).in_array([nil])`, when the column is
non-nullable, raises an error because this expectation is not testable
in any way, as setting a boolean column to nil this way will get
converted to false.
2014-01-21 23:46:23 +00:00
|
|
|
module Shoulda
|
|
|
|
module Matchers
|
2014-01-23 18:07:36 +00:00
|
|
|
# @private
|
2013-11-22 20:46:59 +00:00
|
|
|
class Error < StandardError
|
|
|
|
def self.create(attributes)
|
|
|
|
allocate.tap do |error|
|
|
|
|
attributes.each do |name, value|
|
|
|
|
error.__send__("#{name}=", value)
|
|
|
|
end
|
|
|
|
|
|
|
|
error.__send__(:initialize)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def initialize(*args)
|
|
|
|
super
|
|
|
|
@message = message
|
|
|
|
end
|
|
|
|
|
|
|
|
def message
|
|
|
|
""
|
|
|
|
end
|
Tighten CouldNotSetAttributeError restriction
Why:
* Previously, `allow_value` would raise a CouldNotSetAttributeError
if the value being set didn't match the value the attribute had after
being set, but only if the attribute was being changed from nil to
non-nil or non-nil to nil.
* It turns out it doesn't matter which value you're trying to set the
attribute to -- if the attribute rejects that change it's confusing
either way. (In fact, I was recently bit by a case in which I was
trying to validate numericality of an attribute, where the writer
method for that attribute was overridden to ensure that the attribute
always stored a number and never contained non-number characters.
This ended up making the numericality validation useless, of
course -- but it caused confusion because the test acted in a way
I didn't expect.)
To satisfy the above:
* `allow_value` now raises a CouldNotSetAttributeError if the attribute
rejects the value being set in *any* way.
* However, add a `ignoring_interference_by_writer` qualifier so that
it is possible to manually override this behavior.
* Fix tests that are failing now because of this new change:
* Fix tests for allow_value matcher
* Fix tests for numericality matcher
* Remove tests for numericality matcher + integer column
* An integer column will typecast any non-integer value to an
integer.
* Because of the typecasting, our tests for the numericality matcher
against an integer column don't quite work, because we can't
really test what happens when the attribute is set to a
non-integer value. Now that `allow_value` is more strict, we're
getting a CouldNotSetAttributeError when attempting to do so.
* The tests mentioned were originally added to ensure that we are
handling RangeErrors that ActiveRecord used to emit. This doesn't
happen anymore, so the tests aren't necessary anymore either.
* Fix tests for acceptance matcher
* Fix tests for absence matcher
2015-09-26 05:10:00 +00:00
|
|
|
|
|
|
|
def inspect
|
|
|
|
%(#<#{self.class}: #{message}>)
|
|
|
|
end
|
2013-11-22 20:46:59 +00:00
|
|
|
end
|
Handle ensure_inclusion_of for boolean columns
Currently, using `ensure_inclusion_of` against a boolean column doesn't
work. We can assert that the column allows boolean values, but what
about values that should be rejected? Well, it depends on what you give
to `ensure_inclusion_of`. Here's how it works now:
* `ensure_inclusion_of(:attr).in_array([true])` asserts that false is
rejected
* `ensure_inclusion_of(:attr).in_array([false])` asserts that true is
rejected
* `ensure_inclusion_of(:attr).in_array([true, false])` does not assert
that anything is rejected, instead informing the developer how
this sort of expectation is not fully testable (anything other than
true, false, or nil will be converted to false).
* `ensure_inclusion_of(:attr).in_array([nil])`, when the column is
nullable, does not assert that anything is rejected, either, also
printing a warning
* `ensure_inclusion_of(:attr).in_array([nil])`, when the column is
non-nullable, raises an error because this expectation is not testable
in any way, as setting a boolean column to nil this way will get
converted to false.
2014-01-21 23:46:23 +00:00
|
|
|
end
|
|
|
|
end
|