3

I have a rails API that injects primary key IDs from the client, as opposed to autogenerating through Rails. Specifically:

class ParentModel < ApplicationRecord
  accepts_nested_attributes_for: child_models
  has_many :child_models
end

class ChildModel < ApplicationRecord
  belongs_to :parent_model
end

Nested data is created via:

@parent_object = ParentModel.find_or_initialize_by(id: parent_model_params[:id])
@parent_object.assign_attributes(parent_model_params)
@parent_object.save

If the ID for a child_object already exists in the database, the operation updates the child object as expected. However, if the child object is new, I get:

Couldnt find ChildModel with ID=b35e8f02... for ParentModel with ID=0c9b60f3...

In short: I'm trying to ensure rails creates child records (with the given IDs) when they don't exist, and continues to update existing child records if they do. Any thoughts on how to do that through nested attributes?

2
  • 1
    I'm not sure this is actually possible as the presence of the id attribute will trigger nested attributes to find and update an existing record, that's kind of a key feature and not something you can turn off. You might have to create your own implementation of nested attributes. github.com/rails/rails/blob/… Commented Feb 6, 2023 at 15:57
  • I created an issue that was closed, if you want to give it more strength : github.com/rails/rails/issues/49385 Commented Nov 25, 2024 at 10:47

1 Answer 1

1

For those wondering, I couldn't find an elegant solution. Instead, I manually created a new child object for each new child before calling .assign_attributes. Eg:

parent_model_params[:child_model_attributes].each do |child_params|
  next if @parent_object.child_ids.include?(child_params[:id])

  @parent_object.child_objects << ChildModel.new(child_params)
end

@parent_object.assign_attributes(parent_model_params) # This no longer raises a RecordNotFound error

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.