Validates_Overlap Gem Multiple Scopes Overwriting Eachother

*爱你&永不变心* 提交于 2019-12-24 04:38:04

问题


I'm using Validates_Overlap Gem which can be found here: https://github.com/robinbortlik/validates_overlap

The essence is I have two rooms that can be booked. I want the validation to step in when the same room already has a CONFIRMED booking in the SAME room. It shouldn't throw me an error when the other room is booked, or if the same room is booked but hasn't been confirmed.

My code so far is as follows

validates :start_time, :end_time, 
    :overlap => {
        :exclude_edges => ["starts_at", "ends_at"],
        :scope => { "bookings.studio_id" => proc {|booking| booking.studio_id}} &&  { "bookings.is_confirmed" => proc {|booking| booking.is_confirmed == true}}
        }, on: :update

This returns the following from my server:

Booking Exists (0.4ms)  SELECT  1 AS one FROM "bookings"  WHERE ((bookings.end_time IS NULL OR bookings.end_time >= '2014-10-23 20:00:00.000000') AND (bookings.start_time IS NULL OR bookings.start_time <= '2014-10-24 03:00:00.000000') AND bookings.id != 9 AND bookings.is_confirmed  = 't') LIMIT 1

There are two other bookings (with this studio_id) and none of them are confirmed. What gives?

Here are all the bookings with :studio_id => 2

[#<Booking id: 1, studio_id: 2, engineer_id: 5, is_confirmed: false, title: "", allDay: false, created_at: "2014-10-23 19:59:01", updated_at: "2014-10-23 19:59:01", start_time: "2014-10-23 19:00:00", end_time: "2014-10-23 21:00:00", user_id: nil, booker: "Client", client_id: 3>,
 #<Booking id: 8, studio_id: 2, engineer_id: 1, is_confirmed: false, title: "", allDay: false, created_at: "2014-10-24 03:07:34", updated_at: "2014-10-24 03:07:34", start_time: "2014-10-23 19:00:00", end_time: "2014-10-23 22:00:00", user_id: nil, booker: "Pat Sullivan", client_id: nil>,
 #<Booking id: 9, studio_id: 2, engineer_id: 2, is_confirmed: false, title: "", allDay: false, created_at: "2014-10-24 03:26:17", updated_at: "2014-10-24 03:26:17", start_time: "2014-10-23 20:00:00", end_time: "2014-10-24 03:00:00", user_id: nil, booker: "Client", client_id: 4>]

Update I noticed that the studio_id isn't being noticed with the && in the scope line. How can I have the scope register both? Can I do it within the scope line or should I create a method?

I've also tried a simpler

    validates :start_time, :end_time, 
    :overlap => {
        :exclude_edges => ["starts_at", "ends_at"],
        :scope => "is_confirmed" && "studio_id"
        }, on: :update

This does the same thing -- only uses the later "studio_id"


回答1:


I know, that the names of options are confusing and I'm sorry for that.

I suggest you to implement your named scope called :confirmed and pass it as :query_option parameter.

I think, it should look like this:

class Booking < ActiveRecord::Base
  scope :confirmed_scope, -> {confirmed: true}  
  validates :start_time, :end_time, :overlap => {
    :exclude_edges => ["starts_at", "ends_at"],
    :scope => "studio_id",
    :query_options => {:confirmed_scope => nil}
    }, on: :update
end

BTW... be careful if you are using Rails 4.1, there is a change https://github.com/robinbortlik/validates_overlap#rails-41-update

Short explanation: what you pass as a :scope option, this behave like attribute. But you can extend it by :query_options. What is inside query options will be called in the query chain. So internally it will be called like this:

Booking.confirmed_scope.where("starts_at > 18-02-2014 AND ends_at < 20-02-2014 AND studio_id = 1")

Is it more clear now?



来源:https://stackoverflow.com/questions/26541182/validates-overlap-gem-multiple-scopes-overwriting-eachother

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!