Rails:从祖父母的属性中收集记录

时间:2016-11-13 02:07:01

标签: ruby-on-rails ruby-on-rails-4 ruby-on-rails-5

我有这样一种深层次的关系:

>> @document.template_variables.first.master.box.stack
=> #<Stack id: 6, name: "Contact information", direction: "down", x: 145.0, y: 145.0, template_id: 28, width: 55, page: 1, html_box: "column_right">

Master不是完全正常的Rails关系,它在TemplateVariable中定义如下:

def master
  TemplateVariable.find(master_id) if master_id.present?
end

所以它有点指的是它自己的另一个实例,但正如你从顶部的日志输出中看到它可以正常工作。

我的问题是,我需要所有 TemplateVariables,其父Stack与框名称匹配,如下所示:

scope :by_box, -> (b) { where('box.stack.html_box' => b) }

但无论我尝试什么,即使在控制台中,我都无法正确查询。

>> @document.template_variables.where(master.box.stack.html_box != nil)
!! #<NameError: undefined local variable or method `master' for #<#<Class:0x007fd287cd9888>:0x007fd28bb11ee8>>

并且范围返回此错误:

ActiveRecord::StatementInvalid - PG::UndefinedTable: ERROR:  missing FROM-clause entry for table "box"
LINE 1: ...WHERE "template_variables"."document_id" = $1 AND "box"."sta...

有任何帮助吗?我错过了什么?

1 个答案:

答案 0 :(得分:1)

我想我应该在这里创建一个答案。您的范围引发了错误,因为您没有在where子句boxes之前加入表stackswhere('box.stack.html_box' => b)。 Rails会将其转换为SQL查询

SELECT "template_variables".* FROM "template_variables" WHERE "box"."stack.html_box" = ...

如您所见,此查询不知道where子句。哪个是"box"表?这是"stack.html_box"列? 所以你要做的就是首先加入boxesstacks,然后where子句是where(stacks: { html_box: b })where('stacks.html_box' => b })stacks是复数,因为它是表名),它被转换为SQL查询

SELECT "template_variables".* FROM "template_variables" INNER JOIN "boxes" ON "boxes"."id" = "template_variables"."box_id" INNER JOIN "stacks" ON "stacks"."id" = "boxes"."stack_id" WHERE "stacks"."html_box" = ...

它会运作良好。 另一个建议是,您应该将master定义为belongs_to关联,例如

belongs_to :master, class_name: 'TemplateVariable', foreign_key: :master_id

希望得到这个帮助。