3

An action creates records based on multiple layers of nested attributes, upon the submission of a form. However, the ID of the root record, which I call .save on, is not propagating downwards to the associations.

Here's a simplified example:

class A
  has_many :bs
  # Note that A has direct access to C, without going through B
  has_many :cs
  accepts_nested_attributes_for :b
end

class B
  # B has an :a_id field
  belongs_to :a
  has_many :cs
  accepts_nested_attributes_for :c
end

class C
  # note that C has a "circular relationship" to A, 
  # either directly through the :a_id field, or indirectly through B
  belongs_to :a
  belongs_to :b
end

Given the model definitions above, this is an example payload:

{
  a: {
    name: "Model A",
    bs_attributes: [{
      name: "Model B",
      cs_attributes: [{
        name: "Model C"
      }]
    }]
  }
}

And this payload will be fed into:

A.create(payload)

When that gets persisted on the database and A is assigned an ID, I expect this ID to be automatically set as a foreign key on both children (B) and grand-children (C) records. Is that something that can be accomplished using Rails built-in functions, with simple effort?

An example of solution I could think of would be adding a before_save callback on associations to manually set the :a_id field. However this feels like it could be accomplished in simpler ways.

Currently working on Rails 5 but any guidance is appreciated.

3
  • It's unclear what you expect to happen here. If you expect cs.a_id to be filled then that's never going to happen as Rails only implicitly sets one foreign key attribute when spawning records off a has_many association. It's also unclear why you think it's actually needed when you could use a indirect association. Commented May 6, 2023 at 5:33
  • That makes sense. My ask was: is there some rails mechanism, like the use of inverse_of, that would allow me to automatically set a_id on table C? It’s now clear that this is not a default behavior and it would probably have to be set through a custom method running in a callback, for instance. When it comes to the foreign keys, the example was abstracted from some real world designs I’ve worked with, that seems unusual but there are other reasons for that modeling. I didn’t provide much detail on that since it was a secondary aspect. I believe I got clarity on my questions anyway. Commented May 6, 2023 at 13:30
  • 1
    The answer to that is simply no. Commented May 16, 2023 at 3:47

1 Answer 1

1

Using inverse_of to link the associations should work for the nested attributes. Example, A to B:

class A
  has_many :bs, inverse_of: :a
  accepts_nested_attributes_for :b
end

class B
  belongs_to :a, inverse_of: :bs
end

Same thing for C to B.

A to C is a bit special. Setting c.a = b.a in before_validation callback on C is an option.

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.