Ruby on Rails
Wednesday, February 1, 2012
On Wed, Feb 1, 2012 at 9:22 AM, sandip ransing <sandip@funonrails.com> wrote:
You are probably tripped up by the same unexpected behavior I recently discovered.
At least with Postgresql, if you assign a completely invalid string to a date (or a datetime)
field, it does not throw an exception but simply sets the value to nil:
> c.birth_date = "2012-01-15"
=> "2012-01-15"
1.9.3-p0 :011 > c.save!
(0.2ms) BEGIN
(0.4ms) UPDATE "children" SET "birth_date" = '2012-01-15', "updated_at" = '2012-02-01 08:52:13.063755' WHERE "children"."id" = 1
(8.5ms) COMMIT
=> true
1.9.3-p0 :012 > c.birth_date = "2012-01-45"
=> "2012-01-45"
1.9.3-p0 :013 > c.save!
(0.2ms) BEGIN
(0.4ms) UPDATE "children" SET "birth_date" = NULL, "updated_at" = '2012-02-01 08:54:46.965404' WHERE "children"."id" = 1
(18.8ms) COMMIT
=> true
I would have expected an exception here as the POLS.
But on 'true' it does raise an exception (I discovered this
because Rails.logger.warning now returns true).
c.birth_date = true
=> true
1.9.3-p0 :015 > c.save!
(0.2ms) BEGIN
(0.4ms) UPDATE "children" SET "birth_date" = 't', "updated_at" = '2012-02-01 08:56:00.771141' WHERE "children"."id" = 1
PGError: ERROR: invalid input syntax for type date: "t"
LINE 1: UPDATE "children" SET "birth_date" = 't', "updated_at" = '20...
^
: UPDATE "children" SET "birth_date" = 't', "updated_at" = '2012-02-01 08:56:00.771141' WHERE "children"."id" = 1
(0.2ms) ROLLBACK
ActiveRecord::StatementInvalid: PGError: ERROR: invalid input syntax for type date: "t"
As for the validation. You could use a regex, as suggested by Neethu, but that has the limitation
that it is hard do calculate that 2012-01-29 is OK en 2013-01-29 is not OK.
Better may be to use a combination of strptime and rescue ArgumentError
1.9.3-p0 :051 > begin
1.9.3-p0 :052 > Date.strptime("29/02/2012", "%d/%m/%Y")
1.9.3-p0 :053?> rescue ArgumentError
1.9.3-p0 :054?> puts "This date is invalid"
1.9.3-p0 :055?> end
=> Wed, 29 Feb 2012
1.9.3-p0 :056 > begin
1.9.3-p0 :057 > Date.strptime("2012-31-31", "%Y-%m-%d")
1.9.3-p0 :058?> rescue ArgumentError
1.9.3-p0 :059?> puts "This date is invalid"
1.9.3-p0 :060?> end
This date is invalid
=> nil #This comes from the last line in the rescue block, which is puts here
1.9.3-p0 :061 > begin
1.9.3-p0 :062 > Date.strptime("10/01/2012", "%d/%m/%Y")
1.9.3-p0 :063?> rescue ArgumentError
1.9.3-p0 :064?> puts "This date is invalid"
1.9.3-p0 :065?> end
=> Tue, 10 Jan 2012 # Correct EU dd/mm/yyyy intepretation
1.9.3-p0 :066 > begin
1.9.3-p0 :067 > Date.strptime("10/01/2012", "%m/%d/%Y")
1.9.3-p0 :068?> rescue ArgumentError
1.9.3-p0 :069?> puts "This date is invalid"
1.9.3-p0 :070?> end
=> Mon, 01 Oct 2012 # Correct US mm/dd/yyyy interpretation
HTH,
Peter
-- consider scenario,
User model with name, birth_date fields
(here birth_date is not mandatory field)inside view form birth_date is assigned as '31/31/1985' which is invalid
ideally user object should be invalid and while save raise an error on birth_date field but that's not happening and user object gets saved with birth_date as blank which is completely misleading.
You are probably tripped up by the same unexpected behavior I recently discovered.
At least with Postgresql, if you assign a completely invalid string to a date (or a datetime)
field, it does not throw an exception but simply sets the value to nil:
> c.birth_date = "2012-01-15"
=> "2012-01-15"
1.9.3-p0 :011 > c.save!
(0.2ms) BEGIN
(0.4ms) UPDATE "children" SET "birth_date" = '2012-01-15', "updated_at" = '2012-02-01 08:52:13.063755' WHERE "children"."id" = 1
(8.5ms) COMMIT
=> true
1.9.3-p0 :012 > c.birth_date = "2012-01-45"
=> "2012-01-45"
1.9.3-p0 :013 > c.save!
(0.2ms) BEGIN
(0.4ms) UPDATE "children" SET "birth_date" = NULL, "updated_at" = '2012-02-01 08:54:46.965404' WHERE "children"."id" = 1
(18.8ms) COMMIT
=> true
I would have expected an exception here as the POLS.
But on 'true' it does raise an exception (I discovered this
because Rails.logger.warning now returns true).
c.birth_date = true
=> true
1.9.3-p0 :015 > c.save!
(0.2ms) BEGIN
(0.4ms) UPDATE "children" SET "birth_date" = 't', "updated_at" = '2012-02-01 08:56:00.771141' WHERE "children"."id" = 1
PGError: ERROR: invalid input syntax for type date: "t"
LINE 1: UPDATE "children" SET "birth_date" = 't', "updated_at" = '20...
^
: UPDATE "children" SET "birth_date" = 't', "updated_at" = '2012-02-01 08:56:00.771141' WHERE "children"."id" = 1
(0.2ms) ROLLBACK
ActiveRecord::StatementInvalid: PGError: ERROR: invalid input syntax for type date: "t"
After debugging found that while assigning attributes birth_date value it gets assigned as blank and as birth_date is optional object gets saved.
class User < ActiveRecord::Base
Any clue how to get validation working properly for not mandatory date fields ??
def initialize(args={})
logger.info args[:birth_date] #invalid value comes upto here but vanishes afterwords
super
end
end
As for the validation. You could use a regex, as suggested by Neethu, but that has the limitation
that it is hard do calculate that 2012-01-29 is OK en 2013-01-29 is not OK.
Better may be to use a combination of strptime and rescue ArgumentError
1.9.3-p0 :051 > begin
1.9.3-p0 :052 > Date.strptime("29/02/2012", "%d/%m/%Y")
1.9.3-p0 :053?> rescue ArgumentError
1.9.3-p0 :054?> puts "This date is invalid"
1.9.3-p0 :055?> end
=> Wed, 29 Feb 2012
1.9.3-p0 :056 > begin
1.9.3-p0 :057 > Date.strptime("2012-31-31", "%Y-%m-%d")
1.9.3-p0 :058?> rescue ArgumentError
1.9.3-p0 :059?> puts "This date is invalid"
1.9.3-p0 :060?> end
This date is invalid
=> nil #This comes from the last line in the rescue block, which is puts here
1.9.3-p0 :061 > begin
1.9.3-p0 :062 > Date.strptime("10/01/2012", "%d/%m/%Y")
1.9.3-p0 :063?> rescue ArgumentError
1.9.3-p0 :064?> puts "This date is invalid"
1.9.3-p0 :065?> end
=> Tue, 10 Jan 2012 # Correct EU dd/mm/yyyy intepretation
1.9.3-p0 :066 > begin
1.9.3-p0 :067 > Date.strptime("10/01/2012", "%m/%d/%Y")
1.9.3-p0 :068?> rescue ArgumentError
1.9.3-p0 :069?> puts "This date is invalid"
1.9.3-p0 :070?> end
=> Mon, 01 Oct 2012 # Correct US mm/dd/yyyy interpretation
HTH,
Peter
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
To post to this group, send email to rubyonrails-talk@googlegroups.com.
To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment