Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix eager loading a Rails app with performs in an associated object #14

Merged
merged 1 commit into from
Nov 9, 2023

Conversation

natematykiewicz
Copy link
Contributor

@natematykiewicz natematykiewicz commented Nov 8, 2023

ActiveJob::Performs was being included in an after_initialize hook, which was after the models were loaded, which means that an associated object that has a performs call in it had no performs method.

This triggered the method_missing to run and find the performs method on the ActiveRecord model, use that, and then attempt to call my associated object name on the return value.

Given this code:

class AudioTrack::ListeningPlanDaySyncer < ActiveRecord::AssociatedObject
  performs :sync
end

performs didn't exist, so it'd call AudioTrack.performs :sync, which returns :sync_later. Then the method_missing code would attempt to run :sync_later.listening_plan_day_syncer and error.

By moving this on_load hook out of after_initialize, I now have a performs method when eager loading.

I think the only reason it was working before is because the models were being lazy loaded, so I didn't attempt to call performs until long after boot.

Note: I'm unsure how to test this. The problem only occurs when eager loading.

ActiveJob::Performs was being included in an after_initialize hook,
which was after the models were loaded, which means that an associated
object that has a `performs` call in it had no `performs` method.

This triggered the method_missing to run and find the `performs` method
on the ActiveRecord model, use that, and then attempt to call my
associated object name on the return value.

Given this code:

class AudioTrack::ListeningPlanDaySyncer < ActiveRecord::AssociatedObject
  performs :sync
end

`performs` didn't exist, so it'd call `AudioTrack.performs :sync`, which
returns :sync_later. Then the method_missing code would attempt to
run `:sync_later.listening_plan_day_syncer` and error.

By moving this on_load hook out of `after_initialize`, I now have a `performs`
method when eager loading.

I think the only reason it was working before is because the models
were being lazy loaded, so I didn't attempt to call `performs` until
long after boot.
@kaspth kaspth merged commit 87f0583 into kaspth:main Nov 9, 2023
2 checks passed
@kaspth
Copy link
Owner

kaspth commented Nov 9, 2023

Bah, sorry about that. I figured it would be alright to keep this in an after_initialize.

Note: I'm unsure how to test this. The problem only occurs when eager loading.

Yeah, I'm not sure either.

@natematykiewicz natematykiewicz deleted the fix_eager_load branch November 10, 2023 18:45
@natematykiewicz
Copy link
Contributor Author

No worries at all! Can you ship a version bump?

@kaspth
Copy link
Owner

kaspth commented Nov 13, 2023

@natematykiewicz
Copy link
Contributor Author

Thanks Kasper!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants