Active Admin scopes for each instance of a related model

前端 未结 6 1743
灰色年华
灰色年华 2020-12-30 11:26

I have an issue with a dynamic active admin scope. I am attempting to create a scope for each \"manager\" of a \"project\" in my app. However, the scopes don\'t seem to up

相关标签:
6条回答
  • 2020-12-30 12:01

    Rails only loads classes once in production mode. This means your scopes are only being called once and then they are cached. This is why new scopes don't show up until after a restart. The same thing would be true if you edited the manager's first name in your case.

    I think the solution may be to use a lambda or Proc, but in the few minutes I played with it, I wasn't successful. It may not be possible the way activeadmin is written too.

    0 讨论(0)
  • 2020-12-30 12:11

    Here is an actual solution to this problem ... Altho using filters instead is more desirable stability and maintenance wise, this looks nicer in ActiveAdmin and is more user friendly since scopes become nice looking tabs.

    It is a bit of a hack, but it is a viable solution where appropriate:

    The trick is to update the scopes in a before_filter on the controllers index action.

    This could get bad if you have many scopes created on a resource (altho you can easily set some limits)

    ActiveAdmin.register Project do
      menu :priority => 1
      index do
        column :name
        column :company_name
        column :status
        column :projection do |project|
          number_to_currency project.projection
        end
        column :updated_at
        default_actions
      end
    
      scope :all
      scope :working, :default => true do |projects|
        projects.where(:status => 'working')
      end
    
      controller do
        before_filter :update_scopes, :only => :index
    
        def update_scopes
          resource = active_admin_config
    
          Manager.all.each do |m|
            next if resource.scopes.any? { |scope| scope.name == m.first_name }
            resource.scopes << (ActiveAdmin::Scope.new m.first_name do |projects|
              projects.where(:manager_id => m.id)
            end)
          end
    
          # try something like this for deletions (untested)
          resource.scopes.delete_if do |scope|
            !(Manager.all.any? { |m| scope.name == m.first_name } || ['all', 'working'].include?(scope.name)) # don't delete other scopes you have defined
          end
    
        end
      end
    end
    
    0 讨论(0)
  • 2020-12-30 12:14

    Here is my optimized solution based on Brant Sterling Wedel's answer.

    This solution contains the following additional enhancements:

    • Removes any unused scopes
    • Allows to set default scope
    ### Default scope must be set in advance
    scope "Jeff", default: true do |x| 
      x.joins(:manager).where(manager: {name: "Jeff"})
    end
    
    controller do
    
      before_action :reload_scopes, only: :index
    
      def reload_scopes
        resource_config = active_admin_config
    
        resource_config.instance_variable_set(:@scopes, [
          resource_config.scopes.first ### Default scope
        ])
    
        Manager.all.each do |m|
          next if resource_config.scopes.first.name ==  m.name
    
          resource_config.scopes << ActiveAdmin::Scope.new(m.name){|scope| scope.where(manager_id: m.id) }
        end
      end
    
    end
    
    0 讨论(0)
  • 2020-12-30 12:20

    I found this to work for me:

    ActiveAdmin file

    scope :working, :default => true do |projects|
      Project.working
    end
    

    Model

    scope :working, -> { where(:status => 'working') }
    

    A bit late in the reply but hopefully it helps someone out.

    0 讨论(0)
  • 2020-12-30 12:20

    True dynamic scopes inside the AA register blocks won't work. With that I mean that changes in the Manager table won't be reflected in the at 'initialization'-time created dynamic scopes. Also see: https://github.com/gregbell/active_admin/wiki/Creating-dynamic-scopes. What you could try is using filters instead of scopes. Then you can write something like:

    filter :managers, :as => :select, :collection => proc { Manager.order('name ASC').map(&:first_name) }  
    

    and changes in the managers properties will show (after page refresh) without restarting the server. Also check https://github.com/gregbell/active_admin/issues/1261#issuecomment-5296549

    Also note that active record scopes are !different! from active admin scopes. you might want to check

    http://apidock.com/rails/ActiveRecord/NamedScope/ClassMethods/scope

    0 讨论(0)
  • 2020-12-30 12:24

    The solution mentionned by weston Ganger work like a charm. If you don't have a default scope, you can use the all scope as the default one.

      scope :all, default: true
    
    0 讨论(0)
提交回复
热议问题