过滤器未合并查询pgsearch

时间:2018-12-19 18:23:10

标签: ruby-on-rails postgresql forms parameters pg-search

我的餐厅Rails应用程序内置了一个过滤器。用户能够过滤食物的样式,价格和面积。 enter image description here

分别选择一个过滤器,搜索查询将完全按预期工作。如果我在牛排馆过滤,我会得到所有的牛排馆。如果我按某个价格水平进行过滤,则会得到所有具有该价格水平的餐厅,等等。

但是每当我想将其中的2个或3个合并时。食物的风格似乎总是比其他地方更受青睐,因此,无论价格和面积如何,我只会得到牛排屋。如果将价格水平和面积相结合,我将再次获得整个餐馆清单。

我想对如何使过滤器组合所有3个参数并仅显示与这些参数匹配的结果提出一些建议。

我的路线:

Rails.application.routes.draw do
  root to: 'restaurants#featured'
  get '/tagged', to: "restaurants#tagged", as: :tagged
  get 'index_ibiza', to: "restaurants#index_ibiza", as: :index_ibiza
  get 'index_formentera', to: "restaurants#index_formentera", as: :index_formentera
  devise_for :users

  require "sidekiq/web"
  authenticate :user, lambda { |u| u.admin } do
    mount Sidekiq::Web => '/sidekiq'
  end

  resources :restaurants do
    collection do
      get 'featured', to: 'restaurants#featured'
      get 'ibiza', to: 'restaurants#ibiza'
      get 'formentera', to: 'restaurants#formentera'
      get 'restaurant_ibiza', to: 'restaurants#restaurant_ibiza'
      get 'beach_restaurant_ibiza', to: 'restaurants#beach_restaurant_ibiza'
      get 'cafe_ibiza', to: 'restaurants#cafe_ibiza'
      get 'restaurant_formentera', to: 'restaurants#restaurant_formentera'
      get 'beach_restaurant_formentera', to: 'restaurants#beach_restaurant_formentera'
      get 'cafe_formentera', to: 'restaurants#cafe_formentera'
    end
  end
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end

餐厅模型:

class Restaurant < ApplicationRecord
  belongs_to :user
  has_many_attached :images
  acts_as_taggable_on :tags
  geocoded_by :address
  after_validation :geocode, if: :will_save_change_to_address?
  reverse_geocoded_by :latitude, :longitude, address: :full_address
  after_validation :reverse_geocode
  after_validation :save_city_zipcode, :assign_zipcode_to_municipal

  def save_city_zipcode
    self.zipcode = Geocoder.search([self.latitude, self.longitude]).first.data["address"]["postcode"]
  end

  def assign_zipcode_to_municipal
    case self.zipcode
    when "07800"
      return self.municipal = "Ibiza"
    when "07840", "07849"
      return self.municipal = "Santa Eulalia del Río"
    when "07817", "07818", "07829", "07830", "E-07830", "07839"
      return self.municipal = "San José"
    when "07820", "07816"
      return self.municipal = "San Antonio Abad"
    when "07240", "07810", "07815"
      return self.municipal = "San Juan Bautista"
    when "07872"
      return self.municipal = "Es Caló de Sant Agustí"
    when "07860"
      return self.municipal = "San Francisco Javier"
    when "07870"
      return self.municipal = "La Savina"
    when "07871"
      return self.municipal = "Es Pujols / Sant Ferran de Ses Roques"
    when "07872"
      return self.municipal = "El Pilar de La Mola"
    else
      return self.municipal = ""
    end
  end

  # Validations
  validates :name, presence: true, length: { minimum: 2 }
  validates :island, inclusion: { in: ["Ibiza", "Formentera"] }
  validates :price, inclusion: { in: ["€", "€€", "€€€"] }
  validates :website, format: { with: /\A(http|ftp|https)?(\:\/\/)?[\w-]+(\.[\w-]+)+([\w.,@?^!=%&amp;:\/~+#-]*[\w@?^=%&amp;\/~+#-])+$\z/,
    message: "only allows url links" } , allow_blank: true, presence: false
  validates :rating, inclusion: { in: [1, 2, 3, 4, 5] }
  validates :description, presence: true, allow_blank: false
  validates :images, attached: true, content_type: ['image/png', 'image/jpg', 'image/jpeg'], allow_blank: true, presence: false

  include PgSearch
  pg_search_scope :search_by_name_city_or_island,
      :against => {
        :name => 'A',
        :municipal => 'B',
        :price => 'C'
      },
      :associated_against => {
         :tags => [:name]
        },
      :using => {
        :tsearch => { :prefix => true, :dictionary => "simple" },
        :trigram => {
          :threshold => 0.5,
          :only => [ :name, :price ]
        }
      },
      :ignoring => :accents,
      :ranked_by => ":trigram"

end

查看过滤器:

<div class="container index-container content" style="margin-bottom: 0px;">
  <div class="row">
    <div class="col-sm-12">
      <form action="" class="form-inline">
        <div class="form-group">
          <%= form_tag index_ibiza_path, method: :post do %>
            <%= select_tag :tags, options_for_select([ "steakhouse", "mexican", "italian", "indian", "chinese", "thai", "french", "seafood" ]), include_blank: true %>
            <%= select_tag :price, options_for_select([ "€", "€€", "€€€"]), include_blank: true %>
            <%= select_tag :municipal, options_for_select([ "Es Caló de Sant Agustí", "San Francisco Javier", "La Savina", "Es Pujols / Sant Ferran de Ses Roques", "El Pilar de La Mola" ]), include_blank: true %>
            <%= submit_tag "Filter" %>
          <% end %>
        </div>
      </form>
    </div>
  </div>
</div>

控制器:

class RestaurantsController < ApplicationController
  skip_before_action :authenticate_user!, only: [
    :index,
    :show,
    :featured,
    :ibiza,
    :formentera,
    :restaurant_ibiza,
    :beach_restaurant_ibiza,
    :cafe_ibiza,
    :restaurant_formentera,
    :beach_restaurant_formentera,
    :cafe_formentera,
    :tagged,
    :index_ibiza,
    :index_formentera
  ]
  before_action :set_restaurant, only: [ :show, :edit, :update, :destroy ]

  def index
    if params[:query].present?
      if @restaurants = Restaurant.where.not(latitude: nil, longitude: nil).search_by_name_city_or_island(params[:query]).present?
        @restaurants = Restaurant.where.not(latitude: nil, longitude: nil).search_by_name_city_or_island(params[:query])
        markers(@restaurants)
      else
        render :no_results_search
      end
    else
      @restaurants = Restaurant.where.not(latitude: nil, longitude: nil).all.order(:name)
      markers(@restaurants)
    end
  end

  def index_ibiza
    if params[:tags].present?
      @restaurants = Restaurant.where.not(latitude: nil, longitude: nil).where(island: 'Ibiza').search_by_name_city_or_island(params[:tags])
      markers(@restaurants)
    elsif params[:price].present?
      @restaurants = Restaurant.where.not(latitude: nil, longitude: nil).where(island: 'Ibiza').where("price ILIKE ?", "%#{params[:price]}%")
      markers(@restaurants)
    elsif params[:municipal].present?
      @restaurants = Restaurant.where.not(latitude: nil, longitude: nil).where(island: 'Ibiza').search_by_name_city_or_island(params[:municipal])
      markers(@restaurants)
    else
      @restaurants = Restaurant.where.not(latitude: nil, longitude: nil).where(island: 'Ibiza').order(:name)
      markers(@restaurants)
    end
  end

  def index_formentera
    if params[:tags].present?
      @restaurants = Restaurant.where.not(latitude: nil, longitude: nil).where(island: 'Formentera').search_by_name_city_or_island(params[:tags])
      markers(@restaurants)
    elsif params[:price].present?
      @restaurants = Restaurant.where.not(latitude: nil, longitude: nil).where(island: 'Formentera').where("price ILIKE ?", "%#{params[:price]}%")
      markers(@restaurants)
    elsif params[:municipal].present?
      @restaurants = Restaurant.where.not(latitude: nil, longitude: nil).where(island: 'Formentera').search_by_name_city_or_island(params[:municipal])
      markers(@restaurants)
    else
      @restaurants = Restaurant.where.not(latitude: nil, longitude: nil).where(island: 'Formentera').order(:name)
      markers(@restaurants)
    end
  end

  def ibiza
    @restaurants = Restaurant.where(featured: true)
    @ibiza_town = Restaurant.where(zipcode: "07800") || Restaurant.where(geo_city: 'Ibiza Town')
    @santa_eulalia = Restaurant.where(zipcode: ["07840", "07849"])
    @san_jose = Restaurant.where(zipcode: ["07817", "07818", "07829", "07830", "E-07830", "07839"])
    @san_antonio = Restaurant.where(zipcode: ["07820", "07816"])
    @san_juan = Restaurant.where(zipcode: ["07240", "07810", "07815"])
  end

  def restaurant_ibiza
    if params[:tags].present?
      @restaurants = Restaurant.where.not(latitude: nil, longitude: nil).where(island: 'Ibiza').search_by_name_city_or_island(params[:tags])
      markers(@restaurants)
    elsif params[:price].present?
      @restaurants = Restaurant.where.not(latitude: nil, longitude: nil).where(island: 'Ibiza').where("price ILIKE ?", "%#{params[:price]}%")
      markers(@restaurants)
    elsif params[:municipal].present?
      @restaurants = Restaurant.where.not(latitude: nil, longitude: nil).where(island: 'Ibiza').search_by_name_city_or_island(params[:municipal])
      markers(@restaurants)
    else
      results_ibiza(@restaurants)
    end
  end

  def beach_restaurant_ibiza
    if params[:tags].present?
      @restaurants = Restaurant.where.not(latitude: nil, longitude: nil).where(island: 'Ibiza').search_by_name_city_or_island(params[:tags])
      markers(@restaurants)
    elsif params[:price].present?
      @restaurants = Restaurant.where.not(latitude: nil, longitude: nil).where(island: 'Ibiza').where("price ILIKE ?", "%#{params[:price]}%")
      markers(@restaurants)
    elsif params[:municipal].present?
      @restaurants = Restaurant.where.not(latitude: nil, longitude: nil).where(island: 'Ibiza').search_by_name_city_or_island(params[:municipal])
      markers(@restaurants)
    else
      results_ibiza(@restaurants)
    end
  end

  def cafe_ibiza
    if params[:tags].present?
      @restaurants = Restaurant.where.not(latitude: nil, longitude: nil).where(island: 'Ibiza').search_by_name_city_or_island(params[:tags])
      markers(@restaurants)
    elsif params[:price].present?
      @restaurants = Restaurant.where.not(latitude: nil, longitude: nil).where(island: 'Ibiza').where("price ILIKE ?", "%#{params[:price]}%")
      markers(@restaurants)
    elsif params[:municipal].present?
      @restaurants = Restaurant.where.not(latitude: nil, longitude: nil).where(island: 'Ibiza').search_by_name_city_or_island(params[:municipal])
      markers(@restaurants)
    else
      results_ibiza(@restaurants)
    end
  end

  def formentera
    @restaurants = Restaurant.where(featured: true)
    @es_calo = Restaurant.where(zipcode: ["07872"])
    @san_francisco = Restaurant.where(zipcode: ["07860"])
    @la_savina = Restaurant.where(zipcode: ["07870"])
    @es_pujols_sant_ferran = Restaurant.where(zipcode: ["07871"])
    @el_pilar = Restaurant.where(zipcode: ["07872"])
  end

  def restaurant_formentera
    if params[:tags].present?
      @restaurants = Restaurant.where.not(latitude: nil, longitude: nil).where(island: 'Formentera').search_by_name_city_or_island(params[:tags])
      markers(@restaurants)
    elsif params[:price].present?
      @restaurants = Restaurant.where.not(latitude: nil, longitude: nil).where(island: 'Formentera').where("price ILIKE ?", "%#{params[:price]}%")
      markers(@restaurants)
    elsif params[:municipal].present?
      @restaurants = Restaurant.where.not(latitude: nil, longitude: nil).where(island: 'Formentera').search_by_name_city_or_island(params[:municipal])
      markers(@restaurants)
    else
      results_formentera(@restaurants)
    end
  end

  def beach_restaurant_formentera
    @restaurants = Restaurant.where.not(latitude: nil, longitude: nil).where(island: 'Formentera')
    if params[:tags].present?
      @restaurants = Restaurant.where.not(latitude: nil, longitude: nil).where(island: 'Formentera').search_by_name_city_or_island(params[:tags])
      markers(@restaurants)
    elsif params[:price].present?
      @restaurants = Restaurant.where.not(latitude: nil, longitude: nil).where(island: 'Formentera').where("price ILIKE ?", "%#{params[:price]}%")
      markers(@restaurants)
    elsif params[:municipal].present?
      @restaurants = Restaurant.where.not(latitude: nil, longitude: nil).where(island: 'Formentera').search_by_name_city_or_island(params[:municipal])
      markers(@restaurants)
    else
      results_formentera(@restaurants)
    end
  end

  def cafe_formentera
    if params[:tags].present?
      @restaurants = Restaurant.where.not(latitude: nil, longitude: nil).where(island: 'Formentera').search_by_name_city_or_island(params[:tags])
      markers(@restaurants)
    elsif params[:price].present?
      @restaurants = Restaurant.where.not(latitude: nil, longitude: nil).where(island: 'Formentera').where("price ILIKE ?", "%#{params[:price]}%")
      markers(@restaurants)
    elsif params[:municipal].present?
      @restaurants = Restaurant.where.not(latitude: nil, longitude: nil).where(island: 'Formentera').search_by_name_city_or_island(params[:municipal])
      markers(@restaurants)
    else
      results_formentera(@restaurants)
    end
  end

  def featured
    @restaurants = Restaurant.where(featured: true)
  end

  def tagged
    if params[:tag].present?
      @restaurants = Restaurant.tagged_with(params[:tag])
      markers(@restaurants)
    else
      @restaurants = Restaurant.where.not(latitude: nil, longitude: nil).all.order(:name)
      markers(@restaurants)
    end
  end

  def show
    @related_restaurants = @restaurant.find_related_tags
    @markers = [{
      lng: @restaurant.longitude,
      lat: @restaurant.latitude,
      infoWindow: { content: render_to_string(partial: "/restaurants/map_window", locals: { restaurant: @restaurant }) }
    }]
  end

  def new
    @restaurant = Restaurant.new
  end

  def create
    @restaurant = Restaurant.new(restaurant_params)
    @restaurant.user = current_user
    if @restaurant.save
      redirect_to restaurant_path(@restaurant)
    else
      render :new
    end
  end

  def edit
  end

  def update
    if @restaurant.update(restaurant_params)
      redirect_to restaurant_path(@restaurant)
    else
      render :edit
    end
  end

  def destroy
    @restaurant.destroy
    redirect_to restaurants_path
  end

  private

  def set_restaurant
    @restaurant = Restaurant.find(params[:id])
  end

  def results_ibiza(restaurants)
    if @restaurants = Restaurant.where.not(latitude: nil, longitude: nil).where(island: 'Ibiza').where(category: params[:query]).present?
      @restaurants = Restaurant.where.not(latitude: nil, longitude: nil).where(island: 'Ibiza').where(category: params[:query])
      markers(@restaurants)
    else
      render :no_results
    end
  end

  def results_formentera(restaurants)
    if @restaurants = Restaurant.where.not(latitude: nil, longitude: nil).where(island: 'Formentera').where(category: params[:query]).present?
      @restaurants = Restaurant.where.not(latitude: nil, longitude: nil).where(island: 'Formentera').where(category: params[:query])
      markers(@restaurants)
    else
      render :no_results
    end
  end

  def markers(restaurants)
    if @restaurants
      @markers = @restaurants.map do |restaurant|
        {
         lng: restaurant.longitude,
         lat: restaurant.latitude,
         infoWindow: { content: render_to_string(partial: "/restaurants/map_window", locals: { restaurant: restaurant }) }
        }
      end
    elsif @restaurants_ibiza
      @markers = @restaurants_ibiza.map do |restaurant|
        {
         lng: restaurant.longitude,
         lat: restaurant.latitude,
         infoWindow: { content: render_to_string(partial: "/restaurants/map_window", locals: { restaurant: restaurant }) }
        }
      end
    else
       @markers = @restaurants_formentera.map do |restaurant|
        {
         lng: restaurant.longitude,
         lat: restaurant.latitude,
         infoWindow: { content: render_to_string(partial: "/restaurants/map_window", locals: { restaurant: restaurant }) }
        }
      end
    end
  end

  def restaurant_params
    params.require(:restaurant).permit(
      :name,
      :address,
      :full_address,
      :zipcode,
      :phone,
      :email,
      :facebook,
      :instagram,
      :twitter,
      :website,
      :city,
      :island,
      :featured,
      :active,
      :style,
      :price,
      :rating,
      :longitude,
      :latitude,
      :description,
      :opening_hours_morning,
      :closing_hours_morning,
      :opening_hours_afternoon,
      :closing_hours_afternoon,
      :municipal,
      tag_list: [],
      images: []
      )
  end
end

0 个答案:

没有答案