Как передать фильтр по умолчанию в Filterrific get

Я, наконец, заставил свою фильтрацию работать, и это отличная жемчужина, если не немного сложная для такого нуба, как я.

Моя исходная индексная страница фильтровала активные записи на основе тех, которые находятся рядом с пользователем, следующим образом:

def index 

location_ids = Location.near([session[:latitude], session[:longitude]], 50, order: '').pluck(:id)
@vendor_locations = VendorLocation.includes(:location).where(location_id: location_ids)

@appointments = Appointment.includes(:vendor).
  where(vendor_id: @vendor_locations.select(:vendor_id))

end

Таким образом, это вытягивает все встречи с поставщиками в этом районе, но как мне передать это в поиск Filterrific:

@filterrific = initialize_filterrific(
  params[:filterrific],
  select_options:{ sorted_by: Appointment.options_for_sorted_by, with_service_id: Service.options_for_select },
  ) or return

@appointments = @filterrific.find.page(params[:page])

respond_to do |format|
  format.html
  format.js
end

Кажется, что Filterrerrific по умолчанию загружает ВСЕ встречи, но я хочу ограничиться ближайшими. Что мне не хватает?


person Seth Merritt    schedule 24.12.2016    source источник


Ответы (1)


Кажется, вам не хватает параметра default_filter_params для фильтрующего макроса в модели. (В вашем вопросе не упоминалось, что вы внесли какие-либо коррективы в модель VendorLocation, поскольку это объект, который вы хотите отфильтровать, именно здесь должен вызываться макрос. Возможно, вы просто пропустили его в своем вопросе...)

Из документов модели:

filterrific(
    default_filter_params: { sorted_by: 'created_at_desc' },
    available_filters: [
      :sorted_by,
      :search_query,
      :with_country_id,
      :with_created_at_gte
    ]
  )

Вы, вероятно, уже нашли это, это было на первой странице документации, но в примере приложения есть более важные вещи, которые вам нужны (я тоже столкнулся с этим, когда совсем недавно впервые использовал Filterrific).

Информации на стартовой странице недостаточно, чтобы начать работу. Вы должны прочитать немного дальше, чтобы увидеть другие способы, которыми вам может понадобиться изменить свои модели, доступ к модели и представления для поддержки Filterrific.

Частью, которая делает настройку фильтра по умолчанию эффективной, является этот хэш default_filter_params (НЕ select_options, который предоставляет параметры для «выбора», также известного как раскрывающиеся списки. Это совсем не то, что вам нужно, если только вы не используете раскрывающийся фильтр.) Этот хеш содержит список областей, которые должны быть применены по умолчанию (ключи хеш-функции), а параметр области используется в качестве значения хеш-функции.

Этот хэш default_filter_params может быть не единственным, чего вам не хватает... Вы также должны определить эти области ActiveRecord для каждого фильтра, который вы хотите использовать в модели, и назвать их в available_filters, как указано выше, чтобы сделать их доступными для filterrific:

scope :with_created_at_gte, lambda { |ref_date|
  where('created_at >= ?', ref_date)
end

Важно, чтобы все эти области действия принимали аргумент (значение исходит из значения поля фильтра на странице представления, вы должны добавить их в свое представление, даже если хотите скрыть их от пользователя). Также важно, чтобы они всегда возвращали ассоциации ActiveRecord.

Это больше похоже на то, что вы хотите:

scope :location_near, lambda { |location_string|
  l = Location.near(location_string).pluck(:id)
  where(location_id: l)
end

Проблема с этим подходом заключается в том, что в вашем случае нет location_string или какой-либо одной переменной местоположения, у вас есть несколько координат для параметров вашего местоположения. Но вы вообще не первый человек с такой проблемой!

Эта проблема почти точно описывает проблему, которую вы намеревались решить. Автор Filterrific рекомендовал встраивать поля местоположения в скрытые поля формы во вложенном fields_for, чтобы форма по-прежнему могла передавать в область видимости один аргумент (как в with_distance_fields):

<%= f.fields_for :with_distance do |with_distance_fields| %>
  <%= with_distance_fields.hidden_field :lat, value: current_user.lat %>
  <%= with_distance_fields.hidden_field :lng, value: current_user.lng %>
  <%= with_distance_fields.select :distance_in_meters, 
    @filterrific.select_options[:with_distance] %>
<% end %>

... внесите это изменение в свое представление и добавьте соответствующую область, которая выглядит примерно так (скопировано из связанной проблемы GitHub):

scope :with_distance,  -> (with_distance_attrs) {
  ['lng' => '-123', 'lat' => '49', 'distance_in_meters' => '2000']
  where(%{
    ST_DWithin(
      ST_GeographyFromText(
        'SRID=4326;POINT(' || courses.lng || ' ' || courses.lat || ')'
      ),
      ST_GeographyFromText('SRID=4326;POINT(%f %f)'),
      %d
    )
  } % [with_distance_attrs['lng'], with_distance_attrs['lat'], with_distance_attrs['distance_in_meters']])
}

Таким образом, ваша область видимости :with_distance должна перейти к модели VendorLocation и, вероятно, должна выглядеть так:

scope :with_distance,  -> (with_distance_attrs) {
  lat = with_distance_attrs['lat']
  lng = with_distance_attrs['lng']
  dist = with_distance_attrs['distance']
  location_ids = Location.near([lat, lng], dist, order: '').pluck(:id)
  where(location_id: location_ids)
end

И последнее, но не менее важное: вы, вероятно, заметили, что я удалил ваш вызов includes(:location). Я знаю, что вы поместили его туда намеренно, и я не нашел его очень ясным в документации, но вы все равно можете получить нетерпеливую загрузку и оптимизировать ActiveRecord в один запрос перед передачей работы фильтра в Filterrific, определив метод индекса вашего контроллера следующим образом:

def index
  @appointments = Appointment.includes(:vendor).
    filterrific_find(@filterrific).page(params[:page])
end

Надеюсь это поможет!

person Kingdon    schedule 01.05.2017
comment
Проезжавшие мимо пользователи ... почему этот ответ не был сочтен полезным? - person Kingdon; 03.08.2017
comment
Спасибо, нелегко найти документацию по ....filterrific_find(@filteriffic)... в Active Relation, пришлось вывести ее из исходного кода, затем я нашел этот вопрос и ответ! - person Steve Folly; 31.01.2018
comment
Благодарю вас! Поначалу было очень сложно разобраться с Filterrific, но как только я понял, как правильно его применять, он стал действительно мощным. Прочитав это задним числом, немного шокирован тем, что я все понял. - person Kingdon; 31.01.2018