如何使用带有rails的祖先宝石急切地加载根



我有一个属于Category的Entry模型。Category模型使用祖先,这样我就可以嵌套Categories。

我想按根类别对所选条目进行分组。我遇到的问题是,为了做到这一点,rails对每个条目执行一个查询,以获取根类别。因此,如果我有20条记录,它将执行20个查询,按根类别进行分组。

我已经通过急切地加载类别(如下所示)减少了查询的数量,但我也不知道如何急切地加载该类别的根。

这是我正在使用的代码:

控制器

@entries = current_user.entries.includes(:category)
@entries_by_category = @entries.group_by { |entry| entry.category.root }

entry.rb

class Entry < ActiveRecord::Base
belongs_to :category
end

类别.rb

class Category < ActiveRecord::Base
has_ancestry
has_many :entries
end

我尝试在Category模型上设置一个默认作用域,如下所示:default_scope { includes(:ancestry) }。但这并没有改变已执行查询的数量。我不知道如何在原始查询中使用includes()来同时包含类别和类别的根。

作为一点额外信息,类别只能嵌套2层(只有类别和子类别)。所以根在技术上意味着父,它不必遍历多个级别。

有什么想法吗?

我遇到了一个非常类似的问题,只是我想急切地加载类别的path,而不仅仅是root。不幸的是,急切加载只适用于关联。Ancestry导航器(parentrootpathancestors等)都是方法,而不是关联,因此您不能急于加载它们。

我的解决方案是急切地加载条目的类别关联,然后在Category上使用模型级缓存(请参阅Railscast#115)来缓存path(在您的情况下,您可以修改为root):

类别.rb

def cached_path
Rails.cache.fetch([self, "path"]) { path.to_a }
end

entries_controller.rb

def index
@entries = Entry.includes(:category)
end

views/entries/index.html.haml

- @entries.each do |entry|
= entry.category.cached_path.map{ |c| c.name }.join(" / ")

希望能有所帮助。

最新更新