通过复选框更新嵌套模型中的多个记录

时间:2018-12-23 14:35:27

标签: ruby-on-rails

我已经为此苦苦挣扎了好几天,我已经阅读了六个SO答案,但是似乎找不到正确的方法来实现我所需要的。我查看的最新版本是HERE。我想不出如何使它适应我的需求。

我之前因未正确提出问题而被打分,所以我尝试在问题中包括尽可能多的细节。如果这太多了,请不要在问题上打上勾号,仅建议进行更改,我将负责。

基本上,我想从嵌套形式的复选框中一次更新一个嵌套模型中的多个记录。

我有2个模型,第一个是Message模型:-

class Message < ApplicationRecord
  has_many :message_recipients, dependent: :destroy
  accepts_nested_attributes_for :message_recipients, :allow_destroy => true
end

第二个是MessageRecipient模型:-

class MessageRecipient < ApplicationRecord
    belongs_to :message, optional: true
end

在我的Messages控制器中,我有2种方法:-

def new
  @message = Message.new
  4.times do
   @message.message_recipients.build
  end
end

def create
 @message = Message.new(message_params)
 respond_to do |format|
   if @message.save
     format.html { redirect_to @message, notice: 'Message was successfully created.' }
     format.json { render :show, status: :created, location: @message }
   end

我也可以在控制器中使用参数:-

def message_params
  params.require(:message).permit(:user_id, :expirydate, :subject, :messagebody, :createdate, {message_recipients_attributes: [:id, :_destroy, :role]} )
end

我认为我有:-

<%= form_with(model: message, local: true) do |form| %>
  <div class="field">
    <%= form.label :messagebody %>
    <%= form.text_field :messagebody %>
  </div>
    <%= form.fields_for :message_recipients do |m| %>
      <%= m.select :role, options_for_select(User.role_for_messages.map {|k, v| [k.humanize.capitalize, v]}, :selected => m.object.role)  %>
   <% end %>
    <div class="actions">
    <%= form.submit %>
  </div>
<% end %>

现在所有这些都可以很好地工作,并且完全满足我的需要,但是我不想使用多个选择,而是希望将其转换为使用复选框。为此,我将视图文件更改为:-

<%= form.fields_for :message_recipients do |m| %>
  <%= m.collection_check_boxes :role, User.role_for_messages, :second, :first do |b| %>
      <div class="collection-check-box"> %>
         <%= b.check_box %>
         <%= b.label %>
      </div> %>
    <% end %> 
   <% end %>

我还更改了message_params以允许以下复选框数组:-

params.require(:message).permit(:user_id, :expirydate, :subject, :messagebody, :createdate, {message_recipients_attributes: [:id, :_destroy, :role =>[]] } )

最后,我将消息控制器New方法更改为:-

def new
  @message = Message.new
  @message.message_recipients.build
end

问题是当我没有收到控制台错误时,我也没有创建多个子记录。实际上,我创建了一条记录,但复选框中没有任何值。我认为这与参数的生成方式有关,但我无法弄清问题所在。为了完整起见,我包括以下生成的参数:-

  Parameters: {"utf8"=>"✓", "authenticity_token"=>"qKQ+Ove7DRJqUIZ+NlgCdM85G9Mf5p8h1gWCF36vd9ODa40G4miKkhHaNbG7grpVFqqCiF7uq+BT8G9Olvm5qQ==", "message"=>{"user_id"=>"3", "subject"=>"Subject 3", "messagebody"=>"Message Body 3", "createdate"=>"2018-12-21", "expirydate"=>"09/08/18", "message_recipients_attributes"=>{"0"=>{"role"=>["", "0", "1", "2", "3"]}}}, "commit"=>"Create Message"}

有人可以指出正确的方向和/或提供示例吗?

1 个答案:

答案 0 :(得分:0)

我现在使用'create'方法中的以下代码进行此工作。以防万一这有助于其他人尝试实现相同的目的。如果这不是好习惯,请随时发表评论。

 def create
  # create the message and save it so I can access it's ID
  @message = Message.new(message_params)
  @message.save

  # populate a new array with the role attributes and discard any that are empty
  params_array = params[:message_recipients_attributes][:role]
  params_array.reject!(&:empty?)

  #loop through the roles and create new child records with the message_id and role(s)
  params_array.each  do |doo|
    @message_recipients = MessageRecipient.new(:message_id => @message.id, :role => doo)
    @message_recipients.save
  end

  #standard boilerplate for checking the message saved and redirecting user
  respond_to do |format|
    if @message.save
      format.html { redirect_to @message, notice: 'Message was successfully created.' }
      format.json { render :show, status: :created, location: @message }
    else
      format.html { render :new }
      format.json { render json: @message.errors, status: :unprocessable_entity }
    end
  end
end