【问题标题】:Validate time overlap in ruby on rails在 ruby​​ on rails 中验证时间重叠
【发布时间】:2016-03-07 21:52:57
【问题描述】:

我有一个包含电影、放映时间和屏幕模型的电影票务服务。对于某个屏幕,我必须确保放映时间不重叠。这样做的最佳方法是什么?

我的迁移如下

电影

class CreateMovies < ActiveRecord::Migration
  def change
    create_table :movies do |t|
      t.string  :title
      t.text    :plot
      t.integer :length_minutes
      t.string  :poster
      t.timestamps null: false
    end
  end
end

放映时间

class CreateShowtimes < ActiveRecord::Migration
  def change
    create_table :showtimes do |t|
      t.references :movie, index: true
      t.timestamp  :start_time, null: false
      t.timestamp  :end_time, null: false
      t.references :screen
    end
  end
end

和屏幕

class CreateScreens < ActiveRecord::Migration
  def change
    create_table :screens do |t|
      t.string :name, unique: true
      t.integer :seats_available, null: false, limit: 1
    end
  end
end

这是我的 ShowtimesController 中的 create 方法

def create
    movie_length = Movie.find(showtime_params[:movie_id]).length_minutes
    start_time = Time.new(showtime_params["start_time(1i)"], showtime_params["start_time(2i)"], showtime_params["start_time(3i)"], showtime_params["start_time(4i)"], showtime_params["start_time(5i)"])
    end_time = start_time + movie_length.minutes

    @showtime = Showtime.new(showtime_params)
    @showtime.start_time = start_time
    @showtime.end_time = end_time
    if @showtime.save
      redirect_to @showtime, notice: 'Showtime was successfully created.'
    else
      render :new
    end
  end

如何验证同一屏幕的两个放映时间不重叠。我使用 postgresql 作为我的数据库。

【问题讨论】:

    标签: ruby-on-rails postgresql validation date


    【解决方案1】:

    将此添加到 Showtime 模型中:

    validate :validate_no_overlap_on_screen
    
    def validate_no_overlap_on_screen
      return if Showtime.where('screen_id = ? AND (end_time > ? OR start_time < ?)',
        screen_id, start_time, end_time).none?
      errors.add(:start_time, 'Times overlap another showtime on this screen')
    end
    

    【讨论】:

    • 嗨@MTarantini,我在实施此解决方案时收到以下错误错误:“start_time”列中的空值违反非空约束详细信息:失败行包含(6、1、null、null、1 )。
    • 我认为这应该是比公认的答案更好的解决方案。因为它在数据库端完成工作。您真的不想在客户端将数据拉入内存并进行 ruby​​ 慢速比较!
    • 嗨@jlarding,该错误与您的迁移有关,而不是此解决方案:t.timestamp :start_time, null: false。你的 Showtime 模型应该有验证来检查 start_time 和 end_time 是否存在。
    【解决方案2】:
     validate :no_overlap
    
     def no_overlap
       showtimes = Showtime.where(screen_id: screen_id)
       overlap = showtimes.select{ |showtime| (start_time - showtime.end_time) * (showtime.start_time - end_time) > 0  }
       unless overlap.blank?
         raise "Conflicting showings for screen: #{screen_id}"
       end
     end
    

    【讨论】:

    • 嗨@toddmetheny,我收到以下错误“错误:“start_time”列中的空值违反非空约束详细信息:失败行包含(10、1、null、null、1)。
    • @jlarding 你确定你在通过你的表格打发时间吗?尝试删除验证,然后在您的控制器中执行 puts params.inspect 并确保它们通过您的控制器操作。
    • end_time 参数是在我的控制器中设置的,因为它是通过使用电影的长度和开始时间来计算的。如何在不来自表单的情况下将结束日期传递给参数
    • @jlarding 在调用 Showtime.new 之前,通过 showtime_params[:end_time] = end_time 将 end_time 添加到 showtime_params。
    • 还有——你想用你传递给 start_time 的所有参数做什么?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多