表单字段被拒绝,我不知道为啥
Posted
技术标签:
【中文标题】表单字段被拒绝,我不知道为啥【英文标题】:Form field is being rejected and I can not figure out why表单字段被拒绝,我不知道为什么 【发布时间】:2021-12-24 00:51:27 【问题描述】:嗯,希望这个问题很清楚。
我有一个旧应用程序要移植到 Rails 5。
我有一个使用特殊方法“create_shift”来处理它的表单,它在下面指示的行中断(注意:create_shift 是我要移植的原始代码的一部分)...我已经包含了控制台错误尝试后的消息...
这是错误...
vs.attributes=(assignment_params) #fixme: if i try this line I get...
# ActiveModel::UnknownAttributeError: unknown attribute 'contact_id' for VolunteerShift.
# from /home/fonso/.rbenv/versions/2.5.8/lib/ruby/gems/2.5.0/gems/activemodel-5.0.7.2/lib/active_model/attribute_assignment.rb:48:in `_assign_attribute'
这是表格...
views/assignments/_form.html.erb(contact_id 靠近中间)
<%= form_for @assignment, :url => @my_url, remote: true do |f| %>
<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 -->
<!-- Set Date field has to be here not in the partial-->
<div class="field">
<%= f.label :set_date, "Date" %>
<%= f.text_area(:set_date) %>
</div>
<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 %> #<==============================================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 %>
这是该形式的部分
assignment/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>
</div>
</div>
volunteer_events_controller
class VolunteerEventsController < ApplicationController
before_action :set_volunteer_event, only: [:show, :edit, :update, :destroy]
...
def create_shift # FIXME: evil brought over from original code base
ve = nil
if !params["id"].blank?
ve = VolunteerEvent.find(params["id"])
else
if params["assignment"]["volunteer_shift_attributes"]["roster_id"].blank? || params["assignment"]["set_date"].blank?
ve = VolunteerEvent.new # won't save
else
ve = Roster.find_by_id(params["assignment"]["volunteer_shift_attributes"]["roster_id"]).vol_event_for_date(params["assignment"]["set_date"])
end
end
vs = ve.volunteer_shifts.new
vs.stuck_to_assignment = vs.not_numbered = true
binding.pry
vs.attributes=(assignment_params) #if i try this line I get...
# ActiveModel::UnknownAttributeError: unknown attribute 'contact_id' for VolunteerShift.
# from /home/fonso/.rbenv/versions/2.5.8/lib/ruby/gems/2.5.0/gems/activemodel-5.0.7.2/lib/active_model/attribute_assignment.rb:48:in `_assign_attribute'
binding.pry
...
end
...
private
# Use callbacks to share common setup or constraints between actions.
def set_volunteer_event
@volunteer_event = VolunteerEvent.find(params[:id])
end
# Only allow a list of trusted parameters through.
def assignment_params
params.require(:assignment).permit(:action, :controller, :title, :set_date, :date, :date_range, :volunteer_shift_id, :contact_id, :start_time, :end_time, :start, :end, :attendance_type_id, :notes, :call_status_type_id, :closed, :lock_version, :color, :description, :contact_element_prefix, :lock_versions, :commit, volunteer_shift_attributes: [:volunteer_task_type_id,:roster_id,:program_id,:set_description,:id, :destroy])
# params.require(:volunteer_event).permit(:description, :volunteer_default_event_id, :date, :notes, :nowalkins)
end
def volunteer_event_params
params.require(:volunteer_event).permit(:description, :volunteer_default_event_id, :date, :notes, :nowalkins)
end
end
这甚至是模型关联
class Assignment < ApplicationRecord
# attr_accessor :volunteer_event ,:contact_id #why is this here???
# attr_accessor :redirect_to
belongs_to :volunteer_shift
has_one :volunteer_task_type, :through => :volunteer_shift, :source => :volunteer_task_type
belongs_to :contact ,optional: true
validates_presence_of :volunteer_shift #belongs_to takes care of this now
validates_associated :volunteer_shift
belongs_to :attendance_type
belongs_to :call_status_type
validates_presence_of :set_date, :if => :volshift_stuck #belongs_to takes care of this now??
accepts_nested_attributes_for :volunteer_shift, allow_destroy: true #4 Nested form
delegate :set_date, :set_date=, :to => :volunteer_shift
delegate :set_description, :set_description=, :to => :volunteer_shift
...
end
class VolunteerEvent < ApplicationRecord
belongs_to :volunteer_default_event
validates_presence_of :date
has_many :volunteer_shifts, :dependent => :destroy
has_many :resources_volunteer_events, :dependent => :destroy
validates_associated :volunteer_shifts
...
end
class VolunteerShift < ApplicationRecord
validates_presence_of :roster_id
validates_presence_of :end_time
validates_presence_of :start_time
has_many :assignments
belongs_to :volunteer_default_shift
belongs_to :volunteer_task_type
belongs_to :roster
belongs_to :volunteer_event
belongs_to :program
has_many :contact_volunteer_task_type_counts, :primary_key => 'volunteer_task_type_id', :foreign_key => 'volunteer_task_type_id' #:through => :volunteer_task_type
...
end
我希望这不会太混乱。所以看起来代码在......
vs.attributes=(assignment_params) #fixme: if i try this line I get...
# ActiveModel::UnknownAttributeError: unknown attribute 'contact_id' for VolunteerShift.
# from /home/fonso/.rbenv/versions/2.5.8/lib/ruby/gems/2.5.0/gems/activemodel-5.0.7.2/lib/active_model/attribute_assignment.rb:48:in `_assign_attribute'
所以我想知道...如何让 contact_id 注册?
不确定这是否有帮助,但我会添加它。它接收的参数看起来像这样......
> [2] pry(#<VolunteerEventsController>)> params
> => <ActionController::Parameters "utf8"=>"✓", "assignment"=><ActionController::Parameters
> "volunteer_shift_attributes"=><ActionController::Parameters
> "volunteer_task_type_id"=>"41", "roster_id"=>"7", "program_id"=>"9",
> "set_description"=>"so sick of this database" permitted: false>,
> "set_date"=>"2021-01-11", "start_time(1i)"=>"2021",
> "start_time(2i)"=>"11", "start_time(3i)"=>"11",
> "start_time(4i)"=>"08", "start_time(5i)"=>"00",
> "end_time(1i)"=>"2021", "end_time(2i)"=>"11", "end_time(3i)"=>"11",
> "end_time(4i)"=>"09", "end_time(5i)"=>"00", "notes"=>"Fonso in Matrix
> Nov", "contact_id"=>"166574", "closed"=>"0", "lock_version"=>"0"
> permitted: false>, "contact_element_prefix"=>"contact",
> "commit"=>"Submit", "controller"=>"volunteer_events",
> "action"=>"create_shift" permitted: false> [3]
> pry(#<VolunteerEventsController>)>
较旧的应用程序没有 strong_params,因此这不是问题。但我怀疑旧应用中的 contact_id 周围有一些奇怪的编码。
我该怎么做才能让这条线与contact_id一起工作......
vs.attributes=(assignment_params)
...或者至少是预期的结果?
是否应该将某种用于contact_id 的attr_accessor 放置在volunteer_shift 模型中或更高级别?
我可以使用一些奇怪的 hack 或 rails 魔法吗?大声笑,这听起来很疯狂,但我怀疑这可能是旧应用程序所做的。
如果我需要在这篇文章中添加任何内容,例如模型关联、视图或其他任何内容,请告诉我,我很乐意提供帮助。
感谢您的宝贵时间。
更新:
现在,如果我像这样重写 params 方法...
def volunteer_event_params
> params.require(:volunteer_event).permit(:action, :controller, :title, :set_date, :date, :date_range, :volunteer_shift_id,
> :contact_id, :start_time, :end_time, :start, :end,
> :attendance_type_id, :notes, :call_status_type_id, :closed,
> :lock_version, :color, :description, :contact_element_prefix,
> :lock_versions, :commit, volunteer_shift_attributes:
> [:volunteer_task_type_id,:roster_id,:program_id,:set_description,:id,
> :destroy])
end
我收到此错误
ActionController::ParameterMissing - param is missing or the value is empty: volunteer_event:
用 Pry 挖掘,我知道我得到了这些参数...
> [1] pry(#<VolunteerEventsController>)> params
> => <ActionController::Parameters "utf8"=>"✓", "assignment"=><ActionController::Parameters
> "volunteer_shift_attributes"=><ActionController::Parameters
> "volunteer_task_type_id"=>"41", "roster_id"=>"7", "program_id"=>"9",
> "set_description"=>"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" permitted:
> false>, "set_date"=>"2021-01-11", "start_time(1i)"=>"2021",
> "start_time(2i)"=>"11", "start_time(3i)"=>"11",
> "start_time(4i)"=>"08", "start_time(5i)"=>"00",
> "end_time(1i)"=>"2021", "end_time(2i)"=>"11", "end_time(3i)"=>"11",
> "end_time(4i)"=>"09", "end_time(5i)"=>"00",
> "notes"=>"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
> "contact_id"=>"166574", "closed"=>"0", "lock_version"=>"0" permitted:
> false>, "contact_element_prefix"=>"contact", "commit"=>"Submit",
> "controller"=>"volunteer_events", "action"=>"create_shift" permitted:
> false> [2] pry(#<VolunteerEventsController>)>
【问题讨论】:
【参考方案1】:所以要在这种情况下“修复”这个问题(通过将代码移植到 Rails 5.0 应用程序来升级旧的 Rails 2.x 应用程序)
强参数轮换:
config.action_controller.permit_all_parameters = true
在此处了解更多信息...https://guides.rubyonrails.org/v5.0/configuring.html
【讨论】:
以上是关于表单字段被拒绝,我不知道为啥的主要内容,如果未能解决你的问题,请参考以下文章