Bagaimana cara memasukkan filter default ke Filterrific get

Saya akhirnya membuat filterrific saya berfungsi dan ini merupakan permata yang luar biasa, jika tidak sedikit rumit untuk pemula seperti saya.

Halaman indeks asli saya memfilter catatan aktif berdasarkan catatan terdekat dengan pengguna seperti ini:

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

Jadi ini menarik semua Janji dengan Vendor di area tersebut, tapi bagaimana cara meneruskannya ke pencarian 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

Sepertinya Filterrerrific memuat SEMUA janji temu secara default, tetapi saya ingin membatasi hanya pada janji temu terdekat. Apa yang saya lewatkan?


person Seth Merritt    schedule 24.12.2016    source sumber


Jawaban (1)


Apa yang tampaknya Anda lewatkan adalah param default_filter_params untuk memfilter makro yang bagus dalam model. (Pertanyaan Anda tidak menyebutkan bahwa Anda melakukan penyesuaian apa pun pada model VendorLocation, karena itulah objek yang ingin Anda filter, di situlah makro harus dipanggil. Mungkin Anda baru saja menghilangkannya dari pertanyaan Anda...)

Dari dokumen model:

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

Anda mungkin sudah menemukannya, itu ada di halaman pertama dokumentasi, tetapi ada hal yang lebih penting dalam contoh aplikasi yang Anda perlukan (Saya juga mengalami ini, ketika saya baru saja menggunakan Filterrific untuk pertama kalinya.)

Informasi di halaman awal tidak cukup untuk membantu Anda memulai. Anda harus membaca lebih jauh untuk melihat cara lain yang mungkin Anda perlukan untuk mengubah model, akses model, dan tampilan untuk mendukung Filterrific.

Bagian yang membuat pengaturan filter default efektif adalah hash default_filter_params ini (BUKAN select_options, yang menyediakan opsi untuk "pilih" alias kotak dropdown. Itu bukan yang Anda inginkan sama sekali, kecuali Anda melakukan filter dropdown.) Hash ini berlaku daftar cakupan yang perlu diterapkan secara default (kunci hash) dan parameter cakupan digunakan sebagai nilai hash.

Hash default_filter_params itu mungkin bukan satu-satunya hal yang Anda lewatkan... Anda juga harus mendefinisikan cakupan ActiveRecord tersebut untuk setiap filter yang ingin Anda gunakan dalam model, dan beri nama ini dalam available_filters seperti di atas agar tersedia untuk filterrific:

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

Semua cakupan ini harus mengambil argumen (nilai berasal dari nilai bidang filter pada halaman tampilan, Anda harus menambahkan ini ke tampilan meskipun Anda ingin menyembunyikannya dari pengguna). Penting juga agar mereka selalu mengembalikan asosiasi ActiveRecord.

Ini lebih seperti yang Anda inginkan:

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

Masalah dengan pendekatan ini adalah dalam kasus Anda, tidak ada location_string atau variabel lokasi tunggal apa pun, Anda memiliki banyak koordinat untuk parameter lokasi Anda. Namun Anda bukanlah orang pertama yang mengalami masalah ini!

Masalah ini menjelaskan hampir persis masalah yang ingin Anda selesaikan. Penulis Filterrific merekomendasikan untuk menyematkan bidang lokasi ke dalam bidang formulir tersembunyi di fields_for yang disarangkan, sehingga formulir tersebut masih dapat meneruskan satu argumen ke dalam cakupan (seperti dalam 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 %>

... buat perubahan itu di tampilan Anda, dan tambahkan cakupan pencocokan yang terlihat seperti (disalin dari masalah GitHub tertaut):

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']])
}

Jadi, cakupan Anda :with_distance harus masuk ke model VendorLocation dan mungkin akan terlihat seperti ini:

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

Terakhir, Anda mungkin memperhatikan bahwa saya menghapus panggilan Anda ke includes(:location) Saya tahu Anda sengaja meletakkannya di sana, dan saya tidak menemukannya dengan jelas di dokumentasi, tetapi Anda masih bisa bersemangat memuat dan mengoptimalkan ActiveRecord ke dalam kueri tunggal sebelum meneruskan filter berfungsi ke Filterrific dengan mendefinisikan metode indeks pengontrol Anda dengan cara ini:

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

Semoga ini membantu!

person Kingdon    schedule 01.05.2017
comment
Para downvoter drive-by... mengapa jawaban ini tidak dianggap bermanfaat? - person Kingdon; 03.08.2017
comment
Terima kasih, tidak mudah menemukan dokumentasi tentang ....filterrific_find(@filteriffic)... pada Relasi Aktif, harus menyimpulkannya dari kode sumber, lalu saya menemukan pertanyaan & jawaban ini! - person Steve Folly; 31.01.2018
comment
Terima kasih! Filterrific sangat sulit untuk dipahami pada awalnya, tetapi setelah saya memahami cara menerapkannya dengan benar, filterrific menjadi sangat berguna. Membaca ini jika dipikir-pikir, saya sedikit terkejut karena saya berhasil mengetahui semuanya. - person Kingdon; 31.01.2018