我试图编写一个定义,用作表单中选择字段的选项。
Miniature.rb
has_many :manufacturers
has_many :lines
end
Line.rb
belongs_to :manufacturer
end
将@miniature添加到@line时,我希望下拉菜单只显示属于与@miniature对应的@manufacturer的@lines。
这是我的尝试
def mfr_lines
@mfrs = @miniature.manufacturers.map
@mfr_lines = @mfrs.lines.map
end
第一行似乎有效,它结合了所有@mini.manufacturers 我需要做的是获取EACH @manufacturer的所有行并将它们连接成一个数组。我无法解决如何进行EACH或如何加入它们的问题。尝试了许多可能的解决方案无济于事。任何帮助非常感谢。
它想在视图中最终像这样工作
<%= f.select :line_id, @mfr_lines, include_blank: true %>
答案 0 :(得分:3)
@ hoffm的解决方案很好,但可以使用一点改进的版本:
def mfr_lines
@lines = Line.where(manufacturer_id: @miniature.manufacturers.pluck(:id))
end
用于options_for_select
(1)的选择:
f.select :line_id, options_for_select(@lines.map{|l| [l.name, l.id] }), include_blank: true
为什么它比@miniature.manufacturers.map(&:lines).flatten
更好?
manufacturers.map(&:lines)
实际上在每个.lines
上调用方法manufacturer
(触发SQL查询)。如果您有10个,则会调用10次SELECT * FROM lines WHERE lines.manufacturer_id = <id>
,
Line.where(manufacturer_id: @miniature.manufacturers.pluck(:id))
是并且将始终只有2个组合查询:
# @miniature.manufacturers.pluck(:id) (2)
SELECT id FROM manufacturers WHERE manufacturers.miniature_id = <@miniature.id> ;
# This returns a list of IDs
# Line.where(manufacturer_id: list_of_ids)
SELECT * FROM lines WHERE lines.manufacturer_id IN (<list_of_ids>) ;
总体而言,以下Ruby on Rails代码:
Line.where(manufacturer_id: @miniature.manufacturers.pluck(:id))
触发以下SQL:
SELECT *
FROM lines
WHERE lines.manufacturer_id
IN ( SELECT id
FROM manufacturers
WHERE manufacturers.miniature_id = <@miniature.id> )
参考文献:
答案 1 :(得分:1)
在没有块的情况下调用map
将返回一个枚举器,它听起来并不像您期望的那样。如果我理解你所追求的是什么,这就是要走的路:
def mfr_lines
@miniature.manufacturers.map(&:lines).flatten
end
此代码检索与缩略图相关联的所有制造商的数组,然后将每个制造商的数组映射到其行的数组中。结果是一个行数组的数组,然后我们将它们展平以得到一系列可以迭代的行。