2011-12-14 66 views
15

我有一个ActiveAdmin索引页预先加载相关模型

ActiveAdmin.register Bill 

,我试图以显示指向关联模型

index do 
    column "User" do |bill| 
    link_to bill.user.name, admin_user_path(bill.user) 
    end 
end 

但我碰上了N + 1查询问题 - 有一个查询来获取每个用户。

有没有方法急于加载账单的用户?

回答

26

有在不同的帖子上回答,但它很好地描述了你需要在这里做什么。

controller do 
    def scoped_collection 
     Bill.includes(:user) 
    end 
    end 

在这里,您需要确保遵循范围。因此,如果您的控制器是scope_to'ed,那么您将需要用scope_to'ed参数替换上面的模型名称。

1

重要编辑注:接下来居然是假,看到一个解释的意见。但是我留下这个答案,因为看起来我不是唯一一个被导游弄糊涂的人,所以也许别人会觉得它很有用。

我认为

class Bill < ActiveRecord::Base 
    belongs_to :user 
end 

所以according to RoR guides已经是跃跃欲试加载:

有没有必要使用:包括直接的关联 - 也就是 如果你有订单belongs_to的:客户,那么当需要时,客户自动加载 。

你应该检查你的SQL日志,如果它是真实的(不知道我自己,我只是验证一些有关:include回答你当我看到这个...让我知道)

+0

官方文件中指出,我认为这是很值得怀疑,但谁知道? – 2011-12-14 23:20:38

+2

_客户在需要时自动加载 - 这意味着,如果您有1000个订单并遍历它们,则调用`order1.customer`,并且'customer1`因为需要而被加载。然后你访问`order2.customer`,但是,你没有说你会需要它,所以对数据库的另一个查询就完成了。但是它仍然不知道在下一次迭代中你需要`customer3`,所以你会得到1000个查询,而不是1. – RocketR 2012-03-16 16:29:45

+0

谢谢你的清除。我发现这种方式让事情变得混乱,但英语不是我的母语。 – 2012-03-19 09:48:18

10

执行此操作的方法是覆盖scoped_collection方法(如Jeff Ancel的答案中所述),但请拨super以保留现有范围。这样您就可以保留ActiveAdmin应用的现有范围和任何分页/过滤,而不是从头开始。

ActiveAdmin.register Bill do 
    controller do 
    def scoped_collection 
     super.includes :user 
    end 
    end 

    index do 
    column "User" do |bill| 
    link_to bill.user.name, admin_user_path(bill.user) 
    end 
    end 
end 

截至http://activeadmin.info/docs/2-resource-customization.html