It''s the "Feb 31st" problem... I''m working on a model that has the created_on and updated_on fields, and normally I''d just leave those fields off of the new/edit form, but in this case I want to leave it on to allow the user to backdate posts, if need be. Problem is, the input for the created_on field allows the user to enter invalid dates like Feb 31st. I''d like to catch this in a validation so that rails doesn''t just try to submit it blindly and break when the database rejects it, but I''m not sure exactly how to go about validating that a date is actually valid. Any suggestions? Thanks. -- One Guy With A Camera http://rbpark.ath.cx
Rob Park wrote:>It''s the "Feb 31st" problem... > >I''m working on a model that has the created_on and updated_on fields, >and normally I''d just leave those fields off of the new/edit form, but >in this case I want to leave it on to allow the user to backdate >posts, if need be. Problem is, the input for the created_on field >allows the user to enter invalid dates like Feb 31st. I''d like to >catch this in a validation so that rails doesn''t just try to submit it >blindly and break when the database rejects it, but I''m not sure >exactly how to go about validating that a date is actually valid. >I have this problem too - on Day Three of Four Days on Rails, there is a use of date_select without a proper solution to the validation problem. I was about to post two questions: (i) what is the proper way to do this? (ii) will it work with a plain (non-ActiveRecord) model class? The API documentation refers to "multi-parameter assignment" being used... Googling for this turns up uses of the phrase in the API docs, and Google''s cache also contains a changelog with something closer to a definition: <quote> Added multi-parameter assignment: # Instantiate objects for all attribute classes that needs more than one constructor parameter. This is done # by calling new on the column type or aggregation type (through composed_of) object with these parameters. # So having the pairs written_on(1) = "2004", written_on(2) = "6", written_on(3) = "24", will instantiate # written_on (a date type) with Date.new("2004", "6", "24"). You can also specify a typecast character in the # parenteses to have the parameters typecasted before they''re used in the constructor. Use i for Fixnum, f for Float, # s for String, and a for Array. This is incredibly useful for assigning dates from HTML drop-downs of month, year, and day. </quote> But this still doesn''t tell me where to hook in proper validation. Justin
On Sat, 12 Mar 2005 16:42:08 +0000, Justin Forder <justin-zSfPWr5aQuznITO/+xaoB7VCufUGDwFn@public.gmane.org> wrote:> This is incredibly useful for assigning dates from HTML drop-downs of > month, year, and day. > </quote> > > But this still doesn''t tell me where to hook in proper validation.Yeah, it''s easy to see rails actually using that. Just submit Feb 31st date, watch rails die as the database rejects that value, then use rails'' ever helpful error screen to examine the session data, you can see stuff like this: Parameters: {"panorama"=>{"created_on(2i)"=>"2", "name"=>"", "created_on(3i)"=>"31", "caption"=>"", "created_on(1i)"=>"2005"}} I wonder if there''s a way to just catch that exception and then display it as an error in the same way that other errors are displayed. Then we''d let the database itself do all the hard work of actually validating the date... Well, the first guess I tried didn''t work. I guess I don''t really understand ruby well enough to do this on my own. -- One Guy With A Camera http://rbpark.ath.cx
Rob Park wrote:> [...] Just submit Feb 31st > >date, watch rails die as the database rejects that value, then use >rails'' ever helpful error screen to examine the session data, you can >see stuff like this: > >Parameters: {"panorama"=>{"created_on(2i)"=>"2", "name"=>"", >"created_on(3i)"=>"31", "caption"=>"", "created_on(1i)"=>"2005"}} > >I wonder if there''s a way to just catch that exception and then >display it as an error in the same way that other errors are >displayed. Then we''d let the database itself do all the hard work of >actually validating the date... > >Well, the first guess I tried didn''t work. I guess I don''t really >understand ruby well enough to do this on my own. >Yes, these parameters with ''(1i)'' etc. in their names appear to be an undocumented extension to the behaviour described in ActiveRecord::Base (I''m assuming that the in-line API documentation is supposed to be definitive). It is clearly possible to do some validation (and adjustment) on the contents of the @params hash before giving it to the model''s new or update_attributes method. Constructing a Date from year, month and day numbers fails for invalid arguments, so this can be used to do the validation (we know that it''s going to be the day field that is the problem). But then you want to go on to validate other fields without actually updating the database, and to give an appropriate error message and highlight all the offending controls... I don''t know how to do these things yet. Justin