首页 > 解决方案 > 验证错误 * 签入时间必须是有效的当前或未来时间 - ruby​​ on rails

问题描述

我的rails构建遇到了问题。我创建了一个酒店应用程序,当尝试在未来的任何时间或日期查看房间时,它给了我一个错误,如下图所示。我愿意接受任何反馈,真诚感谢您的帮助!我附上了这个问题的截图,我能想到的所有代码都可能是相关的。

问题的图片

预订.rb

class Reservation < ActiveRecord::Base
  belongs_to :user
  belongs_to :room

  attr_accessor :checkin_date, :checkin_time, :checkout_date, :checkout_time

  validates_presence_of :checkin_date
  validates_presence_of :checkin_time
  validates_presence_of :checkout_date
  validates_presence_of :checkout_time
  validates_presence_of :number_of_rooms

  validate :future_checkin_date
  validate :future_checkin_time
  validate :future_checkout_date
  validate :future_checkout_time
  validate :no_of_rooms_greater_then_0, if: lambda { number_of_rooms.present? }

  def future_checkin_date
    if checkin_date.present? && checkin_date.to_date < DateTime.now.to_date
      errors.add(:checkin_date, 'must be a valid current or future date')
    end
  end

  def future_checkin_time
    if checkin_time.present? && checkin_time.to_time < Time.now
      errors.add(:checkin_time, 'must be a valid current or future time')
    end
  end

  def future_checkout_date
    if checkin_date.present? && checkout_date.present? &&
        checkout_date.to_date < checkin_date.to_date
      errors.add(:checkout_date, 'must be a valid date after your check in ' \
        'date')
    end
  end

  def future_checkout_time
    if checkin_datetime.present? && checkout_datetime.present? &&
        checkout_datetime <= checkin_datetime
        errors.add(:checkout_time, 'must be a valid time after your check in ' \
        'time.')
    end
  end

  def no_of_rooms_greater_then_0
    errors.add(:number_of_rooms, 'must be 1 or more to make a reservation') if
      number_of_rooms <= 0
  end

  def convert_to_datetime
    if self.checkin_date.present? && self.checkin_time.present?
      self.checkin_datetime =  self.merge_datetime(
        self.checkin_date,
        self.checkin_time
      )
    end
    if self.checkout_date.present? && self.checkout_time.present?
      self.checkout_datetime = self.merge_datetime(
        self.checkout_date,
        self.checkout_time
      )
    end
  end

  def merge_datetime(date1, time1)
    res_date = Date.parse(date1)
    res_time = Time.parse(time1)
    merged_datetime = DateTime.new(
      res_date.year,
      res_date.month,
      res_date.day,
      res_time.hour,
      res_time.min,
      res_time.sec
    )
  end

  def room_name
    room.room_type.name
  end

  def decrease_room_inventory
  room.update(inventory: (room.inventory -= number_of_rooms))
  end

  def self.default_checkin_date
    DateTime.now.strftime('%Y-%m-%d')
  end

  def self.default_checkin_time
    (DateTime.now.midday + 3.hours).strftime('%H:%M')
  end

  def self.default_checkout_date
    DateTime.now.tomorrow.strftime('%Y-%m-%d')
  end

  def self.default_checkout_time
    (DateTime.tomorrow.midday).strftime('%H:%M')
  end

  def self.users_reservations(user)
    where('user_id = ?', user)
  end

  def reservation_date(booking_datetime)
    booking_datetime.strftime('%Y-%m-%d')
  end

  def reservation_time(booking_datetime)
    booking_datetime.strftime('%H:%M')
  end

  def self.reservations_checkin_setter(reservations)
    reservations.each do |reservation|
      reservation.checkin_date = reservation.reservation_date(
        reservation.checkin_datetime
      )
      reservation.checkin_time = reservation.reservation_time(
        reservation.checkin_datetime
      )
    end
  end

  def self.reservations_checkout_setter(reservations)
    reservations.each do |reservation|
      reservation.checkout_date = reservation.reservation_date(
        reservation.checkout_datetime
      )
      reservation.checkout_time = reservation.reservation_time(
        reservation.checkout_datetime
      )
    end
  end

  def hotel_name
    room.hotel.name
  end

  def increase_room_inventory
    room.update(inventory: (room.inventory += number_of_rooms))
  end

  def self.reservation_checkin_setter(reservation)
    reservation.checkin_date = reservation.reservation_date(
      reservation.checkin_datetime
    )
    reservation.checkin_time = reservation.reservation_time(
      reservation.checkin_datetime
    )
  end

  def self.reservation_checkout_setter(reservation)
    reservation.checkout_date = reservation.reservation_date(
      reservation.checkout_datetime
    )
    reservation.checkout_time = reservation.reservation_time(
      reservation.checkout_datetime
    )
  end

  def alter_room_inventory(orginal_number)
    if number_of_rooms != orginal_number.to_i
      room = Room.find(room_id)
        room.update(inventory: (room.inventory += orginal_number.to_i))
      answer = self.room_available?(room.room_type)
      if answer[0]
        self.decrease_room_inventory
      else
        room.update(inventory: (room.inventory -= orginal_number.to_i))
      end
      answer
    else
      false
    end
  end

  def room_available?(room_type)
    if Room.find(room_id).inventory == 0
      message = "Unfortunately, all of those #{room_type.name} rooms have "\
        "been reserved. Please select another room"
      return false, message
    elsif number_of_rooms > Room.find(room_id).inventory
      message = "Unfortunately, your desired quantity of the " \
      "#{room_type.name} room is not available. Please select another " \
      "room, or reserve less rooms of this type"
      return false, message
    else
      [true]
    end
  end

  def user_view_reservation_date(booking_datetime)
    booking_datetime.to_date.strftime('%A, %B %d, %Y')
  end

  def user_view_reservation_time(booking_datetime)
    booking_datetime.to_time.strftime('%l:%M %P')
  end

  def total_nights
    (checkout_datetime.to_date - checkin_datetime.to_date).to_i
  end

  def total_price
    nights = self.total_nights == 0? 1 : self.total_nights
    cost = nights * room.room_rate * number_of_rooms
    taxes = cost * 0.15
    cost + taxes
  end
end

_reservation.html.erb

<div>
  <h3><%= reservation.room_name %> at <%= reservation.hotel_name %></h3>
  <ul>
    <strong>Check In: </strong>
    <%= reservation.user_view_reservation_time(reservation.checkin_time) %> on
      <%= reservation.user_view_reservation_date(reservation.checkin_date) %>
    <br />
    <strong>Check out: </strong>
    <%= reservation.user_view_reservation_time(reservation.checkout_time) %> on
      <%= reservation.user_view_reservation_date(reservation.checkout_date) %>
    <br />
    <strong>Rooms: </strong>
    <%= reservation.number_of_rooms %><br />
  </ul>

  <h3>Your Rate</h3>
  <ul>
    <strong>Total Nights: </strong>
    <%= reservation.total_nights %><br />
    <strong>Average Nightly Rate: </strong>
    <%= number_to_currency(reservation.room.room_rate) %><br />
    <strong>Estimated Total Price: </strong>
    <%= number_to_currency(reservation.total_price) %><br />
  </ul>

  <%= button_to 'Edit',
    edit_reservation_path(reservation, reservation.id), method: 'get',
    class: 'btn btn-large btn-primary' %><br />
  <%= button_to 'Delete', reservation_path(reservation), method: 'delete',
    data: { confirm: 'Are you sure you want to delete this reservation?' },
    class: 'btn btn-large'%>
</div>

reservations_controller.rb

class ReservationsController < ApplicationController
  before_action :require_login
  before_action :set_reservation, only: [:edit, :update, :destroy]

  def index
    @reservations = Reservation.users_reservations(current_user)
    Reservation.reservations_checkin_setter(@reservations)
    Reservation.reservations_checkout_setter(@reservations)
  end

  def create
    @reservation = Reservation.new(reservation_params)
    @reservation.checkin_date=(reservation_params[:checkin_date])
    @reservation.checkin_time=(reservation_params[:checkin_time])
    @reservation.checkout_date=(reservation_params[:checkout_date])
    @reservation.checkout_time=(reservation_params[:checkout_time])
    @reservation.convert_to_datetime
    @room_type = RoomType.find(params[:reservation][:room_type_id])
    result = @reservation.room_available?(@room_type)
    if result[0]
      if @reservation.save
        @reservation.decrease_room_inventory
        redirect_to reservations_path,{notice: "Your reservation " \
          "for the #{@reservation.room_name} has been made, $0 are due today"}
      else
        render :'room_types/show'
      end
    else
      redirect_to room_path(@reservation.room.hotel),
        {alert: "#{result[1]}"}
    end
  end

  def edit
    if @reservation.user_id == current_user.id
      Reservation.reservation_checkin_setter(@reservation)
      Reservation.reservation_checkout_setter(@reservation)
      render :edit
    else
      flash[:alert] = "You don't have permission to edit that reservation."
      redirect_to reservations_path
    end
  end

  def update
    @reservation.checkin_date=(reservation_params[:checkin_date])
    @reservation.checkin_time=(reservation_params[:checkin_time])
    @reservation.checkout_date=(reservation_params[:checkout_date])
    @reservation.checkout_time=(reservation_params[:checkout_time])
    @reservation.convert_to_datetime
    @reservation.number_of_rooms = reservation_params[:number_of_rooms]

    result =  @reservation.alter_room_inventory(
      params[:reservation][:orginal_number_of_rooms]
    )
    if !result || result[0]
      if @reservation.save
        redirect_to reservations_path,{notice: "Your reservation " \
          "for the #{@reservation.room_name} has been updated."}
        else
        render :edit
      end
    else
      redirect_to reservations_path, {alert: "#{result[1]}"}
    end
  end


  def destroy
    @reservation.increase_room_inventory
    @reservation.delete
    redirect_to reservations_path,{notice: "Your reservation for " \
      "#{@reservation.checkin_datetime.strftime('%A, %B %d, %Y')} has " \
      "been deleted."}
  end

  private
  def set_reservation
    @reservation = Reservation.find_by(id: params[:id])
  end


  def reservation_params
    params.require(:reservation).permit(
      :checkin_date,
      :checkin_time,
      :checkout_date,
      :checkout_time,
      :number_of_rooms,
      :room_id,
      :user_id
    )
  end
end

用户.rb

class User < ActiveRecord::Base
  has_many :reservations, dependent: :destroy
  has_many :rooms, through: :reservations
  has_many :addresses, dependent: :destroy

  validates_presence_of :name
  has_secure_password
  validates_associated :addresses, unless:
    Proc.new { |user| user.provider.present?}

  def addresses_attributes=(addresses_attributes)
    addresses_attributes.values.each do |address_attributes|
      if address_attributes.keys.include?('id')
        address = self.addresses.find(address_attributes[:id])
        address.update_attributes(address_attributes)
      else
        self.addresses.build(address_attributes)
      end
    end
  end

  def self.from_omniauth(auth)
  where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
      user.provider = auth.provider
      user.uid = auth.uid
      user.name = auth.info.name
      user.password = SecureRandom.hex
    end
  end

  def update_room_inventory
    reservations.each do |reservation|
      reservation.increase_room_inventory
    end
  end
end

路线.rb

Rails.application.routes.draw do
  get '/auth/:provider/callback', to: 'sessions#github'
  resources :addresses, only: [:new, :create, :destroy]
  get '/login', to: 'sessions#new'
  post '/login', to: 'sessions#create'
  delete '/logout', to: 'sessions#destroy'
  resources :users
  resources :reservations, only: [:index, :edit, :update, :destroy]
  resources :rooms, only: :show do
    resources :room_types, only: :show
    resources :reservations, only: :create
  end
  root 'hotels#index'
end

create_reservations.rb

class CreateReservations < ActiveRecord::Migration
  def change
    create_table :reservations do |t|
      t.references :room, index: true, foreign_key: true
      t.references :user, index: true, foreign_key: true
      t.integer :number_of_rooms, default: 1
      t.datetime :checkin_datetime
      t.datetime :checkout_datetime

      t.timestamps null: false
    end
  end
end

标签: ruby-on-rails

解决方案


我看到错误来自 def future_checkin_time错误消息中的错误消息 Checkin time must be a valid current or future time 还必须显示错误消息中的代码签入时间值。您能否打印并检查该值是否被正确捕获?


推荐阅读