Are you 100% certain about that "without JS" part? Because the "use a datepicker" solution is really much easier than any of the alternatives.
In any case, here's a summary of the issues:
- the assignment blows up well before any validations can actually take effect; it's happening in the code that assigns attributes from a hash.
- even if the assignment could be made to work (Kevin's solution should), the dropdowns won't automatically re-populate when an invalid date is entered: they extract the values to use from the actual object
Validates_timeliness isn't able to help out here because (for reasons lost to history) Hobo doesn't use the standard multiparameter assignment stuff in ActiveRecord. You can tell because it creates fields named some_model[some_date_field][year], etc rather than some_model[some_date_field][1i]. Thus, the methods that validates_timeliness hooks into never get called.
Another alternative method of date-entry I've used in a few apps was to switch to a plain text field. To set this up, add this to an initializer:
HoboFields.field_types[:text_date] = Date
HoboFields::PLAIN_TYPES[:text_date] = Date
class Date
COLUMN_TYPE = :date
end
and this in your taglibs:
<def tag="input" for="text_date" attrs="name, no-wrapper">
<%= text_field_tag(name, this.to_s, attributes) %>
<do unless="&no_wrapper"><label>MM / DD / YYYY</label></do>
</def>
This does solve the "blows up on invalid dates" problem, but instead leaves you with the standard Rails behavior if an invalid string is assigned to a date field: the string is ignored and the field is set to nil. In this case, I *think* validates_timeliness might actually be able to help - not sure, though.
--Matt Jones