Jacob Patton
2009-May-18 07:47 UTC
Validating against other records for bulk creates/updates?
I''ve got a OpeningHour model in my application, which keeps tracks of a store''s opening times (like Monday 9am-12pm, and then 1pm-5pm). I want to make sure that the opening hours don''t overlap, and if I do something like: class OpeningHour < ActiveRecord::Base validate :overlapping_openings? protected def overlapping_openings? if OpeningHour.count_by_sql(["SELECT COUNT(id) FROM opening_hours WHERE account_id = ? AND day_of_week = ? AND ends >= ? AND begins <= ?", account_id, day_of_week, ends, begins]) > 0 errors.add_to_base("This opening hour overlaps with another one.") end end end this will work if I insert the opening hours one at a time. When I attempt to create multiple opening hour objects at once, however, I can see in the logs that all of the database selects (to validate against overlapping openings) occur at the start of the request, and then the new opening hours are inserted. What that means is that if the user submits new, overlapping opening hours, the validation passes (incorrectly, since these opening hours overlap with each other, but they *don''t* overlap with any other in the database before the request). Can someone recommend how I can make ActiveRecord validate each new object against the records in the database, even those that are created during the same request? Thanks very much, Jacob Patton
Matt Jones
2009-May-18 16:16 UTC
Re: Validating against other records for bulk creates/updates?
I think you''d be better off validating this in the whatever model account_id links to - then you can check the members of the association against each other, even if they haven''t been saved yet. --Matt Jones On May 18, 3:47 am, Jacob Patton <jacob.pat...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> I''ve got a OpeningHour model in my application, which keeps tracks of > a store''s opening times (like Monday 9am-12pm, and then 1pm-5pm). I > want to make sure that the opening hours don''t overlap, and if I do > something like: > > class OpeningHour < ActiveRecord::Base > > validate :overlapping_openings? > > protected > > def overlapping_openings? > if OpeningHour.count_by_sql(["SELECT COUNT(id) FROM > opening_hours WHERE > account_id = ? AND day_of_week = ? AND ends >= ? AND begins > <= ?", > account_id, day_of_week, ends, begins]) > 0 > errors.add_to_base("This opening hour overlaps with another > one.") > end > end > > end > > this will work if I insert the opening hours one at a time. When I > attempt to create multiple opening hour objects at once, however, I > can see in the logs that all of the database selects (to validate > against overlapping openings) occur at the start of the request, and > then the new opening hours are inserted. What that means is that if > the user submits new, overlapping opening hours, the validation passes > (incorrectly, since these opening hours overlap with each other, but > they *don''t* overlap with any other in the database before the > request). > > Can someone recommend how I can make ActiveRecord validate each new > object against the records in the database, even those that are > created during the same request? > > Thanks very much, > > Jacob Patton