Фильтр не объединяет запросы pgsearch - PullRequest
0 голосов
/ 19 декабря 2018

У меня есть фильтр, встроенный в приложение 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
...