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

Rails: collecting records from grandparent's attributes

我的 deep-nested 关系是这样的:

>> @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

所以它有点引用了它自己的另一个实例,但正如您从顶部的日志输出中看到的那样,它工作正常。

我的问题是我需要获取 all TemplateVariables 其 parent 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>>

和范围returns这个错误:

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

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

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

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

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

希望对您有所帮助。