How to validate a submited date with select boxes?

How can I validate a date that is set with select boxes on the form, so
I
can raise an error when it’s invalid?

The default behavior when an invalid date is entered is to add days to
arrive to a valid date. For example: if 2012-31-06 is sent to the
controller, the resulting date will be 2012-01-07

How can I stop this behavior and raise an error?

I’m using the date_select(object_name, method, options = {},
html_options =
{})method in the view.

On 24.02.2012, at 23:38, David M wrote:

How can I validate a date that is set with select boxes on the form, so I can
raise an error when it’s invalid?

The default behavior when an invalid date is entered is to add days to arrive to
a valid date. For example: if 2012-31-06 is sent to the controller, the resulting
date will be 2012-01-07

How can I stop this behavior and raise an error?

I’m using the date_select(object_name, method, options = {}, html_options =
{})method in the view.

Interesting question.

In the case when date_select helper used, it automatically generates
parameter keys:
‘date(1i)’ - year
‘date(2i)’ - month
‘date(3i)’ - day

When ActiveRecord model receives these parameters, Date object will be
generated and assigned to a corresponding model’s attribute. In this
process, there is its clever logic: when values of these parameters
aren’t clearly ‘crazy’, Date object will be generated correctly without
attention to the minor errors in the number of days (28, 30 or 31)
without any validation errors.

To avoid this integrated logic you can put down your own model’s
accessors for ‘date(1i)’, ‘date(2i)’, ‘date(3i)’ mass-assignment
parameters and appropriate custom validator. Or you can hack
ActiveRecord::MultiparameterAssignment stack to escape its logic. Both
are unaesthetic, unclean approaches from all points of view.

Instead of ‘date_select’, you can use ‘select_date’ (render just the
tag), in this case date parameters will be named as you want. Just write
the accessors and attribute assignment logic, then put the custom
validator and this is it.

As for me, I completely gave up date_helper and other selectors, and
began to use strings for dates in a form, adding to their Jquery Date
selector plugin. Much more convenient and simpler.

On Feb 24, 3:27pm, Valery K. [email protected] wrote:

Interesting question.
Instead of ‘date_select’, you can use ‘select_date’ (render just the tag), in
this case date parameters will be named as you want. Just write the accessors and
attribute assignment logic, then put the custom validator and this is it.

As for me, I completely gave up date_helper and other selectors, and began to
use strings for dates in a form, adding to their Jquery

I also used strings, as it is much easier to enter a date with text
than picking each field from the dropdowns. I made it so that if you
enter a full year, fine. But if you do a 1 or 2 digit year it will
pick the rest of the year correctly. If you have 130 year old dates
you will have to enter all 4 digits.

here’s the code
model>

before_validation :b4_valid

def b4_valid
self.xmonth = self.month_.to_i
self.xday = self.day_.to_i
self.xyear = self.year_.to_i
begin
if (self.xyear >= 0 && self.xyear <= 100)
@compare = Date.new(2000+self.xyear, 1,1)
if (@compare > Date.today)
self.xyear = 1900+self.xyear
self.year_ = self.xyear.to_s
else
self.xyear = 2000+self.xyear
self.year_ = self.xyear.to_s
end
end
rescue
return false
end
begin
self.birthday = Date.new(self.xyear, self.xmonth, self.xday)
rescue
return false
end
end

view>
<% fields_for “household[people_attributes][]”, person do |
person_form| %>

<% fields_for "household" do |household_form| %> <%= household_form.radio_button :hoh, person.hoh %> <% end %> <%= person_form.hidden_field :hoh, :index => nil %> <%= person_form.text_field :last_name, :style => 'text-align: left', :class => 'last_name', :size => 25, :maxlength => 25, :index => nil, :autocomplete => "off" %> <%= person_form.text_field :first_name, :style => 'text-align: left', :class => 'first_name', :size => 25, :maxlength =>25, :index => nil, :autocomplete => "off" %> <%= person_form.text_field :middle, :style => 'text-align: right', :class => 'middle', :size => 1, :maxlength =>1, :index => nil, :autocomplete => "off" %> <%= person_form.text_field :sex, :style => 'text-align: right', :size => 1, :maxlength =>1, :index => nil, :autocomplete => "off" %> <%= person_form.text_field :month_, :style => 'text-align: right', :size => 2, :maxlength =>2, :index => nil, :autocomplete => "off" %> <%= person_form.text_field :day_, :style => 'text-align: right', :size => 2, :maxlength =>2, :index => nil, :autocomplete => "off" %> <%= person_form.text_field :year_, :style => 'text-align: right', :size => 4, :maxlength =>4, :index => nil, :autocomplete => "off" %> <% if !person_form.object.new_record? %> <%= person_form.hidden_field :id, :index => nil %> <%= link_to 'Delete', person_path(person.id), :confirm => 'Are you sure?', :method => :delete %> <% end %>
<% end %>

This will calculate the date object based on the input and fail
validation if the date is incorrect. Because of the rescue statements,
there should be no errors that cause the program to abort. All errors
will show as validation failures.

Best of luck
Bob [email protected]

On 25.02.2012, at 0:57, Bob S. wrote:

I also used strings, as it is much easier to enter a date with text
than picking each field from the dropdowns. I made it so that if you
enter a full year, fine. But if you do a 1 or 2 digit year it will
pick the rest of the year correctly. If you have 130 year old dates
you will have to enter all 4 digits.

I prefer to pick up the date from ONE string:

model:

class Software << ActiveRecord::Base

formatted_date_accessor :release_date

end

lib: (/lib/formatted_date_time.rb)

class ActiveRecord::Base

def self.formatted_date_accessor(*names)
names.each do |name|
define_method("#{name}=") do |value|
super(value)
if value.present? && self[name].nil?
class_eval do
define_method name.to_sym do
value
end
end
self.class.validate do
errors.add(name.to_sym, “can’t be formatted”)
end
end
end
end
end

end

in a View:

<%= f.text_field :release_date %>

You can pass Jan 2, 2011 as:
‘2011-1-2’ or 11-1-2 or 2011.1.2 or 11.01.02, according to a Date’s
localization order.
European order would be: ‘02.01.2011’ or ‘2-1-2011’ whatever…

Any invalid date will raise a validation error. Any posted date saved
for the next request to trace the invalid input.