如何使用带有轨道的祖先宝石来加载根源?

时间:2014-02-22 01:34:19

标签: ruby-on-rails activerecord group-by eager-loading ancestry

我有一个属于类别的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

category.rb

class Category < ActiveRecord::Base
  has_ancestry

  has_many :entries
end

我尝试在类别模型上设置默认范围,如下所示:default_scope { includes(:ancestry) }。但这并没有改变执行查询的数量。我无法弄清楚如何在原始查询中使用includes()来包含类别和类别的根。

作为一些额外信息,类别只能嵌套2个级别(只是类别和子类别)。因此,root在技术上意味着父级,它不必遍历多个级别。

有什么想法吗?

1 个答案:

答案 0 :(得分:3)

我有一个非常类似的问题,除了我想要加载类别path而不仅仅是root。不幸的是,急切加载仅适用于关联。 Ancestry导航器(parentrootpathancestors等等都是方法,而不是关联,所以你可以&#39 ;急于加载它们。

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

<强> category.rb

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

<强> entries_controller.rb

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

<强>视图/条目/ index.html.haml

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

希望有所帮助。