导轨中自定义方法的N + 1问题

时间:2018-10-29 04:34:29

标签: ruby-on-rails select-n-plus-1

在我的Rails应用程序中,我有一个User模型,该模型带有一种称为price_tier的方法:

def price_tier
  Spree::PriceTier.by_code[read_attribute(:price_tier)]
end

但是,当我有一个@users集合并一个一个地调用price_tier时,它将为每个实例加载PriceTier查询,这会导致N + 1问题。

includes在这里不起作用,因为它不是关联。

@users.map { |user| user.price_tier }

有什么办法可以修改解决N + 1问题的代码?

1 个答案:

答案 0 :(得分:1)

您确实应该直接设置模型之间的关系,例如user has_one :price_tier。这将使代码变得轻而易举。

如果您不这样做,那么您会跳过一些很简单的事情。您可以也许使用类似以下内容的方法,尽管它的效率仍然远低于直接关系:

tiers = Spree::PriceTier.where(code: @users.pluck(:price_tier))
                        .each_with_object({}) { |tier, hash| hash[tier[code]] = tier }

@users.map { |user| tiers[user.price_tier] }

以上假设删除实例方法:price_tier并使用该属性。

我不确定是否真的值得包括上述内容-您收集用户的price_tier,访问数据库的db(仅一次,而不是每个用户),然后遍历所有这些以创建用于快速访问的哈希,然后 then 遍历用户以进行映射。通过建立关系可以轻松解决某些事情,这是很多工作。

希望有帮助,并真的希望上面的语气能够通过-基本上意味着您可以进行上述操作,尽管真正的建议是:请不要,设置一个关系,并在这里使用常规方法:)