我的餐厅Rails应用程序内置了一个过滤器。用户能够过滤食物的样式,价格和面积。
分别选择一个过滤器,搜索查询将完全按预期工作。如果我在牛排馆过滤,我会得到所有的牛排馆。如果我按某个价格水平进行过滤,则会得到所有具有该价格水平的餐厅,等等。
但是每当我想将其中的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.,@?^!=%&:\/~+#-]*[\w@?^=%&\/~+#-])+$\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