Rails Fields_为10个嵌套可选型号,在编辑中显示一些填充和一些空白



我有一个模型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);
});

确保您已将_destroyid参数列入白名单。

def update_params
  params.require(:soup).permit(:soup_words_attributes: [:word, :id, :_destroy])
end

最新更新