ruby-on-rails 在Rails中从单个表单提交中提交多个表条目

o4hqfura  于 2022-11-26  发布在  Ruby
关注(0)|答案(1)|浏览(153)

我尝试为我的钓鱼俱乐部会议制作一个出席表,它显示了所有活跃的成员,并允许您在他们的名字旁边放置一个复选框,以记录他们是否参加了某个特定锦标赛的会议。我创建了一个“会议”支架,并在_form中列出了所有活跃的成员,并允许用户在该成员是否参加了所选锦标赛的会议上放置一个复选框。然而,我在向meetings_controller传递哈希数组时遇到了问题,我很困惑。
我读了一堆文章,但我的设计基线关闭这一个:Submit array of hashes with rails
这篇文章没有显示create方法中的内容,所以我有这个...
会议控制器(_C):

def create
    # puts " OUTPUT TEXT: #{params} " 
    
    @meeting = params[:meetings][:meetings]
    
    @meeting.each do |m|

    #If there is no attendance key, its nil. Make it false
    # if !m[:meeting].has_key?("attendance")
    #     m[:meeting].attendance = false
    # end
     
      puts "OUTPUT TEXT: #{m[:meeting]}" # OUTPUT TEXT: {"member_id"=>"1", "tournament_id"=>"2", "attendance"=>"1"}
     
      @meeting = Meeting.new(member_id: m[:meeting][:member_id], tournament_id: m[:meeting][:tournament_id], attendance: m[:meeting][:attendance])
     
   end
    respond_to do |format|
      if @meeting.save
        format.html { redirect_to @meeting, notice: "Meeting was successfully created." }
        format.json { render :show, status: :created, location: @meeting }
      else
        format.html { render :new, status: :unprocessable_entity }
        format.json { render json: @meeting.errors, status: :unprocessable_entity }
      end
    end
  end

表单输入(_F):(基于上面链接的文章)

<% Member.where(active: true).each do |member| %>
   
   <tr>
    <td> <%= member.full_name %> </td>
    
    <input multiple="multiple" value=<%=member.id %> type="hidden" name="meetings[meetings][]meeting[member_id]" />

    <input multiple="multiple" value=<%=@tournament.id %> type="hidden" name="meetings[meetings][]meeting[tournament_id]" />
    

    <td><input type="checkbox" value="1" name="meetings[meetings][]meeting[attendance]" /></td>
  </tr>
 <% end %>

当我点击提交表单时,它只是把我带到显示页面,在那里只有这是显示在一个空白页面上...
{“控制器”=〉“会议”,“操作”=〉“显示”,“id”=〉“18”}
即使show方法中有redirect行

def show
    redirect_to meetings_path
end

我已经花了很多时间阅读,并尝试和错误的尝试,让这个工作。我希望stackoverflow神可以帮助。

gojuced7

gojuced71#

在控制器中,当您循环通过会议参数Meeting时,@meeting不会保存到数据库,并且@meeting变量被覆盖,直到数组中的最后一项...

@meeting.each do |m|     
  @meeting = Meeting.new(member_id: m[:meeting][:member_id], tournament_id: m[:meeting][:tournament_id], attendance: m[:meeting][:attendance])
end

......而那个人被救了。

if @meeting.save

也不知道你的show操作是怎么回事,只是保存后不要重定向到它。
在Rails表单中使用数组有点不确定,但它在这里。
控制器:

# params - submitted params from the form
#          { "authenticity_token"=>"[FILTERED]", 
#             "meetings"=>[
#               { "member_id"=>"1", "tournament_id"=>"1", attendance"=>"1" },
#               ...
#              ],
#            "commit"=>"Save"
#          }

# POST /meetings
def create
  @meetings = meetings_params.map do |param|
    Meeting.create_with(attendance: param[:attendance])
      .find_or_create_by(member_id: param[:member_id], tournament_id: param[:tournament_id])
  end
  respond_to do |format|
    if @meetings.detect{|m| m.id == nil }  # id=nil if any meetings didn't save
      # FIXME: @tournament not initialized here
      format.html { render :new, status: :unprocessable_entity }
    else
      format.html { redirect_to meetings_url, notice: "Meetings were created." }
    end
  end
end

# Returns array 
# [{member_id: 1, tournament_id: 1, attendance: 1}, ...]
def meetings_params
  params.permit(meetings: [:member_id, :tournament_id, :attendance]).require(:meetings)
end

表格:

<%= form_with url: "/meetings" do |f| %>
  <% Member.where(active: true).each do |member| %>
    <%# TODO: if meeting doesn't save, there is no error to show %>
    <%= text_field_tag "meetings[][member_id]",     member.id %>
    <%= text_field_tag "meetings[][tournament_id]", @tournament.id %>
    <%= check_box_tag  "meetings[][attendance]",    Meeting.find_by(member: member, tournament: @tournament)&.attendance %>
  <% end %>
  <%= f.submit %>
<% end %>

或使用fields_for帮助器:

<%= form_with url: "/meetings" do |f| %>
  <% Member.where(active: true).each do |member| %>
    <%#                            this nil does the [] thing %>
    <%#                                     |                 %>
    <%= fields_for "meetings", nil, index: nil do |ff| %>
      <%= ff.number_field "member_id",     value: member.id %>
      <%= ff.hidden_field "tournament_id", value: @tournament.id %>
      <%= ff.check_box    "attendance",    value: Meeting.find_by(member: member, tournament: @tournament)&.attendance %>
    <% end %>
  <% end %>
  <%= f.submit %>
<% end %>

更新

可以说,以上所有这些都是非常不合常理的。下面是我想出的让它变得超级简单的方法:
我们需要一个Attendance表来跟踪每个成员对每个Meeting的出席情况:
一个
MeetingsController是默认支架:

bin/rails g scaffold_controller meeting

仅更新new操作:

# app/controllers/meetings_controller.rb
def new
  @meeting = Meeting.new
  # NOTE: build a list of attendances for the form to render
  Member.where(active: true).each do |member|
    @meeting.attendances.build(member: member)
  end
end

现在的表单非常简单:

<!-- app/views/meetings/_form.html.erb -->
<%= form_with model: @meeting do |f| %>
  <%= f.fields_for :attendances do |ff| %>
    <%= ff.number_field :member_id %>
    <%= ff.check_box :attended %>
  <% end %>
  <%= f.submit %>
<% end %>

createupdate完全独立工作。

相关问题