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