我正在使用模型改进我的应用中的搜索功能。
这是我到目前为止所使用的:
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
到目前为止,这对我来说效果很好,但我开始考虑搜索的其他用例,如可选参数或默认参数,如果由于某种原因没有提供位置或者没有指定开始/结束时间。这引出了一些关于范围搜索的文章,其中所有内容都是在模型级而不是控制器上处理的。
我在Availability
模型中创建了这些范围:
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
我无法将它们放在一起。我不确定如何在模型中包含includes{facility.activities}
的联接,因此当我执行类似Availability.activity(5).not_booked
的操作时,它会正确返回。
答案 0 :(得分:1)
您可以通过以下方式include
activity
内的availability
:
scope :activity, -> (activity) { includes({facility: :activities}).where{activities.id == activity}.references(:all) }
答案 1 :(得分:1)
有很多方法可以做到这一点,但为了简单起见,我把这些事情放在了一个问题上。例如,在app / models / concerns
中的AvailabilitySearch在可用性中,您包含它
class Availability < ActiveRecord::Base
include AvailabilitySearch
end
然后,在这里,你可以做任何你需要的事情。
module AvailabilitySearch
extend ActiveSupport::Concern
module ClassMethods
def search(params)
results = self.includes(:relation_that_is_always_referenced)
# use scopes or not
results = results.where(:key => params[:key]).includes(:relation_that_is_sometimes_referenced) if params[:key]
results = results.activity(params[:activity) if params[:activity]
...
# and then return your results
return results
end
end
end
最后一件事,在搜索页面添加一些javascript,以便从网址中删除所有空白的输入,因此它是干净的,如果它是共享的则是有意义的。
在coffeescript中,如果搜索表单的ID为&#39; search_form&#39;
$(document).on 'ready page:load', ->
$('#search_form').submit ->
$(this).find(':input').filter(->
!@value
).prop 'disabled', true
true
# If they hit back
$('#search_form').find(':input').prop 'disabled', false
# If they stop and click on the form again
$('#search_form').on 'click', ->
$(this).find(':input').prop 'disabled', false
return