Фильтрация нескольких столбцов с помощью Pg_Search в Ruby on Rails

#ruby-on-rails #ruby #filter

#ruby-on-rails #ruby #Фильтр

Вопрос:

Я работаю над проектом, в котором мы должны фильтровать события на основе местоположения, даты, вида спорта и уровня квалификации. На данный момент каждый фильтр работает индивидуально, но я не могу связать их, чтобы получить еще более конкретные результаты.

Это то, что у меня есть в моей модели.

  include PgSearch::Model
  pg_search_scope :global_search, 
  against: [:location, :sport, :level, :date]

  pg_search_scope :date_search,
  against: [:date]

  pg_search_scope :sport_search,
  against: [:sport],
  using: {
    tsearch: { prefix: true }
  }

  pg_search_scope :location_search,
  against: [:location],
  using: {
    tsearch: { prefix: true }
  }

  pg_search_scope :level_search,
  against: [:level]

  enum level: { Beginner: 1, Intermediate: 2, Advanced: 3, Pro: 4 }
 

И это в моем контроллере.

  def index
    if params[:search][:location].present?
      @events = policy_scope(Event).location_search(params[:search][:location])
    elsif params[:search][:sport].present?
      @events = policy_scope(Event).sport_search(params[:search][:sport])
    elsif params[:search][:date].present?
      @events = policy_scope(Event).date_search(params[:search][:date])
    elsif params[:search][:level].present?
      @events = policy_scope(Event).level_search(params[:search][:level])
     
    else
      @events = policy_scope(Event)
    end
  
    @markers = @events.geocoded.map do |event|
      {
        lat: event.latitude,
        lng: event.longitude
      }
    end
  end
 

И это мои фильтры

  <div id="collapseFilters" class="container collapse form">
    <%= simple_form_for :search, url: events_path, method: "GET", html: { class: 'form-block' } do |f| %>
      <%= f.input :date, as: :string, required: false, input_html: {class: "datepicker"} %>
      <%= f.input :level, collection: Event.levels.map{ |l| [l.first, l.second] }, required: false, label_method: :first, value_method: :second%>
      <%= f.input :location, required: false, placeholder: 'Enter a location for your event' %>
      <%= f.button :submit, 'Search', class: "btn btn-primary btn-lg btn-form mt-3" %>
    <% end %>
    </div>
 

Как я мог бы связать их в параметрах, чтобы я мог использовать более одного фильтра одновременно?

Ответ №1:

Вы можете обновить свой контроллер:

 def index
  @events = policy_scope(Event)

  @events = @events.location_search(params[:search][:location]) if params[:search][:location].present?  
  @events = @events.sport_search(params[:search][:sport]) if params[:search][:sport].present?
  @events = @events.date_search(params[:search][:date]) if params[:search][:date].present?
  @events = @events.level_search(params[:search][:level]) if params[:search][:level].present?

  @markers # ...
end
 

или даже (если это достаточно понятно для вас)

 def index
  @events = policy_scope(Event)

  %i[location sport date level].each do |filter|
    next unless params[:search][filter].present?

    @events = @events.public_send("#{filter}_search", params[:search][filter])
  end

  @markers # ...
end
 

если я правильно понимаю, как работает этот драгоценный камень.

Комментарии:

1. Привет, я автор pg_search. Да, это должно сработать.

Ответ №2:

Вы должны использовать опцию multisearchable, как описано в документации https://github.com/Casecommons/pg_search