【问题标题】:Validates_Overlap Gem Multiple Scopes Overwriting Eachother验证重叠 Gem 多个范围相互覆盖
【发布时间】:2014-10-24 03:48:37
【问题描述】:

我正在使用可在此处找到的 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 => 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>]

更新我注意到 studio_id 没有被范围行中的 && 注意到。我怎样才能同时拥有范围寄存器?我可以在范围内做还是应该创建一个方法?

我也试过更简单的

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

这做同样的事情——只使用后面的“studio_id”

【问题讨论】:

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


    【解决方案1】:

    我知道,选项的名称令人困惑,对此我深表歉意。

    我建议您实现名为 :confirmed 的命名范围并将其作为 :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
    

    顺便说一句...如果您使用的是 Rails 4.1,请小心,有一个变化https://github.com/robinbortlik/validates_overlap#rails-41-update

    简短说明:作为 :scope 选项传递的内容,其行为类似于属性。但是你可以通过 :query_options 来扩展它。查询选项内部的内容将在查询链中调用。所以内部会这样调用:

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

    现在更清楚了吗?

    【讨论】:

    • 工作就像一个魅力。谢谢罗宾!
    猜你喜欢
    • 2011-04-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-29
    • 2021-09-03
    • 1970-01-01
    • 1970-01-01
    • 2023-04-11
    相关资源
    最近更新 更多