validates_timeliness
validates_timeliness copied to clipboard
Can't test the validation with allow_blank: true
Hi! I have the Order model with :completed_date attribute. And I would like to validate :completed_date in the following way
class Order < ActiveRecord::Base
#...
validates_date :completed_date, allow_blank: true
#...
end
But my spec for this validation doesn't work
it "is invalid when completed_date is invalid" do
order.completed_date = "incorrect date"
expect{ order.valid? }.to change{ order.errors.messages[:completed_date] }
end
I believe it's because any incorrect date value sets to nil and nil is valid value since I have allow_blank: true
in my validation
When I remove allow_blank: true
from my validation, the spec above works perfectly but I really need to permit blank :completed_date for my orders.
So I wonder if I do something wrong or if there is any way to test such validation?
P.S. I have tried all of the following constructions and all of them didn't work
validates_date :completed_date, allow_blank: true
validates :completed_date, timeliness: { type: :date }, allow_blank: true
validates :completed_date, timeliness: { type: :date, allow_blank: true }
Do you have the plugin parser enabled in the initializer?
I didn't have it but I do have now and the spec above still don't want to pass.
If it will help or if it will turn out as a new issue:
when I uncomment the following line
config.enable_multiparameter_extension!
I get the error
...gems/activesupport-4.2.2/lib/active_support/core_ext/module/aliasing.rb:32:in `alias_method': undefined method `instantiate_time_object' for class `ActiveRecord::Base' (NameError)
Using datetime
type for column in pgsql + ActiveRecord, following does not work
validates_datetime :published_at, allow_blank: true
Allow blank values, any string values become allowed.
I tried enabling plugin parser, but it did not resolve this issue.
also, enabling multiparameter extension
results in error.
According to one of the answers here the problem is that recent versions of Rails do a type cast on values before validation is called and that changes the stored value to nil
if it's invalid for the type. With allow_blank
that value is then accepted.
The gem needs to detect a case where:
if record.public_send("#{attribute}_before_type_cast").present? && value.blank?
and treat it as an invalid datetime having been entered. Or just validate against record.public_send("#{attribute}_before_type_cast")
and ignore what value
has become after typecast?
Also, fwiw, it's probably preferable to use record.read_attribute_before_type_cast(attribute)
rather than send
.