Closed enrico closed 11 years ago
+1
I have something similar and the following code seems to work for me:
validates_each( :date_field ) do |record, attribute|
raw_value = record.send("#{attribute}_before_type_cast".to_sym) || record.read_attribute_for_validation(attribute)
# Rails converts invalid datetimes to nil and if date_field is an optional field (allow_blank) it
# does not get validated and so rails saves the empty value rather than throw an error.
# Therefore, we need to validate against the raw (_before_type_cast) version which does
# not get set to nil
unless raw_value.nil?
Time.zone.parse(raw_value) rescue record.errors.add(attribute, :not_a_date)
end
end
It would be good if @codegram could introduce this behaviour into date_validator itself so that it doesn't need to be called separately.
This code corrects my issue where I had a date_field. Rails converts invalid dates to nil and then because I was allowing blank it submitted the form rather than show an error message to the user.
Hope that helps.
If this behaviour is already in date_validator I'd love to know how to call it, if I've missed something.
+1
@amnesia7 do you want to give a try at implementing the allow_blank
option?
I've not done the whole fork-change-pull before but I'll give it a go as soon as I can. If there's any guidance notes anywhere on how best/easiest to go about it then feel free to post a link so I know.
Thanks
It was a bit difficult to get to stage 1 to begin making any changes - I think your gemfile has some gems missing in it that it requires (other gems seem to have the gems listed in the gemfile that the gem requires to run eg rails, minitest.
I got to the point of running your tests using rake test
and they all passed so I started to add my tests to the test/date_validator.rb
file and the new code to the lib/datevalidator.rb
file.
My tests fail correctly but the code I've added throws up the following error: NoMethodError: undefined method
expiration_date_before_type_cast'`.
Unless you can tell me any different then I assume I need something like def method_missing
: http://made-of-stone.blogspot.co.uk/2007/01/stupid-mistakes-and-helpful-hints.html. I don't really know where to put this in your code if it is required.
@codegram, @txus : can you offer any help/advice?
After looking at the issue again I think the method missing idea was a pointless idea because I was the one setting _before_type_cast
anyway so I thought it best to remove that.
Here's what I changed in my /lib/active_model/validations/date_validator.rb
(https://github.com/codegram/date_validator/blob/master/lib/active_model/validations/date_validator.rb#L38):
def validate_each(record, attr_name, value)
return if (options[:allow_nil] && value.nil?) || (options[:allow_blank] && value.blank?)
unless value.nil?
begin
Time.zone.parse(value)
rescue
record.errors.add(attr_name, :not_a_date)
return
end
end
unless value
record.errors.add(attr_name, :not_a_date, options)
return
end
Here's the tests that I added to my /test/date_validator_test.rb
:
describe "allow_blank set to true" do
it "complains when an invalid date is provided" do
I18n.backend.reload!
TestRecord.validates :expiration_date,
:allow_blank => true,
:date => {:before => Time.now}
model = TestRecord.new("invalid")
model.valid?.must_equal false
model.errors[:expiration_date].must_equal(["is not a date"])
end
it "complains when a bogus date is provided" do
I18n.backend.reload!
TestRecord.validates :expiration_date,
:allow_blank => true,
:date => {:before => Time.now}
model = TestRecord.new("2012-02-99")
model.valid?.must_equal false
model.errors[:expiration_date].must_equal(["is not a date"])
end
it "is happy when a blank date is provided" do
I18n.backend.reload!
TestRecord.validates :expiration_date,
:allow_blank => true,
:date => {:before => Time.now}
model = TestRecord.new(" ")
model.valid?.must_equal true
end
it "is happy when no date is provided" do
I18n.backend.reload!
TestRecord.validates :expiration_date,
:allow_blank => true,
:date => {:before => Time.now}
model = TestRecord.new("")
model.valid?.must_equal true
end
end
I think I'm going to leave it for someone else to takeover, I think I'm a bit out of my depth - I'm still learning rails yet and although I'm getting there with my own app development, I don't think I'm good enough to figure out gem changes yet.
Hope that helps, rather than hinders.
Closed by #37
I'd like to use it like this:
validates :date_of_birth, :date => {:after => ..., :before => ..., :message => 'is invalid' }, :allow_blank? => true , :if => :check_date?