Sometimes you may want to limit ActiveAdmin’s export functionality. In the application that prompted this post, CSV was useful to administrators while JSON and XML were unnecessary surface area.
At the time, I added the following override in a Rails initializer:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
module ActiveAdmin
module Views
class PaginatedCollection
def build_pagination_with_formats(options)
div id: "index_footer" do
build_pagination
div(
page_entries_info(options).html_safe,
class: "pagination_information"
)
build_download_format_links([:csv]) unless @download_links == false
end
end
end
end
end
After adding the initializer, the Rails process needed to be restarted. The allowed formats could then be changed by adjusting:
1
build_download_format_links([:csv])
What the patch actually changed
This was not implementing export logic. It was changing the index footer so that ActiveAdmin only presented links for an explicit list of formats.
That distinction matters. Hiding a UI link is a usability decision, not an authorisation boundary. If exporting data is sensitive, the corresponding controller action and format must also be protected by the application’s authorisation policy. A user who can construct the URL should not gain access merely because the button is absent.
Why monkey patches age badly
The override reopened an internal ActiveAdmin class and replaced part of its rendering behaviour. It was pragmatic, but it coupled the application to private implementation details:
- an upstream rename could break application start-up;
- a changed method signature could fail only when the index rendered;
- upstream fixes to the original method would not automatically reach the replacement;
- the reason for the patch could become invisible to future maintainers.
When a patch is unavoidable, I now treat it like temporary infrastructure: document the upstream version, link to the missing capability, add a focused test and define the condition that allows its removal.
The supported approach today
Current ActiveAdmin releases document download_links directly on the index page. Restricting one resource to CSV can be expressed without replacing a view class:
1
2
3
ActiveAdmin.register Post do
index download_links: [:csv]
end
The links can also be disabled, made conditional, or configured for the whole application. The examples are maintained in ActiveAdmin’s current index-page guide.
A global configuration might look like:
1
2
3
ActiveAdmin.setup do |config|
config.download_links = [:csv]
end
That is a much healthier extension point: the intent is obvious, the framework owns the implementation and upgrades can validate the option through its own test suite.
The lesson beyond ActiveAdmin
The useful part of this old snippet is not the monkey patch itself. It is the sequence of decisions behind it:
- Remove formats the user does not need.
- Enforce data access independently from presentation.
- Prefer a supported configuration surface.
- Isolate and test a patch when no supported surface exists.
- Delete the patch as soon as the framework provides one.
A short workaround can be entirely reasonable. The long-term risk begins when temporary code loses its history and quietly becomes architecture.