Rails 5.07项目如何调整表单参数以得到期望的嵌套结构
Rails 5.07 表单参数结构调整需求
需求说明
在Rails 5.07环境下开发应用时,现有表单及其局部组件提交的参数结构不符合业务要求,需要通过调整参数结构、修改模型关联或优化嵌套表单实现参数重排。
注:当前核心目标仅为完成参数结构转换,若问题描述需要优化,可告知具体原因及优化示例。
参数结构对比
现有参数结构
{"utf8"=>"✓", "assignment"=>{"volunteer_shift_attributes"=>{"volunteer_task_type_id"=>"41", "roster_id"=>"7", "program_id"=>"9", "set_description"=>"Nov10", "set_date"=>"2021-01-08"}, "start_time(1i)"=>"2021", "start_time(2i)"=>"11", "start_time(3i)"=>"10", "start_time(4i)"=>"08", "start_time(5i)"=>"00", "end_time(1i)"=>"2021", "end_time(2i)"=>"11", "end_time(3i)"=>"10", "end_time(4i)"=>"09", "end_time(5i)"=>"00", "notes"=>"Nov10", "contact_id"=>"166574", "closed"=>"0", "lock_version"=>"0"}, "contact_element_prefix"=>"contact", "commit"=>"Submit", "controller"=>"volunteer_events", "action"=>"create_shift"}
期望参数结构
{"assignment"=>{"volunteer_shift_attributes"=> {"volunteer_task_type_id"=>"41", "roster_id"=>"7", "program_id"=>"9", "set_description"=>"fonso says wtf?"}, "set_date"=>"2021-01-07", "contact_id"=>"166574", "closed"=>"0", "start_time(4i)"=>"12", "start_time(5i)"=>"00", "end_time(4i)"=>"13", "end_time(5i)"=>"00", "notes"=>"fuuuuuuuuuk"}, "lock_versions"=>["0"], "contact_element_prefix"=>"contact", "commit"=>"Update", "controller"=>"volunteer_events", "action"=>"create_shift"}
调整后可通过如下代码获取目标值,预期返回结果为"7":
params["assignment"]["volunteer_shift_attributes"]["roster_id"]
若需要模型关联等补充信息可告知,会同步对应内容。
补充表单代码
主表单代码
<!--This is NEW action form--> <%= form_for @assignment, :url => @my_url, remote: true do |f| %> <!-- #FIXME need a fields_for 4 the volunteer_event--> <div class=""> <div class="modal-body d-flex"> <div class="col-sm-8 border-right"> <section id="location-date-time-notes" class="flex"> <% if @assignment.errors.any? %> <div id="error_explanation"> <h2><%= pluralize(@assignment.errors.count, "error") %> prohibited this assignment from being saved:</h2> <ul> <% @assignment.errors.full_messages.each do |message| %> <li><%= message %></li> <% end %> </ul> </div> <% end %> <!--VOLUNTEER SHIFT--> <!--TODO: make this a partial under field_for--> <%= f.fields_for :volunteer_shift do |builder| %> <%= render 'assignments/volunteer_shift_fields', vs: builder %> <% end %> <!--TODO: Volunteer Shift end --> <div id="time-row" class="d-flex flex-row"> <label for="assignment_time" class="col-sm-3 p-2"> <i class="fa fa-clock-o fa-lg" aria-hidden="true"></i> Time: </label> <div class="col- p-2"> <div class="myStartTime" id="start_time_<%= @assignment.id %>"> <%= f.time_select :start_time %> </div> </div> <div class="col- p-2"><i class="fa fa-arrows-h fa-lg" aria-hidden="true"></i></div> <div class="col-sm-3 p-2"> <div class="myEndTime" id="end_time_<%= @assignment.id %>"> <%= f.time_select :end_time %> </div> </div> </div> <div class="d-flex flex-row"> <label for="assignment_notes" class="col-sm-3 p-2"> <i class="fa fa-clipboard fa-lg" aria-hidden="true"></i> Notes: </label> <div class="col-sm-9 p-2"> <div class="d-flex flex-row"> <span> Notes only get saved if a contact is assigned the shift, and get removed when the contact is removed from the shift.</span> <div class=""> <%= f.label :notes %> <%= f.text_area :notes %> </div> </div> </div> </div> </section> </div> <div class="col-sm-4"> <!-- Contact Section--> <div id="contact_section"> <% if @assigned_contacts && @assigned_contacts.length > 0 %> <h2>Previously Assigned Contacts</h2> <% @assigned_contacts.each do |c| %> <%= label_tag "assigned_contacts[#{c.id}]", "Are you sure you want to remove the currently scheduled volunteer, #{c.display_name} (##{c.id}), from the assignment(s)?" %> <%= check_box_tag "assigned_contacts[#{c.id}]", "replace", @replaced_contacts.include?(c.id) %> <% end %> <% end %> <input id="contact_element_prefix" name="contact_element_prefix" type="hidden" value="contact"> <div class="name large flex-row"> <%= f.label :contact_id %><%= f.text_field :contact_id %> </div> <div id="display-contact" class="d-flex flex-row"> <% if f.object.contact_id %> <%= render partial: 'contacts/contact_display', locals: { contact:f.object.contact} %> <% else %> <div>no contact attatched- _form.html called</div> <%#= link_to 'Show Contact', contact_path(f.object.contact_id), remote: true %> <% end %> </div> <!-- FIXME: replace this logic stack with AJAX--> <%#= contact_field("@obj", "contact_id", :locals => {:options => { :object_name => f.object_name.to_s, :field_name => 'contact_id', :on_display => 'display_disciplinary_notes(); display_contact_notes();' }} ) %> <%= f.label :closed, "Is this slot closed?" %> <%= f.check_box :closed %> <!--Contact Section END--> <!--Attendance / Call Status start--> <% if f.object.id && f.object.contact_id %> <div class="flex-row"> <div class="col-25"><label for="assignment_attendance_type_id">Attendance:</label></div> <div class="col-75"><%= select(f.object_name, "attendance_type_id", AttendanceType.all.sort_by(&:id).collect {|p| [ p.name, p.id ] }, :include_blank => true) %></div> </div> <div class="flex-row"> <div class="col-25"><label for="assignment_call_status_type_id">Call status:</label></div> <div class="col-75"><%= select(f.object_name, "call_status_type_id", (["not called yet", ""] + CallStatusType.all.sort_by(&:id).collect {|p| [ p.name, p.id ] }), :include_blank => false) %></div> </div> <% end %> <!-- Attendance / Call Status End--> <!-- LOCK VERSION--> <div class="flex-row"> <div class="col-25"> <%= f.label :lock_version %> </div> <div class="col-75"> <%= f.number_field :lock_version %> </div> </div> <!-- LOCK end--> </div> </div> </div> <div class="modal-footer d-flex justify-content-between"> <div class="edit_icons d-flex flex-row"> <div class="d-flex flex-column"> <!-- <a href="/assignments/edit/<%#= skedj.current.id %>" title="split"><i class="fa fa-share-alt-square fa-lg" aria-hidden="true"></i> Split</a>--> <!-- <a href="/assignments/copy/<%#= skedj.current.id %>" title="copy"><i class="fa fa-files-o fa-lg" aria-hidden="true"></i> Copy</a>--> </div> <div class="d-flex flex-column"> <%#= link_to '<i class="fa fa-pencil-square-o fa-lg" aria-hidden="true"></i>Edit'.html_safe, edit_assignment_path, remote: true%> <!-- <a href="#" onclick="reassign(<%#= skedj.current.id %>); return false;" title="reassign"> <i class="fa fa-refresh fa-lg" aria-hidden="true"></i> Reassign</a>--> </div> </div> <div> <button type="button" class="btn btn-secondary mr-2" data-dismiss="modal">Close</button> <button type="button" class="btn btn-primary"><%= f.submit "Submit" %></button> <!-- <input id="assignment_submit" name="commit" type="submit" value="Update">--> </div> </div> </div> <% end %>
局部组件_volunteer_shift_fields代码
<!--<div class="name large flex-row">--> <%= vs.label :volunteer_shift %> <!--</div>--> <div id="volunteer_shift" class="d-flex flex-row"> <div class="col-sm-12 p-2"> <div id="volunteer_shift" class="text-right"> <div class="field"> <%= vs.label :volunteer_task_type_id %> <%= vs.select 'volunteer_task_type_id', options_from_collection_for_select([VolunteerTaskType.new(:description => ""), VolunteerTaskType.instantiables.effective_on(Date.today)].flatten, "id", "description") %> </div> <div class="field"> <%= vs.label :roster_id %> <%= vs.select 'roster_id', options_from_collection_for_select([Roster.new(:name => ""), Roster.all].flatten, "id", "name") %> </div> <div class="field"> <%= vs.label :program_id %> <%= vs.select 'program_id', options_from_collection_for_select([Program.new(:name => ""), Program.where(:volunteer => true)].flatten, "id", "name")%> </div> <div class="field"> <%= vs.label :set_description, "Description" %> <%= vs.text_area(:set_description) %> </div> <div class="field"> <%= vs.label :set_date, "Date" %> <%= vs.text_field(:set_date) %> </div> </div> </div> </div>
进度更新
调整局部组件后已经完成了90%的预期效果,剩余仅需要将其余表单元素在父子层级间移动即可完成全部调整,测试完成后会同步最终结果。
内容的提问来源于stack exchange,提问作者thefonso
相关产品推荐
相关产品推荐

