Как отсортировать пользовательский столбец в ActiveAdmin? - PullRequest
0 голосов
/ 07 июня 2019

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

Я пробовал многократные решения сортировки, и ни одно из них не работало. Я думал о попытке сортировки с помощью пользовательских областей, но я ищу решение в Active Admin.

 index do
    selectable_column
    id_column
    column ("Driver") { |cd| link_to("#{cd.campaign_driver.full_name}", admin_driver_path(cd.campaign_driver.driver_id)) }
    column :started_at
    column :ended_at
    column ("Distance(km)") { |route| route_distance(route) }
    column ("Clean distance(km)") { |route| route_clean_distance(route) }
    column ("Distance diff(km)") { |route| route_distance_diff(route) }
    column ("Duration") { |route| route_duration(route) }
    column ("Average speed") { |route| route_avg_speed(route) }
    actions
  end

Столбец «Разница в расстоянии» должен быть сортируемым.

Ответы [ 2 ]

0 голосов
/ 22 июня 2019

Я думаю, что вам нужно сначала провести рефакторинг вашего метода, сделать его scoped_collection.

controller do
  def scoped_collection
    Route.select("routes.*, (routes.ended_at-routes.ended_at) AS distance_diff_route")
  end
end

Затем переписать ваш индексный столбец в

column :distance_diff_route, sortable: :distance_diff_route
0 голосов
/ 14 июня 2019

Короче говоря, сортировка по виртуальному атрибуту невозможна из-за способов, которые вы пытались использовать.

Вот почему.Когда вы запрашиваете страницу индекса для сортировки по атрибуту, создается запрос к базе данных, в котором БД сортирует записи по этому столбцу.В этом запросе применяются фильтры (если имеются), и результирующие записи в вашей таблице drivers сортируются по выбранному реальному атрибуту, и возвращается только подмножество (в зависимости от настроек подкачки в config/initializers/active_admin.rb config.default_per_page = 30).Ваши вспомогательные методы применяются к этому подмножеству (и, следовательно, если бы он работал, он отсортировал бы только 30 или около того записей).База данных не знает о вашем виртуальном атрибуте и не может соответствующим образом отсортировать все записи.

Для этого есть как минимум два решения:

1) Область действия по умолчанию

Простое решениеиспользуя собственный Rails default_scope.Он изменяет базовый запрос, который используется в качестве базы для построителя запросов модели.Вы можете разгрузить конструкцию виртуальных полей и использовать ее в Rails, см. Пример ниже.Есть недостатки: 1) будет трудно, если ваши виртуальные поля зависят от других таблиц, 2) часто советуют использовать область по умолчанию - Google "rails default scope bad", чтобы наверстать упущенное.

class Route < ApplicationRecord
  default_scope { select(Arel.star, 'md5(name) hashed_name') }
  ...
end

ActiveAdmin.register Route do
  index do
    column :hashed_name, sortable: true
  end
end

2) Модель на основе представления

Надлежащее, но также более сложное решение - создать представление базы данных, которое будет вычислять все необходимые виртуальные поля, а затем построить модель Rails на основе этого представления.Вот ресурс, который может помочь вам достичь этого - https://dan.chak.org/enterprise-rails/chapter-11-view-backed-models/

...