【问题标题】:Update multiple records in nested model from checkboxes从复选框更新嵌套模型中的多条记录
【发布时间】:2026-02-19 06:20:03
【问题描述】:

我已经为此苦苦挣扎了好几天,我已经阅读了六个 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

在我的消息控制器中,我有 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 =>[]] } )

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

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"}

谁能指出我正确的方向和/或提供一个例子?

【问题讨论】:

    标签: ruby-on-rails


    【解决方案1】:

    我现在可以在“创建”方法中使用以下代码。以防万一这有助于其他人尝试实现同样的目标。如果这不是很好的做法,请随时发表评论。

     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
    

    【讨论】:

      最近更新 更多