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' ) -%>
更新:已修复,感谢您指出 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' ) -%>