ActiveAdmin中多态关联Tag模型表单名称映射问题求助
I get exactly what you're dealing with here—your current code passes plain string names (nicknames/activity names) to the taggable input, but ActiveAdmin needs the actual polymorphic identifiers (taggable_type and taggable_id) to save the association properly. That's why you're hitting the "must exist and can't be blank" error.
Here's a clean solution that uses the label_method/value_method pattern you wanted, letting you show friendly names while ensuring the association saves correctly:
Step 1: Update the Form Input
Modify your taggable input to combine both models in the collection, use a dynamic label to show the right name, and pass a structured value that captures both the model type and ID:
ActiveAdmin.register Tag do permit_params :name, :taggable # We'll handle type/id in the controller # ... form do |f| f.semantic_errors f.inputs do f.input :name, collection: Tag::TAG_NAMES # Remove the separate taggable_type input—we'll derive it from the selected option f.input :taggable, label: "Account / Activity", collection: Account.all + Activity.all, label_method: ->(obj) { # Show nickname for Accounts, name for Activities obj.is_a?(Account) ? obj.nickname : obj.name }, value_method: ->(obj) { # Pass a string combining class name and ID, e.g., "Account:123" "#{obj.class.name}:#{obj.id}" } end f.actions end
Step 2: Add Controller Logic to Parse Polymorphic Values
We need to take the combined string from the form, split it into taggable_type and taggable_id, and assign those fields before saving. Add this controller block to your ActiveAdmin registration:
controller do def create parse_taggable_params super end def update parse_taggable_params super end private def parse_taggable_params return unless params[:tag][:taggable].present? # Split the structured value into model type and ID taggable_type, taggable_id = params[:tag][:taggable].split(':') # Assign the required polymorphic fields params[:tag][:taggable_type] = taggable_type params[:tag][:taggable_id] = taggable_id # Remove the temporary taggable parameter—we don't need it anymore params[:tag].delete(:taggable) end end end
Why This Works
label_method: Dynamically displays the nickname for Accounts and name for Activities, making the dropdown user-friendly instead of showing raw instance strings.value_method: Passes a structured string that holds both the model class and ID, which we can parse into the exact fields your Tag model expects.- Controller Logic: Converts the structured input value into the
taggable_typeandtaggable_idfields, ensuring the association is saved correctly without validation errors.
Optional: Add Type Context to Labels
If you have Accounts and Activities with identical names, add the model type to the label to avoid confusion:
label_method: ->(obj) { "#{obj.class.name}: #{obj.is_a?(Account) ? obj.nickname : obj.name}" }
内容的提问来源于stack exchange,提问作者Antoine Quellier

