Reputation: 18978
I'm upgrading to Rails 6.1, and have the following associations in my model
class Product < ApplicationRecord
has_many :classifications, dependent: :destroy
has_many :order_lines, dependent: :destroy
end
For this following snippet:
p = Product.new
p.classifications.build name: 'my name'
p.order_lines.build line_number: '123'
p.save
If I run it in my existing code env (Rails 6.0, Ruby 2.7.7), it works as expected. However, if I run it against Rails 6.1, the classifications
object is stored in the DB, whereas the order_line
is dropped. There is no SQL statement that attempts to write it to the DB, and checking p.order_lines.inspect
after the save, returns an empty CollectionProxy
.
Changing the order of how we build the objects had no impact. Changing the order of how the association is defined in the model DID change the behaviour (order_line
was persisted and classifications
wasn't)
Interestingly enough, if I switch to
p = Product.create # instead of .new
# rest of snippet
It works as expected against Rails 6.1, and both order_line
and classification
were stored. This is very confusing behaviour, and I have no idea what is introducing it. Any thoughts?
EDIT: the behaviour is consistent with any two has_many
associations I define on any model. The association defined first in the model gets saved, while the other one gets dropped. I tried swapping them around and reloading my console, and the one that gets saved vs dropped was swapped.
Upvotes: 4
Views: 197
Reputation: 424
I am the author former co-worker that inherited this issue to solve and I am giving an update to this problem.
So what I found out after more investigation is that, the problem comes from the fact that one of the has many relationship doesn't have an inverse relationship to the parent.
From the sample above, classifications
has an inverse relationship to Product
belongs_to :product, inverse_of: :classifications
while OrderLine
doesn't define this inverse relationship.
What breaks it is that rails 6.1 introduces below config as default.
config.active_record.has_many_inversing = true
Due to this being a legacy application with a lot of moving parts, the solution for us is to set this config back to false.
Upvotes: 0