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 boxes
和 stacks
。 Rails 会将其转换为 SQL 查询
SELECT "template_variables".* FROM "template_variables" WHERE "box"."stack.html_box" = ...
如您所见,此查询不知道 where 子句。哪个是 "box"
table?哪个是 "stack.html_box"
列?
所以你所要做的就是首先加入 boxes
和 stacks
,然后 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
希望对您有所帮助。
我的 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 boxes
和 stacks
。 Rails 会将其转换为 SQL 查询
SELECT "template_variables".* FROM "template_variables" WHERE "box"."stack.html_box" = ...
如您所见,此查询不知道 where 子句。哪个是 "box"
table?哪个是 "stack.html_box"
列?
所以你所要做的就是首先加入 boxes
和 stacks
,然后 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
希望对您有所帮助。