过滤器的最佳范围

时间:2011-12-18 15:24:09

标签: ruby-on-rails ruby-on-rails-3

我想写一些快速范围来过滤我的餐馆。

我这样做

@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的餐馆。 我怎么能尽可能快地做到这一点?

1 个答案:

答案 0 :(得分:1)

SQL中的

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

您需要进行一些完整性检查,例如确保keyRestaurant模型上的属性,但这应该有效。此外,我已经校对了几次,以确保我没有错过任何东西,但这是未经测试的代码,可能有错误或错别字。买者自负。 :)