我想写一些快速范围来过滤我的餐馆。
我这样做
@restaurants = Restaurant.all
@restaurants = filter(@restaurants)
def filter(restaurants)
restaurants = restaurants.filter('types', params[:type].split(',')) unless params[:type].nil?
restaurants = restaurants.filter('cuisines', params[:cuisine].split(',')) unless params[:cuisine].nil?
restaurants = restaurants.filter('facilities', params[:facility].split(',')) unless params[:facility].nil?
restaurants = restaurants.filter('services', params[:service].split(',')) unless params[:service].nil?
restaurants = restaurants.filter('prices', params[:price].split(',')) unless params[:price].nil?
return restaurants
end
其中filter是:
scope :filter, lambda{|type_name, type_id| includes(type_name.to_sym).where(["#{type_name}.id in (?)", type_id]) }
所以...当我得到网址时:
.../search?service=1,2,3
我得到服务1或2或3的餐馆,但我想获得服务1和2和3的餐馆。 我怎么能尽可能快地做到这一点?
答案 0 :(得分:1)
IN
总是将成为OR
操作。您需要首先拆分参数,然后执行多个过滤器。此外,all
回避了AREL的延迟加载,因此您首先加载所有内容然后从那里进行过滤。坏魔鬼。 :)
您是否考虑过这样做?
# restaurant.rb
scope :filter, lambda{|type_name, type_id| includes(type_name.to_sym).where("#{type_name}_id" => type_id) }
# routes.rb
match 'restaurants/search/*query', "restaurants_controller#search"
# restaurants_controller.rb
def search
query = params[:query]
query.delete_at(-1) if query.length % 2 > 0 #Otherwise we'll get an exception for providing an odd number of elements.
search_hash = Hash[*query].symbolize_keys
@restaurants = Restaurant.scoped
search_hash.each do |key, value|
value.split(",").each do |v|
@restaurants.filter(key, v)
end
end
end
然后您的搜索网址就像:
/search/service/1,2,3/type/3,4,5
您需要进行一些完整性检查,例如确保key
是Restaurant
模型上的属性,但这应该有效。此外,我已经校对了几次,以确保我没有错过任何东西,但这是未经测试的代码,可能有错误或错别字。买者自负。 :)