administrate
administrate copied to clipboard
Have a NESTED_ATTRIBUTES configuration to control what is being shown for HasOne relations
- What would you like to be able to do? Can you provide some examples?
On the show page of model A, I'd like to show details of model B (A has_one B). Currently administrate fetches the configuration from FORM_ATTRIBUTES, I'd like to have more control by separating this definition into it's own configuration: NESTED_ATTRIBUTES (for instance)
- How could we go about implementing that?
Probably some reconfiguration of the Field::HasOne class
- Can you think of other approaches to the problem?
Create my own custom field to handle this, but it seems to be a valuable addition to the current solution. You could even overwrite NESTED_ATTRIBUTES = FORM_ATTRIBUTES in the Administrate::BaseDashboard for backwards compatibility.
The problem I see with the NESTED_ATTRIBUTES approach is that it's not very generic. If we wanted to show different nested attributes for the same model on different dashboards, it wouldn't be possible.
Perhaps a better approach would be to have the list of attributes as an option to the field. Something like this:
# Dashboard definition for "child" model
class ProductDashboard < Administrate::BaseDashboard
ATTRIBUTE_TYPES = {
created_at: Field::DateTime,
updated_at: Field::DateTime,
description: Field::Text,
image_url: Field::Url,
name: Field::String,
price: Field::Number.with_options(prefix: "$", decimals: 2),
product_meta_tag: Field::HasOne,
}
#...
end
# One "parent" dashboard
class LineItemDashboard < Administrate::BaseDashboard
ATTRIBUTE_TYPES = {
# ...
product: Field::BelongsTo.with_options(attributes: [:name, :price]),
# ...
}
# Different "parent" dashboard
class MarketingFeatureDashboard < Administrate::BaseDashboard
ATTRIBUTE_TYPES = {
# ...
product: Field::BelongsTo.with_options(attributes: [:name, :image_url, :description]),
# ...
}
Thinking about how this could be achieved, I had a look at the code. The dashboard pages are rendered from the views at app/views/administrate/application (see show.html.erb, etc). These in turn get their data from the Administrate::Page::Show, etc presenters, and these get the lists of attributes from the dashboards.
Again as a first look into the problem, it looks to me as though it should be possible to feed that new option attributes from the template and presenter into Administrate::Page::Show, so that it returns the desired field information, and the template renders that instead of the default.
There would be at least one open question, which is: what if we wanted the index and show pages show different attributes for the associated, "child" field? However I think this could be done in the future with specialised form_attributes and show_attributes options, leaving attributes still valid, as a default for both.
I would be willing to look into a PR for this. Would you be game? I'm happy to provide guidance.
While this is addressed, I proposed a workaround at StackOverflow: https://stackoverflow.com/questions/67129863/show-administrate-attribute-in-one-area-but-not-in-another