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)

Most upvoted comments

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:

  1. Would it work if you redefined Admin::CoursesController#scoped_resource to do the eager loading?
  2. Not sure how to proceed on this one. This needs more research. Would you be able to replicate this one by altering the example app, and show it in a branch? This may help shed light into what’s going on.
  3. This is actually the only place where the option :scope applies, which comes to show that it’s a misnomer and probably should go away. I wonder if we could add a controller method edit_resource, similar to the existing new_resource, and do some eager loading there?
  4. Try this: define a new association 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.