我有一个模型A,该模型A可以在一对一的关系中具有多达10个相关模型B。这些嵌套模型只有一个字符串属性代表一个单词。
我想显示一个表格来创建/编辑父型模型和所有嵌套的孩子,并显示10个可能模型的字段。然后,如果我只填写其中两个,将创建两个模型。
最后,当编辑模型A时,我需要显示10个字段,其中两个填充了与数据相关联的模型B,其余的空白就可以填充。
尝试使用数组的fields_for
,但仅显示已经存在的模型B实例的字段。
查看:
= form_for @a, remote: true do |f|
= f.text_field :title, placeholder: true
= f.fields_for :bs, @a.bs do |ff|
/ Here, for the edit action, N text fields appear, being N equals to @soup.soup_words.size
/ and I need to display 10 fields everytime, because a Soup can have up to 10 SoupWord
/ For the new action, it should display 10 empty text fields.
/ Finally, if you fill three of the 10 fields,
/ model A should have only 3 instances of model B associated. i.e if there were 4 filled and
/ I set one of them blank, the model B instance should be destroyed.
= ff.text_field :word, placeholder: true
= f.submit
控制器:
class Bs < ApplicationController
def edit
respond_to :js
@soup = Soup.find params[:id]
end
def update
respond_to :js
puts params
end
end
update
现在创建和编辑操作现在起作用,只需将reject_if
参数放在模型A,
accepts_nested_attributes_for :bs, reject_if: proc { |attrs| attrs[:word].blank? }
并将build
设置在控制器上。
def new
respond_to :js
@a = A.new
10.times { @a.bs.build }
end
def edit
respond_to :js
@a = Soup.find params[:id]
@a.bs.size.upto(9) do |sw|
@a.bs.build
end
end
现在,如果我在编辑操作中将它们设置为空白,我需要破坏B的实例。
通常,您会使用allow_destroy: true
选项并通过_destroy
参数删除嵌套记录:
class Soup
accepts_nested_attributes_for :soup_words,
reject_if: proc { |attrs| attrs[:word].blank? },
allow_destroy: true
end
要获得想要的行为,您可以将JavaScript与隐藏的输入一起使用:
= form_for @soup, remote: true do |f|
= f.text_field :title, placeholder: true
= f.fields_for :soup_words, @soup.soup_words do |ff|
= ff.text_field :word, class: 'soup_word', placeholder: true
= ff.hidden_input :_destroy
= f.submit
$(document).on('change', '.soup_word', function(){
var $obj = $(this);
if (!this.value || !this.value.length) {
// set soup_word to be destroyed
$obj.siblings('input[name~=_destroy]').val('1');
}
$obj.fadeOut(50);
});
确保您已将_destroy
和id
参数列入白名单。
def update_params
params.require(:soup).permit(:soup_words_attributes: [:word, :id, :_destroy])
end