Association cache regression in Rails 6

Hello,

I’ve found a regression in Rails 6 while upgrading my Rails 5.2 app that I’m sure is not correct behavior but I’d like a core member to confirm or not before I create a PR for it. The root of the problem lies in the association cache in the internals of ActiveRecord. The example below is the root of a more complex issue in my app, but the following is as basic as I can get to show the issue.

class Customer
has_many :appointments
end

class Appointment
belongs_to :customer
end

Example that works in Rails 5.2

a = Appointment.new customer_id: @customer.id
a.association(:customer).reader # returns @customer

Example that doesn’t work in Rails 6.0

a = Appointment.new customer_id: @customer.id
a.association(:customer).reader # returns nil

Example that works in both Rails 5.2 and 6.0 (note the association is set without the id)

a = Appointment.new customer: @customer
a.association(:customer).reader # returns @customer

So is the example that doesn’t work in Rails 6.0 a bug? The example I provided isn’t something you’ll see in a Rails app, but Rails internals uses the association cache and if this is a bug, then fixing this would fix other potential issues. Again, I found this issue due to a regression in my code with autosaved associations that I was setting via a foreign key parameter (ie. customer_id).

Andrew

Hi Andrew,

Afraid I’m not a Rails member, but I have been working on a couple caching-related bugs in Rails as of late. The behavior you’re describing looks buggy, but I’m not quite able to replicate the issue from the example code you provided, so I’m having trouble understanding exactly where the discrepancy between Rails 5.2 and 6 is coming from. Would you be able to provide a failing executable test case, or explain in more detail the circumstances which trigger the behavior you’re experiencing?

If useful, here’s an executable test case I wrote as a starting point: https://gist.github.com/alipman88/d499739a466f3e6b6746eeccfa567f9a

(It may be practical to open an issue via GitHub and continue conversation there, moving forward.)

Ok great, I’ll take a look at your test case and see if I can provide a failing test. Thanks for the reply.

Hi Aaron,

I’ve taken your example and provided a failing test case with a more elaborate example. I’ve opened an issue at https://github.com/rails/rails/issues/37869 with a reference to an updated test case.

I wasn’t able to get the example working in Rails 5.2 (the test was failing in Rails 5.2 as well), but the issue has only presented itself in Rails 6.0 in my apps use case. The updated code in the test case is more in line with what’s occurring in my application. My app uses accepts_nested_attributes_for which sets autosave automatically, so in the test case, I just set autosave on the association in the test. Also I use a custom save context which forces re-validation of the child association without the child association needing to be marked as dirty.

I also provided a “fix” that allows both test cases to pass (one fails and one passes right now).