Having an issue with updating nested attributes for a polymorphic association, specifically, when attempting to update nested records through a join model.
The nested records can be one of a dozen different models and are known simply to the join model as "component". My error messages correctly indicate the attribute that failed validation but the message identifies the record as "component": "Validation failed: Page components component alt text can't be blank"
Here are my relationship configurations:
class Page < ApplicationRecord
has_many :page_components, -> { order(position: :asc) }, dependent: :destroy, autosave: true
accepts_nested_attributes_for :page_components, allow_destroy: true
...
end
class PageComponent < ApplicationRecord
belongs_to :page, optional: trueacts_as_list scope: :page
belongs_to :component, polymorphic: true, autosave: true
accepts_nested_attributes_for :component
...
end
class PageImageComponent < ApplicationRecord
has_one :page_component, as: :component, autosave: true
...
end
In the error message, Page is correctly identified as the parent but what I'm hoping for is to identify which type of association failed validation. So if the component is a PageImageComponent the message would ideally read "Validation failed: Page components page_image_component alt text can't be blank". Or something like that
Is this just not possible? I would think if it can identify the attribute it should have access to the class name as well..
update:
where this is happening is a simple record update:
@page.update!(permitted_params[:page])
where permitted_params would be:
#<ActionController::Parameters {"title"=>"test 1", "page_group_id"=>"4", "description"=>"test page description", "is_visible"=>"1", "is_public"=>"1", "template_type"=>"default", "has_chrome_warning_banner"=>"0", "image_alt_text"=>"", "page_components_attributes"=>#<ActionController::Parameters {"0"=>#<ActionController::Parameters {"id"=>"14", "component_type"=>"PageImageComponent", "position"=>"1", "_destroy"=>"0", "component_attributes"=>#<ActionController::Parameters {"url"=>"/about", "alignment"=>"center", "alt_text"=>""} permitted: true>} permitted: true>} permitted: true>} permitted: true>
rescue block:
rescue => e
respond_to do |format|
if params[:action] === 'update'
format.html { redirect_to edit_admin_page_path(@page), flash: { error: "#{e.message}"} }
else
format.html { redirect_to new_admin_page_path, flash: { error: "#{e.message}"} }
end
end
Human attribute names are defined on class level. So by default it knows nothing about params you pass (while your association is polymorphic and types may vary).
You can add
validates_associatedmethod inPageComponentclass with amessageoption:I would also consider custom validator for
Pagemodel where I could get full error messages I want including positions of failed components which might by useful as well.