我使用activeadmin来显示分支模型记录,分支模型有很多分支电话,我想在activeadmin分支模型屏幕上显示为此分支创建的第一个分支电话作为额外的自定义属性,所以我这样写
show do
attributes_table do
row :id
row :manager_name
row :manager_email
row :phone_number do |branch|
branch&.branch_phones&.order(created_at: :asc)&.first&.phone_number
end
end
end
index do
column :id
column :manager_name
column :manager_email
column :phone_number do |branch|
branch&.branch_phones&.order(created_at: :asc)&.first&.phone_number
end
actions
end
该代码的问题在于,它会导致我执行 n+1 次查询,每次代码获取分支时,它都会在其中创建一个额外的查询以获取分支的分支电话,这会在调用分支时产生类似的结果activeadmin 上的模型屏幕
Processing by Admin::BranchesController#index as HTML
Parameters: {"subdomain"=>""}
AdminUser Load (0.8ms) SELECT "admin_users".* FROM "admin_users" WHERE "admin_users"."id" = $1 ORDER BY "admin_users"."id" ASC LIMIT $2 [["id", 1], ["LIMIT", 1]]
Rendering /usr/local/bundle/gems/activeadmin-2.7.0views/active_admin/resource/index.html.arb
(0.6ms) SELECT COUNT(*) FROM (SELECT 1 AS one FROM "branches" LIMIT $1 OFFSET $2) subquery_for_count [["LIMIT", 30], ["OFFSET", 0]]
CACHE (0.1ms) SELECT COUNT(*) FROM (SELECT 1 AS one FROM "branches" LIMIT $1 OFFSET $2) subquery_for_count [["LIMIT", 30], ["OFFSET", 0]]
(0.4ms) SELECT COUNT(*) FROM "branches"
CACHE (0.0ms) SELECT COUNT(*) FROM (SELECT 1 AS one FROM "branches" LIMIT $1 OFFSET $2) subquery_for_count [["LIMIT", 30], ["OFFSET", 0]]
Branch Load (0.5ms) SELECT "branches".* FROM "branches" ORDER BY "branches"."id" desc LIMIT $1 OFFSET $2 [["LIMIT", 30], ["OFFSET", 0]]
Store Load (0.6ms) SELECT "stores".* FROM "stores" WHERE "stores"."id" IN ($1, $2, $3) [["id", 21], ["id", 1], ["id", 2]]
BranchPhone Load (0.4ms) SELECT "branch_phones".* FROM "branch_phones" WHERE "branch_phones"."branch_id" IN ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11) [["branch_id", 25], ["branch_id", 24], ["branch_id", 22], ["branch_id", 20], ["branch_id", 19], ["branch_id", 14], ["branch_id", 11], ["branch_id", 4], ["branch_id", 3], ["branch_id", 2], ["branch_id", 1]]
BranchPhone Load (0.7ms) SELECT "branch_phones".* FROM "branch_phones" WHERE "branch_phones"."branch_id" = $1 ORDER BY "branch_phones"."created_at" ASC LIMIT $2 [["branch_id", 25], ["LIMIT", 1]]
BranchPhone Load (0.5ms) SELECT "branch_phones".* FROM "branch_phones" WHERE "branch_phones"."branch_id" = $1 ORDER BY "branch_phones"."created_at" ASC LIMIT $2 [["branch_id", 24], ["LIMIT", 1]]
BranchPhone Load (0.3ms) SELECT "branch_phones".* FROM "branch_phones" WHERE "branch_phones"."branch_id" = $1 ORDER BY "branch_phones"."created_at" ASC LIMIT $2 [["branch_id", 22], ["LIMIT", 1]]
BranchPhone Load (0.6ms) SELECT "branch_phones".* FROM "branch_phones" WHERE "branch_phones"."branch_id" = $1 ORDER BY "branch_phones"."created_at" ASC LIMIT $2 [["branch_id", 20], ["LIMIT", 1]]
BranchPhone Load (0.3ms) SELECT "branch_phones".* FROM "branch_phones" WHERE "branch_phones"."branch_id" = $1 ORDER BY "branch_phones"."created_at" ASC LIMIT $2 [["branch_id", 19], ["LIMIT", 1]]
BranchPhone Load (0.3ms) SELECT "branch_phones".* FROM "branch_phones" WHERE "branch_phones"."branch_id" = $1 ORDER BY "branch_phones"."created_at" ASC LIMIT $2 [["branch_id", 14], ["LIMIT", 1]]
BranchPhone Load (0.2ms) SELECT "branch_phones".* FROM "branch_phones" WHERE "branch_phones"."branch_id" = $1 ORDER BY "branch_phones"."created_at" ASC LIMIT $2 [["branch_id", 11], ["LIMIT", 1]]
BranchPhone Load (0.2ms) SELECT "branch_phones".* FROM "branch_phones" WHERE "branch_phones"."branch_id" = $1 ORDER BY "branch_phones"."created_at" ASC LIMIT $2 [["branch_id", 4], ["LIMIT", 1]]
BranchPhone Load (0.3ms) SELECT "branch_phones".* FROM "branch_phones" WHERE "branch_phones"."branch_id" = $1 ORDER BY "branch_phones"."created_at" ASC LIMIT $2 [["branch_id", 3], ["LIMIT", 1]]
BranchPhone Load (0.2ms) SELECT "branch_phones".* FROM "branch_phones" WHERE "branch_phones"."branch_id" = $1 ORDER BY "branch_phones"."created_at" ASC LIMIT $2 [["branch_id", 2], ["LIMIT", 1]]
BranchPhone Load (0.2ms) SELECT "branch_phones".* FROM "branch_phones" WHERE "branch_phones"."branch_id" = $1 ORDER BY "branch_phones"."created_at" ASC LIMIT $2 [["branch_id", 1], ["LIMIT", 1]]
Rendered /usr/local/bundle/gems/activeadmin-2.7.0views/active_admin/resource/index.html.arb (219.4ms)
Completed 200 OK in 258ms (Views: 208.7ms | ActiveRecord: 23.2ms)
那么,有什么解决方案可以消除分行电话的n+1查询吗? 知道我试图使用这样的控制器操作来消除它
但分行电话N+1查询仍未解决
您收到 (N+1) 次查询,因为您正在订购
branch_phones
。默认情况下,Rails 按同意顺序返回记录。您不必再次订购。
我相信你有如下的联想:
# app/models/branch.rb
class Branch < ApplicationRecord
has_many :branch_phones
end
# app/models/branch_phone.rb
class BranchPhone < ApplicationRecord
belongs_to :branch
end
请将此行添加到您的
app/admin/brach.rb
文件中。
# app/admin/brach.rb
controller do
def scoped_collection
super.includes(:branch_phones)
end
end
index do
column :id
column :manager_name
column :manager_email
column :phone_number do |branch|
branch.branch_phones.first&.phone_number
end
actions
end
现在 includes 方法在 ActiveAdmin 中可用。您需要做的就是将其添加到所需的管理文件中。
ActiveAdmin.register Branch do
includes :branch_phones
index do
column :id
column :manager_name
column :manager_email
column :phone_number do |branch|
branch&.branch_phones&.order(created_at: :asc)&.first&.phone_number
end
actions
end
end