administrate: Can't avoid under/overfetching
What were you trying to do?
I added bullet to my project, which shows that I should add eager loading for my dashboard relationships to avoid N+1 queries when showing the index. For instance I have a Course
with program: Field::BelongsTo
, and this program
is visible on the course index.
Bullet throws:
Bullet::Notification::UnoptimizedQueryError: user: sdubois
GET /admin/courses
USE eager loading detected
Program => [:translations]
Add to your query: .includes([:translations])
The issue is gone if I remove program
from the Course’s COLLECTION_ATTRIBUTES
.
So following the documentation, I changed program:
to Field::BelongsTo.with_options(scope: -> { Program.eager_load(:translations) })
.
What did you end up with (logs, or, even better, example apps are great!)?
The option has no effect. In fact even if I change to Field::BelongsTo.with_options(scope: -> { raise "I got called!" })
, it does not raise. It seems that this scope
option is not applied.
What versions are you running?
- Rails 6.0.3.2
- administrate 0.14.0
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Comments: 16 (4 by maintainers)
I would like to voice my need for this fix. Specifically in my use case I have a lot of associated records (~19000 associated with just one object). Loading all of these just for a
count
is completely breaking all of my RAM and forcing reloads on Heroku. Obviously, this is an edge case, but it seems reasonable for the index page to be able to display this.Thanks for the excellent project, and I’d be happy to help build up a PR on this.
Thank you for that comprehensive information @sedubois. I agree that this part of the code is a bit of a mess at the moment, and it’s difficult to work with it. I’m looking into ways to refactor/redesign Administrate to overcome these difficulties.
Regarding each specific issue you have, a main problem is that you have an association,
translations
, that Administrate is not aware of (and that makes sense), so it doesn’t know how to deal with it. I can’t be 100% sure of the solutions, but these are the ideas that come to mind for each one:Admin::CoursesController#scoped_resource
to do the eager loading?:scope
applies, which comes to show that it’s a misnomer and probably should go away. I wonder if we could add a controller methodedit_resource
, similar to the existingnew_resource
, and do some eager loading there?has_many :admin_translations, class_name: 'Translation', ->{ eager_load(course_modules: :translations) }
, and use this for the field instead. Does this help at all? This is the path I’ve had in mind lately, for replacing field options with ActiveRecord’s own idiomatic tools.