【问题标题】:Rails eager loading multiple associations difficultyRails 急切加载多个关联的难度
【发布时间】:2014-08-26 20:41:29
【问题描述】:

我有以下三种型号:

一个 TestRun 模型、一个 TestResult 模型和一个 Test 模型。一个 TestRun 有多个 TestResult,一个 TestResult 有一个 Test。 (一个测试可以有很多结果,但它与这个问题并不真正相关)

我渴望使用以下内容将所有内容加载到测试运行中:

test_run = TestRun.includes(test_results: [:test]).find(params[:id])

这很好用,创建了三个单独的查询。现在的问题是我想确定其中一个查询的范围。我想从该查询的 test_results 中排除一个字段(称为“日志”)。我在 TestResult 模型中创建了一个范围,但我不确定如何在这种情况下应用它。

我可以这样做:

tr = TestRun.find(id)
tr.test_results.without_log.include(:test).load

除了当我调用第三个关联时它没有预加载之外,它有效。例如

tr.test_results[1].test #This causes an additonal query

我试图保留一个预先加载所有其他关联的 TestRun 模型。这可能吗?

编辑:

def self.without_log
    select(column_names-['log'])
end

【问题讨论】:

  • 我不知道without_log 是什么样子,但如果没有日志只是一个 where 子句,TestRun.find(id).test_results.includes(:test).without_log 应该可以工作。 Check This Out for More。您可以使用 eager_load 强制预加载
  • 我将在原始帖子中添加 without_log。但是是的,您的查询确实有效,但它没有保存任何内容。我想基本上调用这个查询并将它的所有加载到我可以传递的对象中。我可以单独做,但我的序列化程序和所有东西都设置好了,除了一个 TestRun 对象,它希望完全加载并且不会进行任何额外的查询
  • 如果我可以从您给我的查询中获取结果并将其存储回一个可以正常工作的 TestRun 对象,我只是不确定是否有一种简单的方法可以做到这一点。不这样做将需要我更改我的序列化程序当前的工作方式。
  • 您是否总是希望预先加载关联?如果是这样,或者即使不发布 TestRun 模型关联可能是有益的,但您可以使用预先加载的默认范围。这样,当您加载 TestRun 时,它会自动预先加载关联

标签: ruby-on-rails ruby


【解决方案1】:

我会尽量回答这个问题。

如果您总是希望预先加载关联,那么我会尝试使用 default_scope

class TestRun < ActiveRecord::Base
   has_many :test_results
   default_scope includes({:test_results=> :test})
end

这应该会在每个查询中预先加载关联,因此TestRun.find(id).without_log 应该已经准备好预先加载这些项目。

如果您不总是希望加载关联,那么我建议使用一个范围,例如

class TestRun < ActiveRecord::Base
  has_many :test_results
  scope :find_with_eager_load,->(id){
       where(id: id).includes({:test_results => :test}).without_log
  }
end

然后调用TestRun.find_with_eager_load(id),它应该会产生请求的结果。 尽管我不确定其含义,但您确实有另一种选择,但您可以尝试

class TestRun < ActiveRecord::Base
  has_many :test_results
  has_many :tests, through: :test_results
end

然后要么创建一个作用域或默认作用域,要么调用为TestRun.find(id).includes(:test_results,:tests).without_log

它应该会产生类似的结果,尽管我不确定通过has_many 关联使用has_many 时的查询。此外,由于您没有使用 whereorder 子句,因此您必须将 includes 更改为 eager_load 以强制进行单数查询。

希望这对您想要实现的目标有所帮助

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-26
    相关资源
    最近更新 更多