
当 rails 表单中存在多个 name="motivo" 的输入框时,浏览器仅提交最后一个同名字段的值(或空值),导致控制器收不到预期参数——根本原因在于 html 表单规范要求 name 属性唯一性,而非 simpleform 或 rails 本身缺陷。
当 rails 表单中存在多个 name="motivo" 的输入框时,浏览器仅提交最后一个同名字段的值(或空值),导致控制器收不到预期参数——根本原因在于 html 表单规范要求 name 属性唯一性,而非 simpleform 或 rails 本身缺陷。
在你的表单中,两个 <div> 内分别定义了:
<%= f.input :motivo, input_html: { id: 'motivo_tomadas' }, label: 'Motivo de los días tomados' %>
<%= f.input :motivo, input_html: { id: 'motivo_abonadas' }, label: 'Motivo de los días abonados' %>尽管你为它们设置了不同的 id(用于 DOM 定位和 JS 控制),但 SimpleForm 默认为同一模型属性生成相同的 name="vacacion[motivo]"。浏览器提交表单时,后出现的同名字段会覆盖先出现的值,最终控制器收到的 params[:vacacion][:motivo] 总是来自最后渲染的那个 <input>(可能为空或非预期值)。
✅ 正确解决方案:为不同场景的 motivo 字段使用独立的模型属性或显式指定唯一 name
方案一:扩展模型,添加专用字段(推荐)
在 Vacacion 模型中添加两个独立属性(需迁移):
rails generate migration AddMotivoTomadasAndMotivoAbonadasToVacacions motivo_tomadas:text motivo_abonadas:text rails db:migrate
更新表单,分别绑定不同字段:
<div id="id1" style="display:none">
<%= f.input :desde, label: 'Fecha inicio vacaciones', as: :datepicker, ... %>
<%= f.input :hasta, label: 'Fecha fin vacaciones', as: :datepicker, ... %>
<%= f.input :dias_tomados, label: 'Días de vacaciones utilizados', ... %>
<%= f.input :motivo_tomadas, label: 'Motivo de los días tomados', input_html: { id: 'motivo_tomadas' } %>
</div>
<div id="id2" style="display:none">
<%= f.input :dias_abonados, label: 'Días de vacaciones a abonar', ... %>
<%= f.input :motivo_abonadas, label: 'Motivo de los días abonados', input_html: { id: 'motivo_abonadas' } %>
</div>控制器中按需处理:
# app/controllers/vacacions_controller.rb
def create
if params[:vacacion][:tipo] == "tomadas"
@vacacion.motivo = params[:vacacion][:motivo_tomadas]
elsif params[:vacacion][:tipo] == "abonadas"
@vacacion.motivo = params[:vacacion][:motivo_abonadas]
end
# ... save logic
end方案二:手动指定 name(无需迁移,但需手动处理参数)
若暂无法修改模型,可绕过 SimpleForm 的自动绑定,用原生 input 并自定义 name:
<div id="id1" style="display:none">
<%= f.input :desde, ... %>
<!-- 其他字段 -->
<%= content_tag :div, class: "form-group" do %>
<%= content_tag :label, "Motivo de los días tomados", class: "control-label" %>
<%= text_field_tag "vacacion[motivo_tomadas]", @vacacion.motivo_tomadas,
class: "form-control", id: "motivo_tomadas" %>
<% end %>
</div>
<div id="id2" style="display:none">
<%= f.input :dias_abonados, ... %>
<%= content_tag :div, class: "form-group" do %>
<%= content_tag :label, "Motivo de los días abonados", class: "control-label" %>
<%= text_field_tag "vacacion[motivo_abonadas]", @vacacion.motivo_abonadas,
class: "form-control", id: "motivo_abonadas" %>
<% end %>
</div>并在控制器中统一赋值:
def vacacion_params
params.require(:vacacion).permit(
:tipo, :desde, :hasta, :dias_tomados, :dias_abonados,
:motivo_tomadas, :motivo_abonadas
).tap do |whitelisted|
tipo = whitelisted[:tipo]
whitelisted[:motivo] =
tipo == "tomadas" ? whitelisted.delete(:motivo_tomadas) :
tipo == "abonadas" ? whitelisted.delete(:motivo_abonadas) : nil
end
end⚠️ 注意事项:
- 永远不要依赖 id 区分表单参数:id 仅用于 CSS/JS,name 才决定提交键名;
- JavaScript 显示/隐藏逻辑无需修改(你当前的 $("#vacacion_tipo").change(...) 已正确);
- 若使用方案二,务必在 Strong Parameters 中显式允许新字段;
- 浏览器开发者工具的 Network → Payload 标签页可直观验证最终提交的参数结构。
通过确保每个可提交字段拥有唯一 name,即可彻底解决参数被静默覆盖的问题——这是前端表单开发中的基础但关键原则。

















