Rails 表单字段将旧数据传递给白名单参数

Rails form fields passing old data to whitelisted params

更新:已修复,感谢您指出 kjmagic13。您可以在下面查看解决方案。

所以我从昨天开始就一直在研究这个。我有一个 Rails 项目,其中 form_for 收集客户数据,如姓名、年龄等。有一个 "Add spouse?" 按钮,它使用 javascript 显示其他配偶输入字段。所有这些属性都被列入白名单,配偶数据实际上只是客户端模型上的属性(没有配偶对象)。

您第一次向这些字段输入数据时,它们都顺利通过并被保存。然后,当您重新访问该页面时,表单会预先填充该数据。您可以编辑字段并更新客户信息,但不能更新配偶字段 --> 即使这些字段已列入白名单并且只不过是客户属性。我什至无法想象我是如何故意让这一切发生的,更不用说想出如何解决它了。

表单已提交,传入的参数始终是旧的配偶数据,而不是输入字段中的内容。但是,所有新客户信息都以相同的形式更新。查看日志总是显示旧的配偶数据正在传递,好像我从未输入过任何内容

这是相关的片段:

在clients_controller

def update
  if @client.report_ready?
    outdate_report
  end

  respond_to do |format|
    if @client.update(client_params)
      format.html { redirect_to @client, notice: 'Client was successfully updated.' }
      format.json { render :show, status: :ok, location: @client }
    else
      format.html { render :show }
      format.json { render json: @client.errors, status: :unprocessable_entity }
    end
  end
end

def client_params
  params.require(:client).permit(:first_name, :last_name, :email, :dob, :address, :city, :state, :zip, :phone, :retire_age, :ss_age, :user_id, :spouse_dob, :spouse_retire_age, :spouse_ss_age, :spouse_first_name, :spouse_last_name)
end

# the form in the view
<%= form_for (@client) do |f| %>
<% if @client.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@client.errors.count, "error") %> prohibited this plan from being saved:</h2>
      <ul>
      <% @client.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div>
    <div>
      <%= f.label :first_name, class: 'left' %><br>
      <%= f.text_field :first_name %>
    </div>
    <div>
      <%= f.label :last_name, class: 'left' %><br>
      <%= f.text_field :last_name %>
    </div>
    <div>
      <%= f.label :email, class: 'left' %><br>
      <%= f.email_field :email %>
    </div>
    <div>
      <%= f.label :phone, class: 'left' %><br>
      <%= f.phone_field :phone %>
    </div>
    <div>
      <%= f.label :dob, 'Birthdate', class: 'left' %>
      <%= f.date_field :dob, style: "font-size: .9em;" %>
    </div>
    <div>
      <% if @client.dob.present? %>
        <%= f.label :age, class: 'left' %><br>
        <%= text_field_tag :age, @client.age, readonly: true %>
      <% else %>
        <%= hidden_field :age, value: nil %>
      <% end %>
    </div>
    <div>
      <%= f.label :retire_age, 'Ret. age', class: 'left' %><br>
      <%= f.number_field :retire_age %>
    </div>
    <div>
      <%= f.label :ss_age, 'S.S. age', class: 'left' %><br>
      <%= f.number_field :ss_age %>
    </div>
    <div>
      <%= f.submit "Save", class: "button radius tiny" %>  
    </div>

    <% if !@client.new_record? && @client.has_spouse? %>
      <%= render 'spouse_fields', f: f  %>
    <% else %>
      <%= render 'spouse_button' %>
    <% end %>

    <span id="spouse_fields" style="display:none">
      <%= render 'spouse_fields', f: f %>
    </span>

# the spouse fields (which are really just a continuation of the form)
<hr>
<h1>Spouse Information</h1>
<div>
  <%= f.label :spouse_first_name, 'First name', class: 'left' %><br>
  <%= f.text_field :spouse_first_name %>
</div>
<div>
  <%= f.label :spouse_last_name, 'Last name', class: 'left' %><br>
  <%= f.text_field :spouse_last_name %>
</div>
<div>
  <%= f.label :spouse_dob, 'Date of Birth', class: 'left' %><br>
  <%= f.date_field :spouse_dob, style: "font-size: .9em;" %>
</div>
<div>
  <% if @client.spouse_dob.present? %>
    <%= f.label :spouse_age, 'Age', class: 'left' %><br>
    <%= text_field_tag :spouse_age, @client.spouse_age, readonly: true%>
  <% else %>
    <%= hidden_field :spouse_age, value: nil %>
  <% end %>
</div>
<div>
  <%= f.label :spouse_retire_age, 'Ret. age', class: 'left' %><br>
  <%= f.number_field :spouse_retire_age %>
</div>
<div>
  <%= f.label :spouse_ss_age, 'S.S. age', class: 'left' %><br>
  <%= f.number_field :spouse_ss_age %>
</div>
<div>
  <%= f.submit "Save", class: "button radius tiny" %>  
</div>

# the js for the 'Add spouse button' (just reveals fields, then disappears)
<text id="spouse_button" onclick="toggleFields()">
  Add Spouse?
</text>

<script>
  function toggleFields() {
    document.getElementById("spouse_fields").style.cssText = "";
    document.getElementById("spouse_button").style.cssText = "display:none";
  };
</script>

修复:

我只错过了隐藏的额外配偶字段的位置。它们需要移动到它上面的 if/else 块中,像这样(但是 kjmagic13 的 2 行解决方案显然更好):

<% if !@client.new_record? && @client.has_spouse? %>
  <%= render 'spouse_fields', f: f  %>
<% else %>
  <%= render 'spouse_button' %>

  <span id="spouse_fields" style="display:none">
    <%= render 'spouse_fields', f: f %>
  </span>
<% end %>

您在编辑记录时复制了 spouse_fields 部分。将有两个 ID 为 spouse_fields 的元素,而 Javascript 只会切换它遇到的第一个元素。另一个将保持隐藏状态,很可能是传递给服务器的字段。

<% if !@client.new_record? && @client.has_spouse? %>
    <%= render 'spouse_fields', f: f # renders here on edit  %>
<% else %>
    <%= render 'spouse_button' %>
<% end %>

<span id="spouse_fields" style="display:none">
    <%= render 'spouse_fields', f: f # and renders here on edit %>
</span>

你会想要更多类似这样的东西:

<%= render 'spouse_button' unless @client.has_spouse? %>
<%= content_tag :span, render('spouse_fields', f: f), style: ( @client.has_spouse? ? nil : 'display:none' ) -%>