具有嵌套属性的模型在不是模型属性的字段中不显示 fields_for
Model with nested attributes doesn't show fields_for in field that is not an attribute in the model
我有一个 Exam
和一个 ExamBattery
,它们只是 Exams
的集合。它们彼此有一个 has_and_belong_to_many
声明,并且 ExamBattery
接受 Exam
的嵌套属性,例如:
class Exam < ApplicationRecord
has_and_belongs_to_many :exam_batteries
validates_presence_of :name
end
class ExamBattery < ApplicationRecord
has_and_belongs_to_many :exams
accepts_nested_attributes_for :exams, reject_if: lambda { |attrs| attrs['name'].blank? }
validates_presence_of :name
end
当我创建一个新的 Exam
时,我希望能够将它分配给一个或多个 ExamBatteries
,因此在 ExamsController
中我将数组 exam_battery_ids
列入了白名单接受多个 ExamBatteries
将它们分配给当前的 Exam
(没有进行其他更改,控制器只是来自脚手架):
def exam_params
params.require(:exam).permit(:name, :description, :order, :price, exam_battery_ids: [])
end
此外,在视图 exams/new
中,我添加了一个倍数 select 以将所需的 exam_battery_ids
作为参数发送:
<%= form_with(model: exam, local: true) do |form| %>
# ... typical scaffold code
<div class="field">
<% selected = exam.exam_batteries.collect { |eb| eb.id } %>
<%= form.label :exam_battery_ids, 'Add batteries:' %>
<%= form.select :exam_battery_ids,
options_from_collection_for_select(ExamBattery.all, :id, :name, selected),
{ prompt: 'None' },
multiple: true %>
</div>
<% end %>
想法是能够创建一个新的ExamBattery
,里面有新的Exams
,形式相同(我还没有写那部分,我现在只能编辑).另外,当我编辑 ExamBattery
时,我希望能够编辑它的 Exams
甚至将它们分配给其他 ExamBatteries
(如果我 select 'None',或者只是另一个考试电池,它将停止分配给当前 ExamBattery
),所以在 exam_batteries/edit
中(实际上,其中的部分形式)我有这个代码:
<%= form_with(model: exam_battery, local: true) do |form| %>
# ... normal scaffold code
<div class="field">
<!-- it should be exam_battery[exams_attributes][#_of_field][order] -->
<!-- it is exam_battery[exam_battery_ids][] -->
<% selected = exam_battery.exams.map { |exam| exam.id } %>
<%= form.label :exam_battery_ids, 'Edit batteries:' %>
<%= form.select :exam_battery_ids,
options_from_collection_for_select(ExamBattery.all, :id, :name, selected),
{ prompt: 'None' },
multiple: true %>
</div>
<% end %>
在 ExamBatteriesController
中,我将 exam_batteries_attributes
列入白名单,其中 exam_battery_ids: []
作为参数:
params.require(:exam_battery).permit(:name, :certification, exams_attributes: [:name, :description, :order, :price, exam_battery_ids: []])
但是当我在 ExamBattery
表单中尝试编辑 Exam
的 exam_batteries
时,信息不会更新,因为参数是这样的:
Parameters: {"utf8"=>"✓", "authenticity_token"=>"blah", "exam_battery"=>{"name"=>"Battery1", "certification"=>"test1", "exams_attributes"=>{"0"=>{"name"=>"Exam1", "description"=>"", "order"=>"", "id"=>"3"}, "1"=>{"name"=>"Exam2", "description"=>"", "order"=>"", "id"=>"4"}, "2"=>{"name"=>"Exam3", "description"=>"", "order"=>"", "id"=>"5"}}, "exam_battery_ids"=>["", "", "", "", "", "3"]}, "commit"=>"Update Exam battery", "id"=>"3"}
exam_battery_ids
作为不同的参数发送,因为 select 名称是 exam_battery[exam_battery_ids][]
而不是像 exam_battery[exams_attributes][0][name]
这样的东西,就像其他字段一样。我该如何解决?
谢谢。
我的表格有误。在 exam_batteries/edit
中我没有注意到我使用的是 form_with 变量(表单)而不是 fields_for 变量(生成器),所以它应该是这样的:
<div class="field">
<!-- it should be exam_battery[exams_attributes][0][order] -->
<!-- it is exam_battery[exam_battery_ids][] -->
<% selected = exam_battery.exams.map { |exam| exam.id } %>
<%= builder.label :exam_battery_ids, 'Escoge una batería' %>
<%= builder.select :exam_battery_ids,
options_from_collection_for_select(ExamBattery.all, :id, :name, selected),
{
include_hidden: false,
prompt: 'Ninguna'
},
multiple: true %>
</div>
有了它应该可以工作。
现在唯一的问题是,当我在 fields_for 中显示它们时,我无法获得选定的电池,但我正在努力。
更新:我可以通过用以下代码替换视图中的选定变量,以嵌套形式显示考试的当前 exam_batteries:
<% selected = exam_battery.exams[builder.options[:child_index]].exam_batteries.map { |eb| eb.id } %>
如果您知道更清洁的方法,请告诉我。
我有一个 Exam
和一个 ExamBattery
,它们只是 Exams
的集合。它们彼此有一个 has_and_belong_to_many
声明,并且 ExamBattery
接受 Exam
的嵌套属性,例如:
class Exam < ApplicationRecord
has_and_belongs_to_many :exam_batteries
validates_presence_of :name
end
class ExamBattery < ApplicationRecord
has_and_belongs_to_many :exams
accepts_nested_attributes_for :exams, reject_if: lambda { |attrs| attrs['name'].blank? }
validates_presence_of :name
end
当我创建一个新的 Exam
时,我希望能够将它分配给一个或多个 ExamBatteries
,因此在 ExamsController
中我将数组 exam_battery_ids
列入了白名单接受多个 ExamBatteries
将它们分配给当前的 Exam
(没有进行其他更改,控制器只是来自脚手架):
def exam_params
params.require(:exam).permit(:name, :description, :order, :price, exam_battery_ids: [])
end
此外,在视图 exams/new
中,我添加了一个倍数 select 以将所需的 exam_battery_ids
作为参数发送:
<%= form_with(model: exam, local: true) do |form| %>
# ... typical scaffold code
<div class="field">
<% selected = exam.exam_batteries.collect { |eb| eb.id } %>
<%= form.label :exam_battery_ids, 'Add batteries:' %>
<%= form.select :exam_battery_ids,
options_from_collection_for_select(ExamBattery.all, :id, :name, selected),
{ prompt: 'None' },
multiple: true %>
</div>
<% end %>
想法是能够创建一个新的ExamBattery
,里面有新的Exams
,形式相同(我还没有写那部分,我现在只能编辑).另外,当我编辑 ExamBattery
时,我希望能够编辑它的 Exams
甚至将它们分配给其他 ExamBatteries
(如果我 select 'None',或者只是另一个考试电池,它将停止分配给当前 ExamBattery
),所以在 exam_batteries/edit
中(实际上,其中的部分形式)我有这个代码:
<%= form_with(model: exam_battery, local: true) do |form| %>
# ... normal scaffold code
<div class="field">
<!-- it should be exam_battery[exams_attributes][#_of_field][order] -->
<!-- it is exam_battery[exam_battery_ids][] -->
<% selected = exam_battery.exams.map { |exam| exam.id } %>
<%= form.label :exam_battery_ids, 'Edit batteries:' %>
<%= form.select :exam_battery_ids,
options_from_collection_for_select(ExamBattery.all, :id, :name, selected),
{ prompt: 'None' },
multiple: true %>
</div>
<% end %>
在 ExamBatteriesController
中,我将 exam_batteries_attributes
列入白名单,其中 exam_battery_ids: []
作为参数:
params.require(:exam_battery).permit(:name, :certification, exams_attributes: [:name, :description, :order, :price, exam_battery_ids: []])
但是当我在 ExamBattery
表单中尝试编辑 Exam
的 exam_batteries
时,信息不会更新,因为参数是这样的:
Parameters: {"utf8"=>"✓", "authenticity_token"=>"blah", "exam_battery"=>{"name"=>"Battery1", "certification"=>"test1", "exams_attributes"=>{"0"=>{"name"=>"Exam1", "description"=>"", "order"=>"", "id"=>"3"}, "1"=>{"name"=>"Exam2", "description"=>"", "order"=>"", "id"=>"4"}, "2"=>{"name"=>"Exam3", "description"=>"", "order"=>"", "id"=>"5"}}, "exam_battery_ids"=>["", "", "", "", "", "3"]}, "commit"=>"Update Exam battery", "id"=>"3"}
exam_battery_ids
作为不同的参数发送,因为 select 名称是 exam_battery[exam_battery_ids][]
而不是像 exam_battery[exams_attributes][0][name]
这样的东西,就像其他字段一样。我该如何解决?
谢谢。
我的表格有误。在 exam_batteries/edit
中我没有注意到我使用的是 form_with 变量(表单)而不是 fields_for 变量(生成器),所以它应该是这样的:
<div class="field">
<!-- it should be exam_battery[exams_attributes][0][order] -->
<!-- it is exam_battery[exam_battery_ids][] -->
<% selected = exam_battery.exams.map { |exam| exam.id } %>
<%= builder.label :exam_battery_ids, 'Escoge una batería' %>
<%= builder.select :exam_battery_ids,
options_from_collection_for_select(ExamBattery.all, :id, :name, selected),
{
include_hidden: false,
prompt: 'Ninguna'
},
multiple: true %>
</div>
有了它应该可以工作。 现在唯一的问题是,当我在 fields_for 中显示它们时,我无法获得选定的电池,但我正在努力。
更新:我可以通过用以下代码替换视图中的选定变量,以嵌套形式显示考试的当前 exam_batteries:
<% selected = exam_battery.exams[builder.options[:child_index]].exam_batteries.map { |eb| eb.id } %>
如果您知道更清洁的方法,请告诉我。