I'm working on improving my search functionality in my app by using models.
This is what I've been using so far:
searchController#index
:
def index
# Enable display of results page on direct access with no params
return false if params[:s].nil?
# Venues near search location using Lon/Lat and Geocoder
@venues = Venue.near eval(params[:s]["geo"])
# Search variables
near_by_venues = @venues.to_a.map(&:id)
s_activity = params[:s]["activity"].to_i
s_start_time = (params[:s]["start_time"]).to_datetime
s_end_time = (params[:s]["end_time"]).to_datetime
# Filter availabilities based on search criteria
@search = Availability.includes{facility.activities}
.where{
(facility.venue_id.in near_by_venues)
}
.where{
(activities.id == s_activity) &
(booking_id == nil) &
(start_time >= s_start_time ) &
(end_time <= s_end_time )
}
.order{start_time.desc}
.references(:all)
end
This has worked well for me so far but I started thinking other use cases for search, like optional parameters or default parameters if for some reason a location wasn't provided or start/end time wasn't specified. This lead me to articles regarding scoped search where everything is handled at the model level instead of the controller.
I created these scopes in my Availability
model:
class Availability < ActiveRecord::Base
# Associations
belongs_to :facility
belongs_to :booking
# Scopes for search filters
scope :close_to, -> (locations) { where{facility.venue_id.in locations} }
scope :activity, -> (activity) {where {activities.id == activity}}
scope :start_date, -> (datetime) {where{created_at >= datetime}}
scope :end_date, -> (datetime) {where{created_at <= datetime}}
scope :not_booked, -> {where(booking: nil)}
scope :order, -> {order{start_time.desc}}
end
I'm having trouble putting it all together. I'm not sure how to include the joins I have includes{facility.activities}
in the model so when I do something like Availability.activity(5).not_booked
it returns correctly.
You can include
the activity
within availability
in the following fashion:
scope :activity, -> (activity) { includes({facility: :activities}).where{activities.id == activity}.references(:all) }