在rails中编辑关联资源;如何通过id查找对象?

时间:2017-07-09 18:56:20

标签: ruby-on-rails ruby-on-rails-5

1)当我使用链接"编辑"在edit.html.erb中,其字段由第一个对象(task)的属性填充。好像我使用方法.first而不是方法.find(id)。 但是我需要编辑一个合适的对象,而不是第一个对象。

我试图改变TasksController:

@project = Project.find(params[:project_id])
@task = @project.tasks.find_by(project_id: params[:id])

以这种方式:

@project = Project.find(params[:project_id])
@task = Task.find(params[:id])

并收到:

  在TasksController中编辑ActiveRecord :: RecordNotFound #edit(无法找到   带有' id')的任务

当我尝试更改<%= form_for [@project, @task] do |f| %>上的<%= form_for @task do |f| %>时,我收到了:

  

任务编辑中的NoMethodError(未定义方法`task_path&#39;)

然后我尝试更改show.html.erb中的链接:

2)如果我按下按钮&#34;更新任务&#34;我收到:

  

TasksController#update中的NoMethodError(未定义方法`update&#39; for   零:NilClass)

in string:

@task.update(task_params)

对象路径定义中的错误是什么?

来源:

TasksController

class TasksController < ApplicationController

def edit
    @project = Project.find(params[:project_id])
    @task = @project.tasks.find_by(project_id: params[:id])
end

def create
    @project = Project.find(params[:project_id])
    @task = @project.tasks.create(task_params)
    redirect_to project_path(@project)
end

def update
    @project = Project.find(params[:project_id])
    @task = @project.tasks.find_by(project_id: params[:id])

    @task.update(task_params)
    redirect_to project_path(@project)
end

def destroy
    @project = Project.find(params[:project_id])
    @task = @project.tasks.find(params[:id])
    @task.destroy
    redirect_to project_path(@project)
end

private
def task_params
    params.require(:task).permit(:title, :description, :status)
end

end

edit.html.erb

<h2>Add a task:</h2>

<%= form_for  [@project, @task] do |f| %>

  <p>
    <%= f.label :title %><br>
    <%= f.text_field :title %>
  </p>
  ...
  <p>
    <%= f.submit %>
  </p>
<% end %>

的routes.rb

Rails.application.routes.draw do
  get 'welcome/index'

  resources :projects do
    resources :tasks
  end

  root 'welcome#index'
end

项目/ show.html.erb

...
  <p>
    <%= link_to 'Destroy task', [task.project, task],
                method: :delete,
                data: { confirm: 'Are you sure?' } %>
                 |
    <%= link_to 'Edit', edit_project_task_path(@project) %> 
  </p>

...

路由

    welcome_index GET    /welcome/index(.:format)                       welcome#index
    project_tasks GET    /projects/:project_id/tasks(.:format)          tasks#index
                  POST   /projects/:project_id/tasks(.:format)          tasks#create
 new_project_task GET    /projects/:project_id/tasks/new(.:format)      tasks#new
edit_project_task GET    /projects/:project_id/tasks/:id/edit(.:format) tasks#edit
     project_task GET    /projects/:project_id/tasks/:id(.:format)      tasks#show
                  PATCH  /projects/:project_id/tasks/:id(.:format)      tasks#update
                  PUT    /projects/:project_id/tasks/:id(.:format)      tasks#update
                  DELETE /projects/:project_id/tasks/:id(.:format)      tasks#destroy
         projects GET    /projects(.:format)                            projects#index
                  POST   /projects(.:format)                            projects#create
      new_project GET    /projects/new(.:format)                        projects#new
     edit_project GET    /projects/:id/edit(.:format)                   projects#edit
          project GET    /projects/:id(.:format)                        projects#show
                  PATCH  /projects/:id(.:format)                        projects#update
                  PUT    /projects/:id(.:format)                        projects#update
                  DELETE /projects/:id(.:format)                        projects#destroy
             root GET    /                                              welcome#index

提前谢谢。

重复ru.stackoverflow: https://ru.stackoverflow.com/q/690120/219253

1 个答案:

答案 0 :(得分:0)

我们使用一种非常具体的方式来处理属于Rails中另一个模型的模型。这需要了解表单,控制器,模型和视图如何在rails中工作。

你在rails中有这个声明:

resources :projects do
    resources :tasks
end

此代码表示资源task属于资源project。换句话说,所有任务都有一个关联的项目,当您与tasks进行交互时,URI前面总是有一个/projects/:project_id。由此产生的路径结构在您的问题中。

话虽如此,在您的tasks控制器中,获得与您合作的Project的正确方法是:

@project = Project.find(params[:project_id])

而且,如果您正在修改或访问现有的Task对象(:edit, :update, :destroy, :show),则访问Task对象的方法是:

@task = Task.find(params[:id])

现在,编写表单的正确方法是:

<%= form_for [@project, @task] do |f| %>

这告诉表单您正在修改/创建属于@task的{​​{1}}。根据您是创建还是修改@projectTask方法会呈现与不同控制器方法交互的表单。

您收到了form_form,因为您更改了将表单从正确的方式编码为错误的方式(不指定任务所属的项目)。

您可能收到了NoMethodError in Tasks#edit,因为您以错误的方式访问了该任务,因此拥有NoMethodError in TasksController#update for nil:NilClass nil

希望这有帮助!

来自@Yaraslau Khamenka的编辑7/12/2017

此外,您需要在@task中提供与您正在编辑的任务相关联的项目:

link_to