Rails nested form with has_many :through, how to edit attributes of join model?
Figured out the answer. The trick was:
@topic.linkers.build.build_article
That builds the linkers, then builds the article for each linker. So, in the models:
topic.rb needs accepts_nested_attributes_for :linkers
linker.rb needs accepts_nested_attributes_for :article
Then in the form:
<%= form_for(@topic) do |topic_form| %>
...fields...
<%= topic_form.fields_for :linkers do |linker_form| %>
...linker fields...
<%= linker_form.fields_for :article do |article_form| %>
...article fields...
When the form generated by Rails is submitted to the Rails controller#action
, the params
will have a structure similar to this (some made up attributes added):
params = {
"topic" => {
"name" => "Ruby on Rails' Nested Attributes",
"linkers_attributes" => {
"0" => {
"is_active" => false,
"article_attributes" => {
"title" => "Deeply Nested Attributes",
"description" => "How Ruby on Rails implements nested attributes."
}
}
}
}
}
Notice how linkers_attributes
is actually a zero-indexed Hash
with String
keys, and not an Array
? Well, this is because the form field keys that are sent to the server look like this:
topic[name]
topic[linkers_attributes][0][is_active]
topic[linkers_attributes][0][article_attributes][title]
Creating the record is now as simple as:
TopicController < ApplicationController
def create
@topic = Topic.create!(params[:topic])
end
end