初めての投稿です!
プログラミングスクール3ヶ月目でPFで架空のホテルのホームページを制作しました。
予約する時の空室検索を実装するときに参考になる記事を見つけることができず苦労したので参考になればと思い共有させていただきます。
※本格的なものではありません!
※検索ページ↑
##仕組み
ホテルにはA、B、Cという部屋がある。
・Aタイプはホテルに3室、Bタイプはホテルに5室、Cタイプはホテルに10室(部屋数:capacity)というように制限がある。
・それぞれの客室に定員数が決まっている(定員数:people)・ユーザーがチェックイン日(start_date)とチェックアウト日(end_date)とpeople(定員数)を入力して検索し、宿泊できる部屋を一覧で表示するといった流れです。
連泊での予約はできない
客室からの空室検索はできない
といった点に注意してください。
##実装
カラム名
start_date チェックイン日(到着日)
end_date チェックアウト日(出発日)
people 定員数
空室検索ページのビューです。
<%= form_with model: @reservation, url: room_reservations_path do |f| %>
<label for="reservation_start_date">チェックイン日</label><%= f.date_field :start_date, required: true %>
<label for="reservation_end_date">チェックアウト日</label>
<%= f.date_field :end_date, required: true %>
<label for="reservation_people">宿泊人数</label>
<%= f.select :people, [1,2,3,4] %>
<%= f.submit "検索", class: "button", id: "button" %>
<% end %>
form_withで選択された日付がreservationコントローラのroomに飛ぶように指定しているのでroomアクションに記述していきたいと思います↓
class ReservationsController < ApplicationController
def search
@reservation = Reservation.new
end
def room
@start_date = Date.parse(reservation_params[:start_date])
@end_date = Date.parse(reservation_params[:end_date])
reservations = Reservation.where(start_date: @start_date...@end_date).group(:room_id)
not_available_room_ids = []
reservations.each do |reservation|
room_reservation = Reservation.where(start_date: @start_date...@end_date)
.where(room_id: reservation.room.id)
# 予約されてる部屋の件数 == 実際にある部屋数
if room_reservation.count == reservation.room.capacity
# 予約不可の部屋のID << 予約できない部屋のIDを配列に追加
not_available_room_ids << reservation.room.id
end
end
@people = (reservation_params[:people]).to_i
room_all = Room.all
room_all.each do |room|
# 選択された人数 > 部屋の定員数
if @people > room.people
not_available_room_ids << room.id
end
end
# .notで予約不可の部屋のID以外を@roomsに代入
@rooms = Room.where.not(id: not_available_room_ids)
end
end
順を追って説明します。
まず1行目と2行目の@start_dateと@start_dateに選択された日付を取得し代入し、
reservationsには選択された日付の予約されている部屋をgrepで取得。
ここでは予約されている部屋の種類はどれかという情報だけ。
@start_date = Date.parse(reservation_params[:start_date])
@end_date = Date.parse(reservation_params[:end_date])
reservations = Reservation.where(start_date: @start_date...@end_date).group(:room_id)
次に宿泊不可の部屋を入れるための空の配列を作成。
not_available_room_ids = []
reservationsの情報をもとに選択された日付の予約されている部屋の予約をroom_reservationに代入する。
条件分岐で予約されている部屋の件数と実際にある部屋数(capasity)が一緒ならその部屋は満室ということなので、その部屋のIDを先ほど作った配列(not_available_room_ids)に入れる。
reservations.each do |reservation|
room_reservation = Reservation.where(start_date: @start_date...@end_date)
.where(room_id: reservation.room.id)
# 予約されてる部屋の件数 == 実際にある部屋数
if room_reservation.count == reservation.room.capacity
# 予約不可の部屋のID << 予約できない部屋のIDを配列に追加
not_available_room_ids << reservation.room.id
end
人数も同じように条件分岐で選択された人数と定員数を比べ、宿泊不可の部屋の配列へ入れています(例:定員数は2名なのに3名で選択されたら2名以下が定員数のの部屋は検索結果に表示されないようにする)
最後に、予約不可の部屋のIDの配列を使い、@roomsに宿泊できる部屋をwhereで抽出し、検索結果のページには@roomsをeach分で回して表示しています。
@rooms = Room.where.not(id: not_available_room_ids)
他の実装方法もあると思うので参考までに!