Reputation: 59
I am building a reservation system where users can search for an open reservation. Reservation has an :on scope that filters the reservations that are booked on a given day and time. This filter on Reservations alone works fine, but I also want to add a filter to the Table model for a given seating_capacity
(guests) so I can display all of the booked reservations that match a given seating_capacity
on a given day/time. Any ideas how to add that filter?
Models
class Reservation < ApplicationRecord
belongs_to :user, optional: true
belongs_to :table, optional: true
scope :on, -> (day, time) { where('date = ? AND starts_at <= ? AND ends_at > ?', day, time, time)}
end
class Table < ApplicationRecord
has_many :reservations
has_many :users, through: :reservations
def self.free_on(guests, day, time)
reserved_table_ids = Reservation.on(day, time).pluck('DISTINCT table_id')
reserved_table_ids ? where.not(id: reserved_table_ids) : all
end
def self.reserved_on(guests, day, time)
reserved_table_ids = Reservation.on(day, time).pluck('DISTINCT table_id')
where(id: reserved_table_ids)
end
end
Controller
class TablesController < ApplicationController
def index
@reserved_tables = Table.reserved_on(params[:guests], params[:day], params[:time])
@open_tables = Table.free_on(params[:guests], params[:day], params[:time])
end
end
View
<%= form_tag(tables_path, :method => "get", id: "table-search-form") do %>
<%= text_field_tag :day, params[:day], class:"datepicker", placeholder: "Select Day" %>
<%= text_field_tag :time, params[:time], class:"timepicker", placeholder: "Select Time" %>
<%= submit_tag "Search", :name => nil %>
<% end %>
Schema
create_table "reservations", force: :cascade do |t|
t.integer "user_id"
t.integer "table_id"
t.datetime "date"
t.time "starts_at"
t.time "ends_at"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["table_id"], name: "index_reservations_on_table_id", using: :btree
t.index ["user_id"], name: "index_reservations_on_user_id", using: :btree
end
create_table "tables", force: :cascade do |t|
t.integer "seating_capacity"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
Upvotes: 2
Views: 668
Reputation: 141
@reservationsWithinInterval1 = Reservation.where('startdate >= ? AND startdate < ? , @reservation.startdate, @reservation.enddate)
@reservationsWithinInterval2 = Reservation.where('enddate >= ? AND enddate < ?, @reservation.startdate, @reservation.enddate)
Then check if
if @reservationsWithinInterval1.count > 0 || @reservationsWithinInterval2.count>0
flash[:notice] = 'Select different time. Car already reserved in this time'
Upvotes: 0
Reputation: 4427
Datagrid is good gem to add filters easily on pages.
https://github.com/bogdan/datagrid
checkout demo: http://datagrid.herokuapp.com/
Upvotes: 1
Reputation: 1735
You can implement the seating_capacity scope using joins(:table)
, this is how it looks:
scope :with, -> (capacity) { joins(:table).where(tables: {seating_capacity: capacity}) }
Then you can query specific reservations for day, time and seating_capacity like this:
Reservations.on(day, time).with(capacity)
Upvotes: 1