表单字段被拒绝,我不知道为啥

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

【讨论】:

以上是关于表单字段被拒绝,我不知道为啥的主要内容,如果未能解决你的问题,请参考以下文章

我的应用在 App Store 被拒绝,但我不明白为啥

***Error,我不知道为啥

我的可滚动 ui 堆栈视图中有空格,我不知道为啥

如果 $_POST 值仍然相同,PHP 表单将拒绝发送

使用 jQuery 提交表单并使用 PHP 发送.. 不知道为啥它不发送

我不知道为啥会发生错误[重复]