Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Change default sort order in ActiveAdmin scope

For most models, the default sort order (id desc) is fine. But for a couple of scopes on one of my models, it would make more sense to reverse the order, or order by the updated_at field.

I seem unable to achieve this without breaking other functionality, so I'm hoping someone else might teach me how to do this!

I've tried adding a .order() on the objects I'm returning:

scope :example do |models|
  models.order('id asc')
end

This does not seem to have any effect.

I've also tried unscoping, which kind of works. It does sort my objects the way I want to, but it completely breaks all filtering/search functionality.

scope :example do |models|
  models.unscoped.order('id asc')
end

What to do?

like image 217
rogerkk Avatar asked Jul 12 '13 07:07

rogerkk


4 Answers

This works and also ensures that the default sort order to correctly reflected in the UI.

This is overwriting the apply_sorting method of ActiveAdmin, so all the usual caveats about monkey patching third party gems apply.

  module ActiveAdmin
    class ResourceController < BaseController
      module CallableSortOrder
        def apply_sorting(chain)
          params[:order] ||= if active_admin_config.sort_order&.respond_to?(:call)
                               active_admin_config.sort_order.call(self)
                             else
                               active_admin_config.sort_order
                             end
          super
        end
      end

      prepend CallableSortOrder
    end
  end

Use it like this:

  config.sort_order = ->(controller) {
    controller.params[:scope] == 'something' ? 'created_at_desc' : 'name_asc'
  }
like image 56
Sam Stickland Avatar answered Nov 18 '22 21:11

Sam Stickland


use config.sort_order like:

config.sort_order = "updated_at_desc"
like image 22
yxf Avatar answered Nov 18 '22 21:11

yxf


Why not make 2 scopes in your model, one for a particular sort order, the other, reversed, then in ActiveAdmin set one as the default?

scope :example_asc, :default => true
scope :example_desc

If that doesn't work for you, perhaps create a controller block in ActiveAdmin that defines what you're trying to do:

controller do
  def asc
    Model.order('id ASC')
  end
  def desc
    Model.order('id DESC')
  end
end

scope :example do |models|
  asc
end

scope :example do |models|
  desc
end

And finally, I think this answer is probably fairly accurate: https://stackoverflow.com/a/17612718/175825

But you might want to investigate more about how you can implement sort_order:

  • https://github.com/gregbell/active_admin/blob/master/lib/active_admin/dsl.rb#L25
  • https://github.com/gregbell/active_admin/blob/master/lib/active_admin/dsl.rb#L97

For what it's worth, I'm not a fan of ActiveAdmin's skinny docs. Good luck.

like image 5
corysimmons Avatar answered Nov 18 '22 22:11

corysimmons


You need to use reorder to override the default order, but also be sensitive as to whether ActiveAdmin sorts are being applied

scope :example do |models|
  if params[:order].blank? or params[:order] == "id_desc" #default ordering
    models.example.reorder('your order SQL here')
  else
    models.example
  end
end
like image 1
millie Avatar answered Nov 18 '22 21:11

millie