Validates_Overlap Gem多个范围覆盖彼此

时间:2014-10-24 03:48:38

标签: ruby-on-rails validation activerecord ruby-on-rails-4

我正在使用Validates_Overlap Gem,可在此处找到:https://github.com/robinbortlik/validates_overlap

本质上我有两个房间可以预订。我希望验证在同一房间已在相同的房间中进行确认预订时介入。如果预订了另一个房间,或者预订了相同的房间但尚未确认,则不应该给我一个错误。

我的代码到目前为止如下

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

这将从我的服务器返回以下内容:

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

还有另外两个预订(使用此studio_id)并且没有一个被确认。是什么给了什么?

以下是所有预订:studio_id =&gt; 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>]

更新我注意到&amp;&amp;&amp;&amp;在范围行中。我怎样才能让范围注册?我可以在范围内执行此操作,还是应该创建方法?

我也尝试过更简单的

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

这也是一样的 - 只使用后面的“studio_id”

1 个答案:

答案 0 :(得分:2)

我知道,选项的名称令人困惑,我很抱歉。

我建议您实现名为scope的命名范围:确认并将其传递为:query_option参数。

我认为,它应该是这样的:

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 ...如果您使用的是Rails 4.1,请注意,有一个更改https://github.com/robinbortlik/validates_overlap#rails-41-update

简短说明:您传递的内容为:范围选项,此行为与属性相似。但您可以通过以下方式扩展它:query_options。什么是内部查询选项将在查询链中调用。所以内部会像这样调用:

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

现在更清楚了吗?