Skip to content

display_on? on the default :new action item raises NameError (v4.0.0.beta22) #9072

Description

@joker-777

Summary

Calling display_on? on the default :new action item (the one AA registers
automatically for every resource, added in ActiveAdmin::Resource::ActionItems #add_default_new_action_item) raises a NameError because its if: lambda
references active_admin_config, which is not resolvable in the context the
lambda is evaluated from when triggered via display_on?.

Reproduction

ActiveAdmin.register SomeModel do
  config.action_items.delete_if do |item|
    item.name == :new && item.display_on?(:index)
  end
end

Booting a page for SomeModel (or anything that walks config.action_items
and calls display_on?) raises:

NameError: undefined local variable or method 'active_admin_config' for an instance of ActiveAdmin::ActionItem

Root cause (as far as we've traced it)

lib/active_admin/resource/action_items.rb registers the default :new item
with:

add_action_item :new, only: :index, if: -> { new_action_authorized?(active_admin_config.resource_class) } do
  ...
end

In 3.x, the equivalent visibility check ran inline, evaluated lazily at
render time in a view context where active_admin_config resolves. In
4.0.0.beta22, the check moved into a separate if: lambda that gets
evaluated by ActiveAdmin::OptionalDisplay#display_on? outside that view
context, where active_admin_config is no longer in scope.

Any resource-level code that calls display_on? on the default :new item
(a previously-working, documented pattern for conditionally hiding it) will
hit this.

Environment

  • activeadmin 4.0.0.beta22 (gem, from github.com/activeadmin/activeadmin
    at tag v4.0.0.beta22)
  • Ruby 3.4.9, Rails 7.2.3
  • Reproduced independently of activeadmin_addons or any other gem — bare AA
    v4 core against a single custom resource registration.

What we did as a workaround

We dropped the display_on? probe and delete by name only, since the
default :new item is registered only: :index — for the default item,
name == :new && display_on?(:index) and name == :new are equivalent:

config.action_items.delete_if { |item| item.name == :new }

This sidesteps the lambda entirely but obviously doesn't fix the underlying
display_on?/if:-lambda scoping issue for anyone who needs to call
display_on? for a different reason.

Happy to provide more context or a minimal repro repo if useful.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions