【问题标题】:Using form_for with Nested Resources将 form_for 与嵌套资源一起使用
【发布时间】:2017-01-24 10:24:50
【问题描述】:

我正在构建一个 To Do 应用程序以尝试熟练使用 Rails。我的应用程序中有四个层次结构。

  1. 用户
  2. 目标(每位用户有多个目标)
  3. 任务(每个目标多个任务)
  4. 子任务(每个任务多个子任务)

我为每个使用嵌套资源的前端表单提供了工作。我的 routes.rb 有这样的东西

 resources :goal do
  resources :task do
    resources :subtask
  end
 end

我现在想做的是将所有这些表单都放在用户控制器的一个视图中。

这是我尝试创建的表单:

<%= form_for @task, url: {controller: 'task', action: 'create'} do |f| %>

 <%= f.label :description %>

 <%= f.text_field :description %>

 <%= f.submit "Add Goal", class: "btn" %>

<% end %>

但我最终得到了这个错误

No route matches {:action=>"create", :controller=>"task", :id=>"1"}

:id=>1 对应于我所在的用户页面 (http://localhost:3000/user/1)

我的理解是,我没有在任何地方提供此步骤所针对的目标 ID。不知道如何实现这一点。

我注意到的另一件事是,对rake routes 的响应显示了很多 URI 路径,但 POST 方法却没有。它不允许我在url: 中使用form_for 中的路径,因为它与POST 方法不匹配。

所以我的问题是:

  1. 当您有嵌套资源时,如何路由表单?
  2. 如何在使用 form_for 时提供父资源的 ID,以便正确路由我的创建操作?

【问题讨论】:

  • 这可能会给你一些想法:stackoverflow.com/questions/2034700/…
  • 做一个 rake 路由并检查创建任务路由。用户 ID 可能未指示为 :id。
  • 不,我有 /goal/:goal_id/task 作为创建任务路线。是的,这条路线中没有 :id,我仍然需要在某处提供 :goal_id 并且我不知道该怎么做(正如我在问题中提到的那样)。

标签: ruby-on-rails forms ruby-on-rails-4 model-view-controller url-routing


【解决方案1】:

嵌套深度超过两层的路由通常是不好的做法。我会将您的路线更改为:

  resources :goal do
    resources :task 
  end

  resources :task do
      resources :subtask
  end

现在,如果您在命令行中运行“bundle exec rake routes”,您将看到所有嵌套路由及其对应的助手。您当前的问题在于 form_for 方法。您需要添加其嵌套的资源,在这种情况下应该是:

<%= form_for [@goal,@task] do |f| %>
    blah blah
<% end %>

最后,@goal 也仍未定义,因此您需要在任务控制器的“新”操作中定义它。这通常是通过传递与您的任务相关联的目标的 id 来完成的,该目标将通过 params 哈希和用于获取“新”表单的“link_to”。然后在任务控制器的新操作中:

@goal = Goal.find(params[:goal_id]) #The parameter can be named anything
@task = Task.new

然后在您的“创建”操作中,您应该建立关联:

@task = Goal.tasks.new(task_params)
if @task.save
   flash[:success] = "Woot" 
   redirect_to somewhere_awesome_path
else
  whatever
end

【讨论】:

  • 使用form_for [@goal,@task]给我错误undefined method goal_tasks_path for #&lt;#&lt;Class:..... 我真正难以理解的是目标ID是如何通过参数has和link_to传递到表单中的,正如你所建议的。此外,此表单不在与任务控制器或目标控制器关联的视图中,它实际上在与用户控制器关联的 show.html.erb 中。表单如何知道寻找另一个控制器而不是用户?
  • 感谢您的回复,这是一个很好的答案。只是需要你多一点帮助:)
  • 没问题。您想在连接到显示表单的操作中定义“@goal”和“@task”,因此在这种情况下,您可以在“显示”操作内的用户控制器中定义它们。然后,您还可以像使用“url:{controller:'task',action:'create'}”部分一样定义表单将提交到的路径。至于传递goal_id,您可以将其添加为带有预设值的表单内的隐藏字段。例如
猜你喜欢
  • 2012-10-22
  • 1970-01-01
  • 2011-01-16
  • 2011-01-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多