500 error - #valid_action? called with the wrong arguments when rendering Field::HasMany
Created by: maxkwallace
This issue applies to the current, unreleased master
branch, not to 0.4.0. And first off-- thanks for the awesome gem! Administrate has been a huge boon to my org, and I really appreciate all the hard work.
If I have two Resources with routes like:
resources :users
resources :orders, except: [:edit, :update]
And UserDashboard
has orders: Field::HasMany,
under SHOW_PAGE_ATTRIBUTES
, when someone navigates to admin/users/:id
(the show action) Administrate will render, among other things, administrate/app/views/fields/has_many/_show.html.erb
, which looks like:
<% if field.resources.any? %>
<%= render(
"collection",
collection_presenter: field.associated_collection,
resources: field.resources(params[field.name])
) %>
...
Inside the collection partial, we have:
<% if valid_action? :edit %>
<td><%= link_to(
t("administrate.actions.edit"),
[:edit, namespace, resource],
class: "action-edit",
) %></td>
<% end %>
When we call valid_action?
here, it looks up resource_name
on the rendering Controller's resource_resolver
, which is for the User Resource, not the Order Resource.
Since the Order Resource doesn't have an edit route declared in routes.rb
, a 500 error gets thrown because the path link_to
goes to look up doesn't exist.
The same issue exists for the other routes, not just :edit
and :update
.
Stop-gap solution (for anyone else running into this issue):
Put the following in your routes.rb
, after your Administrate route declarations:
get 'orders/:id/edit', to: 'orders#show', as: :edit_admin_order
This deals with the 500s, but the "Edit" links still get generated in collection partials.
Actual solution:
I spent about an hour unsuccessfully trying to come up with a fix for this in a PR. It's easy to write a heuristic to pass resource_name
into valid_action?
for the Resource being rendered, but I'm very unsure what would be required to make that correct in all cases, or if there's a larger refactor that would be more appropriate. Administrate::ResourceResolver
defines a clear mapping from the URL path to the Resource, but I'm not sure about going the other way without breaking things in some cases.