Fix inclusion matcher w/ date & datetime attrs
Why: * The inclusion matcher (when used with the `in_array` qualifier) makes the assertion that when the attribute is set to a value that is outside the given array, the record in question is invalid. The issue is that when used with a date or datetime attribute, the arbitrary value the matcher chose was a string. This was getting typecast and so the matcher was throwing a CouldNotSetAttributeError. To satisfy the above: * If the column is a date, use a Date for the arbitrary value * If the column is a datetime, use a DateTime for the arbitrary value * If the column is a time, use a Time for the arbitrary value
This commit is contained in:
parent
5a5af1089a
commit
8fa97b4ff3
7
NEWS.md
7
NEWS.md
|
@ -1,3 +1,10 @@
|
|||
# HEAD
|
||||
|
||||
### Bug fixes
|
||||
|
||||
* Fix `validate_inclusion_of` + `in_array` when used against a date or datetime
|
||||
attribute so that it does not raise a CouldNotSetAttributeError.
|
||||
|
||||
# 3.0.0
|
||||
|
||||
### Backward-incompatible changes
|
||||
|
|
|
@ -263,9 +263,12 @@ module Shoulda
|
|||
|
||||
# @private
|
||||
class ValidateInclusionOfMatcher < ValidationMatcher
|
||||
ARBITRARY_OUTSIDE_STRING = 'shouldamatchersteststring'
|
||||
ARBITRARY_OUTSIDE_STRING = 'shoulda-matchers test string'
|
||||
ARBITRARY_OUTSIDE_FIXNUM = 123456789
|
||||
ARBITRARY_OUTSIDE_DECIMAL = BigDecimal.new('0.123456789')
|
||||
ARBITRARY_OUTSIDE_DATE = Date.jd(9999999)
|
||||
ARBITRARY_OUTSIDE_DATETIME = DateTime.jd(9999999)
|
||||
ARBITRARY_OUTSIDE_TIME = Time.at(9999999999)
|
||||
BOOLEAN_ALLOWS_BOOLEAN_MESSAGE = <<EOT
|
||||
You are using `validate_inclusion_of` to assert that a boolean column allows
|
||||
boolean values and disallows non-boolean ones. Be aware that it is not possible
|
||||
|
@ -447,6 +450,12 @@ EOT
|
|||
[ARBITRARY_OUTSIDE_FIXNUM]
|
||||
when :decimal
|
||||
[ARBITRARY_OUTSIDE_DECIMAL]
|
||||
when :date
|
||||
[ARBITRARY_OUTSIDE_DATE]
|
||||
when :datetime
|
||||
[ARBITRARY_OUTSIDE_DATETIME]
|
||||
when :time
|
||||
[ARBITRARY_OUTSIDE_TIME]
|
||||
else
|
||||
[ARBITRARY_OUTSIDE_STRING]
|
||||
end
|
||||
|
@ -492,9 +501,9 @@ EOT
|
|||
|
||||
def column_type_to_attribute_type(type)
|
||||
case type
|
||||
when :boolean, :decimal then type
|
||||
when :integer, :float then :fixnum
|
||||
else :default
|
||||
when :timestamp then :datetime
|
||||
else type
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -503,7 +512,10 @@ EOT
|
|||
when true, false then :boolean
|
||||
when BigDecimal then :decimal
|
||||
when Fixnum then :fixnum
|
||||
else :default
|
||||
when Date then :date
|
||||
when DateTime then :datetime
|
||||
when Time then :time
|
||||
else :unknown
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -75,7 +75,7 @@ describe Shoulda::Matchers::ActiveModel::ValidateInclusionOfMatcher, type: :mode
|
|||
end
|
||||
end
|
||||
|
||||
context "against a float attribute" do
|
||||
context 'against a float attribute' do
|
||||
it_behaves_like 'it supports in_array',
|
||||
possible_values: [1.0, 2.0, 3.0, 4.0, 5.0],
|
||||
zero: 0.0,
|
||||
|
@ -97,7 +97,7 @@ describe Shoulda::Matchers::ActiveModel::ValidateInclusionOfMatcher, type: :mode
|
|||
end
|
||||
end
|
||||
|
||||
context "against a decimal attribute" do
|
||||
context 'against a decimal attribute' do
|
||||
it_behaves_like 'it supports in_array',
|
||||
possible_values: [1.0, 2.0, 3.0, 4.0, 5.0].map { |number|
|
||||
BigDecimal.new(number.to_s)
|
||||
|
@ -121,6 +121,72 @@ describe Shoulda::Matchers::ActiveModel::ValidateInclusionOfMatcher, type: :mode
|
|||
end
|
||||
end
|
||||
|
||||
context 'against a date attribute' do
|
||||
today = Date.today
|
||||
|
||||
it_behaves_like 'it supports in_array',
|
||||
possible_values: (1..5).map { |n| today + n },
|
||||
reserved_outside_value: described_class::ARBITRARY_OUTSIDE_DATE
|
||||
|
||||
it_behaves_like 'it supports in_range',
|
||||
possible_values: (today .. today + 5)
|
||||
|
||||
define_method :build_object do |options = {}, &block|
|
||||
build_object_with_generic_attribute(
|
||||
options.merge(column_type: :date, value: today),
|
||||
&block
|
||||
)
|
||||
end
|
||||
|
||||
def add_outside_value_to(values)
|
||||
values + [values.last + 1]
|
||||
end
|
||||
end
|
||||
|
||||
context 'against a datetime attribute (using DateTime)' do
|
||||
now = DateTime.now
|
||||
|
||||
it_behaves_like 'it supports in_array',
|
||||
possible_values: (1..5).map { |n| now + n },
|
||||
reserved_outside_value: described_class::ARBITRARY_OUTSIDE_DATETIME
|
||||
|
||||
it_behaves_like 'it supports in_range',
|
||||
possible_values: (now .. now + 5)
|
||||
|
||||
define_method :build_object do |options = {}, &block|
|
||||
build_object_with_generic_attribute(
|
||||
options.merge(column_type: :datetime, value: now),
|
||||
&block
|
||||
)
|
||||
end
|
||||
|
||||
def add_outside_value_to(values)
|
||||
values + [values.last + 1]
|
||||
end
|
||||
end
|
||||
|
||||
context 'against a datetime attribute (using Time)' do
|
||||
now = Time.now
|
||||
|
||||
it_behaves_like 'it supports in_array',
|
||||
possible_values: (1..5).map { |n| now + n },
|
||||
reserved_outside_value: described_class::ARBITRARY_OUTSIDE_TIME
|
||||
|
||||
it_behaves_like 'it supports in_range',
|
||||
possible_values: (now .. now + 5)
|
||||
|
||||
define_method :build_object do |options = {}, &block|
|
||||
build_object_with_generic_attribute(
|
||||
options.merge(column_type: :time, value: now),
|
||||
&block
|
||||
)
|
||||
end
|
||||
|
||||
def add_outside_value_to(values)
|
||||
values + [values.last + 1]
|
||||
end
|
||||
end
|
||||
|
||||
context 'against a string attribute' do
|
||||
it_behaves_like 'it supports in_array',
|
||||
possible_values: %w(foo bar baz),
|
||||
|
@ -270,7 +336,7 @@ describe Shoulda::Matchers::ActiveModel::ValidateInclusionOfMatcher, type: :mode
|
|||
end
|
||||
|
||||
if zero
|
||||
it 'matches when one of the given values is a 0' do
|
||||
it 'matches when one of the given values is a zero' do
|
||||
valid_values = possible_values + [zero]
|
||||
builder = build_object_allowing(valid_values)
|
||||
expect_to_match_on_values(builder, valid_values)
|
||||
|
@ -527,7 +593,6 @@ describe Shoulda::Matchers::ActiveModel::ValidateInclusionOfMatcher, type: :mode
|
|||
end
|
||||
end
|
||||
|
||||
|
||||
def build_object_with_generic_attribute(options = {}, &block)
|
||||
attribute_name = :attr
|
||||
column_type = options.fetch(:column_type)
|
||||
|
|
Loading…
Reference in New Issue