[英]Missing required keys rails
I'm trying to create a form for task in my app.App has two entities: 我正在尝试为我的应用程序中的任务创建表单。应用程序有两个实体:
belongs_to
User 项目belongs_to
用户 belongs_to
Project 任务belongs_to
项目 But I get this error in my view when I'm trying to create this (pretty basic) form 但是,当我尝试创建此(相当基本的)表单时,出现了这个错误
No route matches {:action=>"index", :controller=>"tasks"} missing required keys: [:project_id]
Here is a part of my view with this form 这是我对此表格的看法的一部分
<div class="glyphicon glyphicon-plus col-xs-1 left_plus" ></div>
<div class="col-xs-10" >
<%= form_for [@project, @task],url: project_tasks_path do |f| %>
<%= f.input :body,class: 'form-control' %>
<%= f.submit 'Add task', class: 'btn' %>
<% end %>
And here is the project controller: 这是项目负责人:
class ProjectsController < ApplicationController
before_action :load_project, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!
def index
@projects = current_user.projects unless current_user.nil?
@task = Task.find_by(params[:project_id])
end
def show
@task = @project.tasks.build
end
def new
@project = current_user.projects.new
end
def edit
end
def create
@project = current_user.projects.create(project_params)
if @project.save
redirect_to root_path
else
render :new
end
end
def update
if @project.update(project_params)
redirect_to @project
else
render :edit
end
end
def destroy
@project.destroy
redirect_to projects_path
end
private
def load_project
@project = Project.find(params[:id])
end
def project_params
params.require(:project).permit(:name, :user_id)
end
end
And the tasks controller: 和任务控制器:
class TasksController < ApplicationController
before_action :set_task, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!
def index
@tasks = Task.where(project_id: project_id)
end
def show
project = Project.find_by(id: params[:project_id])
@task = Task.new(project: project)
end
def new
project = Project.find_by(id: params[:project_id])
@task = Task.new(project: project)
end
def edit
project = Project.find_by(id: params[:project_id])
@task = Task.new(project: project)
end
def references
respond_to do |format|
if @task.valid?
format.html { redirect_to root_url }
format.json { render :show, status: :created, location: @task }
else
format.html { render :home_url }
format.json { render json: @task.errors, status: :unprocessable_entity }
end
end
end
def create
@project = Project.find_by(id: params[:project_id])
@task = @project.tasks.create(task_params)
respond_to do |format|
if @task.valid?
format.html { redirect_to root_url }
format.json { render :show, status: :created, location: @task }
else
format.html { render :home_url }
format.json { render json: @task.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if @task.update(task_params)
format.html { redirect_to root_url }
format.json { render :home_url, status: :ok, location: @task }
else
format.html { render :root_url }
format.json { render json: @task.errors, status: :unprocessable_entity }
end
end
end
def edit
end
def destroy
@task.destroy
respond_to do |format|
format.html { redirect_to root_url }
format.json { head :no_content }
end
end
private
def set_task
@task = Task.find(params[:id])
end
def task_params
params.require(:task).permit(:deadline, :body, :project_id)
end
end
The routes file: 路由文件:
devise_for :users, :controllers => { :omniauth_callbacks => "callbacks" }
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
root 'projects#index'
resources :projects do
resources :tasks
end
And my routes: 而我的路线:
projects#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
Can somebody please help me to clarify where is the problem and what is the problem? 有人可以帮我弄清楚问题出在哪里,问题出在哪里?
The problem is with your TasksController#index
action. 问题出在您的TasksController#index
操作上。 What is project_id
there? 那里的project_id
是什么? For accessing a project's tasks, the project needs to exist in the first place. 为了访问项目的任务,该项目首先需要存在。 And not just that. 不仅如此。 To access any CRUD action on tasks, a project has to exist first. 要访问对任务的任何CRUD操作,必须首先存在一个项目。
Modify your TasksController as 将您的TasksController修改为
class TasksController < ApplicationController
before_action :set_project
before_action :set_task, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!
def index
@tasks = @project.tasks
end
def show
#makes use of set_task
end
def new
@task = @project.tasks.new
end
def edit
end
def references
respond_to do |format|
if @task.valid?
format.html { redirect_to root_url }
format.json { render :show, status: :created, location: @task }
else
format.html { render :home_url }
format.json { render json: @task.errors, status: :unprocessable_entity }
end
end
end
def create
@task = @project.tasks.create(task_params)
respond_to do |format|
if @task.valid?
format.html { redirect_to root_url }
format.json { render :show, status: :created, location: @task }
else
format.html { render :home_url }
format.json { render json: @task.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if @task.update(task_params)
format.html { redirect_to root_url }
format.json { render :home_url, status: :ok, location: @task }
else
format.html { render :root_url }
format.json { render json: @task.errors, status: :unprocessable_entity }
end
end
end
def destroy
@task.destroy
respond_to do |format|
format.html { redirect_to root_url }
format.json { head :no_content }
end
end
private
def set_project
@project = current_user.projects.find(params[:project_id]
end
def set_task
@task = @project.tasks.find(params[:id])
end
def task_params
params.require(:task).permit(:deadline, :body, :project_id)
end
end
Since we have defined a before_action
set_project, @project
will be available to all methods. 由于我们定义了before_action
set_project,因此@project
将对所有方法可用。 Note that set_project
finds the project from the projects created by the current user. 请注意, set_project
从当前用户创建的项目中查找项目。
In the ProjectsController#index, you won't actually get a value for params[:project_id]
. 在ProjectsController#index中,实际上不会获得params[:project_id]
。 Modify your index action to 修改索引操作为
def index
@projects = current_user.projects unless current_user.nil?
end
And I don't understand your show
method. 而且我不了解您的show
方法。 The build
method is actually used to create a in-memory representation of an object. build
方法实际上用于创建对象的内存表示。 The show
method of projects_controller can be used to display the project along with its tasks. projects_controller的show
方法可用于显示项目及其任务。 If this is what you need, change you show
action in ProjectsController
to 如果这是您需要的,请将您在ProjectsController
中的show
操作更改为
def show
#@project is available from load_project
@tasks = @project.tasks
end
You could also modify your load_project
project as 您也可以将load_project
项目修改为
def load_project
begin
@project = Project.find(params[:id]) #raises an exception if project not found
rescue ActiveRecord::RecordNotFound
redirect_to projects_path
end
end
To know more about rescuing exceptions, see Begin, Rescue and Ensure in Ruby? 要了解有关抢救异常的更多信息,请参见在Ruby中开始,抢救和确保?
For more, see http://blog.8thcolor.com/en/2011/08/nested-resources-with-independent-views-in-ruby-on-rails/ 有关更多信息,请参见http://blog.8thcolor.com/en/2011/08/nested-resources-with-independent-views-in-ruby-on-rails/
The problem is with the url for submitting the form. 问题在于提交表单的网址。 If you check your rake routes
you'd see that all your task routes would be nested under projects, therefore in passing the url option, you should have something like: 如果检查rake routes
您会看到所有任务路径都将嵌套在项目下,因此在传递url选项时,您应具有以下内容:
<div class="glyphicon glyphicon-plus col-xs-1 left_plus" ></div>
<div class="col-xs-10" >
<%= form_for [@project, @task],url: project_tasks_path(@project) do |f| %>
<%= f.input :body,class: 'form-control' %>
<%= f.submit 'Add task', class: 'btn' %>
<% end %>
or even better, I think you should be able to do that without passing the url option: 甚至更好,我认为您应该能够做到这一点而无需通过url选项:
<div class="glyphicon glyphicon-plus col-xs-1 left_plus" ></div>
<div class="col-xs-10" >
<%= form_for [@project, @task] do |f| %>
<%= f.input :body,class: 'form-control' %>
<%= f.submit 'Add task', class: 'btn' %>
<% end %>
UPDATE 更新
def index
project = Project.find(params[:project_id])
@projects = ProjectsViewPresenter.new(project)
end
# presenters/projects_view_presenter.rb
class ProjectsViewPresenter
attr_reader :project
def initialize(project)
@project = project
end
def tasks
@tasks ||= project.tasks
end
def task
@task ||= tasks.new
end
end
Your form_for would now be like this: 您的form_for现在将如下所示:
<div class="glyphicon glyphicon-plus col-xs-1 left_plus" ></div>
<div class="col-xs-10" >
<%= form_for [@project.project, @project.task] do |f| %>
<%= f.input :body,class: 'form-control' %>
<%= f.submit 'Add task', class: 'btn' %>
<% end %>
If the form to create a new task is in projects/index.html.erb you should make a @task variable available to the view; 如果用于创建新任务的表单位于projects / index.html.erb中,则应为视图提供@task变量; try to change the index action as follow: 尝试更改索引操作,如下所示:
def index
@projects = current_user.projects unless current_user.nil?
@task = Task.new
end
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.