I have a strange workflow whereby a child record is created first and then I want it associated with the parent through a nested form. Here is an example using rspec:
Here are the models:
class Parent < ApplicationRecord
has_many :children, class_name: 'Child', dependent: :destroy
accepts_nested_attributes_for :children, allow_destroy: true, reject_if: :all_blank
end
class Child < ApplicationRecord
belongs_to :parent, foreign_key: 'child_id', optional: true
end
My controller is standard:
def create
@prent = Parent.new(parent_params)
respond_to do |format|
if @parent.save
format.html { redirect_to @parent }
else
p @recipe.errors.full_messages
end
end
end
def parent_params
params.require(:parent).permit(
:name,
children_attributes: [
:id, :_destroy
]
)
end
Since the child already exists, I am only trying to associate it with the parent, not create an entirely new record. Here is my test that fails with an error:
child = Child.create
expect {
post "/parent", params: {
parent: {
name: "test",
children_attributes: [{
id: child.id
}]
}
}.to change(Parent.all, :size).by(+1)
.and change(Child.all, :size).by(0)
end
And the error I'm receiving is
ActiveRecord::RecordNotFound:
Couldn't find Child with ID=1 for Parent with ID=
Clearly it's because Child exists before Parent but I still feel this should be possible. Is there a way to get this to work such that the existing child is associated with the parent when the parent is saved?
If you only need to associate existing records when creating another, use
child_ids=method.https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many
childrenis not a join table here, but if you have through associations set up,*_idsmethod will also just work. Something like this: https://stackoverflow.com/a/75972917/207090