【问题标题】:Separating year, month and day in rails forms以 Rails 形式分隔年、月和日
【发布时间】:2026-01-03 10:10:01
【问题描述】:

通常,为了在 Rails 中选择日期,我会这样写:

<%= form_for(:buddy, :url => {:action => :create}) do |f| %>
<%= f.date_select(:dob) %>
<%= f.submit("HI") %>
<% end %>

然后得到这个html作为结果:

<form action="/buddy/create" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="&#x2713;" /><input type="hidden" name="authenticity_token" value="Qs8RK+6gEt9ZoycMbMHwX4xMyoFpRvjA/El3cLnO30RXddr864WmEXzyAgYtXBe5Y9l0zC3UDw4ggRw1xYW1sg==" />
<select id="buddy_dob_1i" name="buddy[dob(1i)]">
<option value="2010">2010</option>
<!-- ETC -->
<select id="buddy_dob_2i" name="buddy[dob(2i)]">
<option value="1" selected="selected">January</option>
<!-- ETC -->
<select id="buddy_dob_3i" name="buddy[dob(3i)]">
<option value="1">1</option>
<!-- ETC -->
<input type="submit" name="commit" value="HI" />

但现在我正在使用引导程序。如果我使用 bootstrap_form_for gem,我会遇到一个问题,即在小屏幕上,三个选择会相互叠加,这是不可接受的。所以我想出了一个我认为很好的解决方案:将每个选择放在表的不同字段中,这可以防止这种行为。所以我写了这段代码:

  <%= form_for(:buddy, {:action => :create, :role => 'form'}) do |f| %>
  <div class="form-group">
    <label for="buddy_dob">Date of Birth</label>
    <table class="table functional-table">
      <tr>
        <td> 
          <%= select_year(Date.today, {:start_year => DateTime.now.year, :end_year => DateTime.now.year - 117}, {:name => 'buddy[dob(1i)]', :id => 'buddy_dob_1i', :class => 'form-control'}) %>
        </td>
        <td>
          <%= select_month(Date.today, {}, {:name => 'buddy[dob(2i)]', :id => 'buddy_dob_2i', :class => 'form-control'}) %>
        </td>
        <td>
          <%= select_day(1, {}, {:name => 'buddy[dob(3i)]', :id => 'buddy_dob_3i', :class => 'form-control'}) %>
        </td>
      </tr>
    </table>
  </div>
  <div class="form-group">
    <%= f.submit("HI") %>
  </div>

  <% end %>

产生这个结果:

<form role="form" action="/buddy/new" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="&#x2713;" /><input type="hidden" name="authenticity_token" value="6Ek01J6PIgzHl/NLpjI6V+kolUVCpw7jrQTF8eYT3ef98/8Dm6qWwuLG1kHnr92xBr0rCAY1+S1xzK60mli3EQ==" />
  <div class="form-group">
    <label for="buddy_dob">Date of Birth</label>
    <table class="table functional-table">
      <tr>
        <td> 
          <select id="buddy_dob_1i" name="buddy[dob(1i)]" class="form-control">
            <option value="2015" selected="selected">2015</option>
              <!-- ETC -->
        </td>
      </tr>
    </table>
    <table class="table functional-table">
      <tr>
        <td>
          <select id="buddy_dob_2i" name="buddy[dob(2i)]" class="form-control">
          <option value="1" selected="selected">January</option>
          <!-- ETC -->
        </td>
      </tr>
    </table>
    <table class="table functional-table">
      <tr>
        <td>
          <select id="buddy_dob_3i" name="buddy[dob(3i)]" class="form-control">
          <option value="1" selected="selected">1</option>
          <!-- ETC -->
        </td>
      </tr>
    </table>
  <div class="form-group">
    <input type="submit" name="commit" value="HI" />
  </div>
</form>

这个显示完全按照我的意愿工作,但是当我尝试提交表单时,我被重定向到操作 :new,没有任何错误被 rails 注册,也没有创建条目。我从来没有达到:创建。我怀疑这可能是因为我手动分离了 date_select 分离的日期字段,然后重新组合在一起,rails 无法处理这个问题,但我不确定。如何解决此问题并让表单正常工作?

【问题讨论】:

    标签: ruby-on-rails twitter-bootstrap twitter-bootstrap-3 form-helpers


    【解决方案1】:

    您有嵌套表单 - 这是非法的!大多数浏览器会简单地忽略内部表单标签,因此您最终会得到一个呈现的 DOM 结构。外部形式没有指定 action 属性,因此浏览器会将当前路径作为操作附加,在本例中为 /buddy/new。我有点惊讶您在这里没有收到路由错误 - 您是否有机会使用 match /buddy/new 而不指定动词?

    无论如何 - 解决方案是摆脱周围的形式(具有角色的形式),而是将此角色附加到您的 form_for 呼叫:

    <%= form_for(:buddy, url: {action: :create}, html: {role: :form) do |f| %>
    

    【讨论】:

    • 糟糕。我在发布后立即发现了这个问题。感谢您的帮助!
    【解决方案2】:

    解决了!我刚刚将 form_for 更改为 form_tag ,它现在按预期工作。感谢 BroiSatse 提供有关 ActionDispatch 知道如何转换参数的信息;它鼓励我到别处寻找问题。

    【讨论】:

      【解决方案3】:

      您选择的名称不是“标准”名称。 buddy[dob(3i)] 不是有效名称。

      当查询发送到 Rails 时,第一个模块将所有接收到的名称更改为 params。在这里,它不能,而且失败了。

      你应该这样设置:buddy[dob_month]

      【讨论】:

      • 这些名称是rails处理复合数据的标准方式,它们在创建参数时由ActionDispatch正确处理,然后由assign_attributes方法将它们转换为日期或时间(取决于类型数据库中的列)
      最近更新 更多