我尝试在app中创建任务表单.App有两个实体:
y[i] = x
IndexError: list assignment index out of range
用户belongs_to
项目但是当我试图创建这个(非常基本的)表单时,我在我看来会出现这个错误
belongs_to
以下是我使用此表单的视图的一部分
No route matches {:action=>"index", :controller=>"tasks"} missing required keys: [:project_id]
这是项目控制器:
<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 %>
任务控制器:
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
路线档案:
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
我的路线:
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
有人可以帮我澄清问题出在哪里,问题是什么?
答案 0 :(得分:1)
问题在于您的TasksController#index
操作。什么是project_id
?为了访问项目的任务,项目首先需要存在。而不只是那个。要访问任务上的任何CRUD操作,必须首先存在项目。
将您的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
由于我们已经定义了before_action
set_project,因此@project
可用于所有方法。请注意,set_project
从当前用户创建的项目中查找项目。
在ProjectsController#index中,您实际上不会获得params[:project_id]
的值。将索引操作修改为
def index
@projects = current_user.projects unless current_user.nil?
end
我不理解你的show
方法。 build
方法实际上用于创建对象的内存中表示。 projects_controller的show
方法可用于显示项目及其任务。如果这是您所需要的,请将show
中的ProjectsController
操作更改为
def show
#@project is available from load_project
@tasks = @project.tasks
end
您还可以将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
要了解有关拯救例外的更多信息,请参阅Begin, Rescue and Ensure in Ruby?
有关详情,请参阅http://blog.8thcolor.com/en/2011/08/nested-resources-with-independent-views-in-ruby-on-rails/
答案 1 :(得分:0)
问题在于提交表单的网址。如果您检查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 %>
甚至更好,我认为你应该能够在不传递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 %>
<强>更新强>
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
您的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 %>
答案 2 :(得分:0)
如果要在projects / index.html.erb中创建新任务的表单,则应该为视图提供一个@task变量;尝试更改索引操作如下:
def index
@projects = current_user.projects unless current_user.nil?
@task = Task.new
end