Skip to content

avoid N+1 queries for attached images #3282

@loicginoux

Description

@loicginoux

I customized a list view displaying multiple informations and realised there are many N+1 requests when showing the list views.
I managed to make them disappear for associations with an attribute eager_load (which is by the way not really documented, I had to dig in the code and several other issues mentionning it).

So let's say with have posts which have many comments we can do the following for displaying the posts list:

list do
  fields :comments do
    formatted_value do
      bindings[:view].render partial: 'rails_admin/posts/comments_preview', locals: { ride: bindings[:object] }
    end
    eager_load true
  end
end

The problem now I am facing is that if a post has photos and I want to display them in the list view, there is no way, currently to not do N+1 queries for them.

What would be good is something a bit similar as for associations:

list do
  fields :photos do
    eager_load true
  end
end

then when loading the posts collection it would basically do something like this, supposing we use active storage:

Posts.with_attached_photos.all

At the moment the only way I managed to fix the N+1 query is overwritting the get_collection method for this model in particular adding the following in config/initializers/rails_admin.rb:

require 'rails_admin/main_controller'
module RailsAdmin
  class MainController < RailsAdmin::ApplicationController
    def get_collection(model_config, scope, pagination)
      associations = model_config.list.fields.select { |f| f.try(:eager_load?) }.collect { |f| f.association.name }
      options = {}
      options = options.merge(page: (params[Kaminari.config.param_name] || 1).to_i, per: (params[:per] || model_config.list.items_per_page)) if pagination
      options = options.merge(include: associations) unless associations.blank?
      options = options.merge(get_sort_hash(model_config))
      options = options.merge(query: params[:query]) if params[:query].present?
      options = options.merge(filters: params[:f]) if params[:f].present?
      options = options.merge(bulk_ids: params[:bulk_ids]) if params[:bulk_ids]
      if model_config.abstract_model.to_s == "Ride"
        model_config.abstract_model.all(options, scope.with_attached_photos)
      else
        model_config.abstract_model.all(options, scope)
      end
    end
  end
end

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions