为浅路由调整 Rails 中的表格

Adjusting forms in Rails for shallow routing

我有模型的学生和清单,每个学生都有很多清单。我一直在尝试更改默认脚手架以使用浅层路由。我通过控制器根据操作设置清单和学生来修复,这似乎有效。但是我在 _form 部分遇到了问题,因为我不知道要更改什么 - 虽然我可以在嵌套路由的表单上找到内容,但对于浅层路由没有这样的帮助。

<%= form_with(model: [@student, checklist]) do |form| %>
  <% if checklist.errors.any? %>
    <div style="color: red">
      <h2><%= pluralize(checklist.errors.count, "error") %> prohibited this checklist from being saved:</h2>

      <ul>
        <% checklist.errors.each do |error| %>
          <li><%= error.full_message %></li>
        <% end %>
      </ul>
    </div>
  <% end %>

  <div>
    <%= form.label :title, style: "display: block" %>
    <%= form.text_field :title %>
  </div>

  <div>
    <%= form.label :date, style: "display: block" %>
    <%= form.date_field :date %>
  </div>

  <div>
    <%= form.label :setting, style: "display: block" %>
    <%= form.text_field :setting %>
  </div>

  <div>
    <%= form.submit %>
  </div>
<% end %>

您真的不需要做很多事情就可以让表单与嵌套路由一起工作。

当您使用 form_with 时,它会将参数传递给 polymorphic route helpers,这将在尝试找到相应的路线时压缩数组:

                                                 # method | path
form_with(model: [Foo.find(1), Bar.new])         # POST   | foo_bars_path(foo_id: 1)
form_with(model: [nil, Bar.new])                 # POST   | bars_path
form_with(model: [Foo.find(1), Bar.find(2)]) ->  # PATCH  | foo_bars_path(foo_id: 1, id: 2)
form_with(model: [nil, Bar.find(1)]) ->          # PATCH  | bar_path(1)

数组的最后一个元素被视为由表单生成器包装的实际对象。在处理浅嵌套时,您只需确保在更新记录时不传递父记录

您可以通过在局部中使用一个“本地”来做到这一点:

<%= form_with(model: model) %>

# new.html.erb 
<%= render partial: 'form', model: [@student, @checklist] %>

# edit.html.erb 
<%= render partial: 'form', model: @checklist %>

或者您可以使用 local_assigns 散列来访问本地而不会在没有传递本地时引发 NoMethodError:

<%= form_with(model: [local_assigns[:student], checklist]) %>

# new.html.erb 
<%= render partial: 'form', student: @student, checklist: @checklist %>

# edit.html.erb 
<%= render partial: 'form', checklist: @checklist %>

这是可行的,因为局部变量不是实际的局部变量 - 相反,传递的局部变量存储在散列中并且Rails通过元编程动态提供访问器。