Rails嵌套资源自定义方法不起作用?

时间:2016-09-26 08:01:22

标签: ruby-on-rails devise nested

我想要取消"取消"用户项目的方法,它不是删除记录,而是将状态更新为"取消",存储取消前的最后状态,并记录用户的原因(输入)。

我有用户(设计)的控制器和嵌套的项目。 RESTful动作似乎一切正常,但是取消选项并没有,我无法弄明白!

这是我的routes.rb

 devise_for :users

 resources :users do
  resources :projects do
    get "cancel" => 'projects#cancel'
    post "cancel" => 'projects#cancel_save'
  end
end

当我运行rake routes

             user_project_cancel GET    /users/:user_id/projects/:project_id/cancel(.:format) projects#cancel
                                 POST   /users/:user_id/projects/:project_id/cancel(.:format) projects#cancel_save
                   user_projects GET    /users/:user_id/projects(.:format)                    projects#index
                                 POST   /users/:user_id/projects(.:format)                    projects#create
                new_user_project GET    /users/:user_id/projects/new(.:format)                projects#new
               edit_user_project GET    /users/:user_id/projects/:id/edit(.:format)           projects#edit
                    user_project GET    /users/:user_id/projects/:id(.:format)                projects#show
                                 PATCH  /users/:user_id/projects/:id(.:format)                projects#update
                                 PUT    /users/:user_id/projects/:id(.:format)                projects#update
                                 DELETE /users/:user_id/projects/:id(.:format)                projects#destroy

我的projects_controller.rb(为了以防万一,我将整件事包括在内)

class ProjectsController < ApplicationController
before_filter :deny_to_visitors
before_action :correct_user, only: [:show, :edit, :update, :destroy, :cancel, :cancel_save]
before_action :set_current_status, only: [:cancel, :cancel_save]

def index
  @projects = Project.all.order(id: :asc)
end

def show
end

def new
  @project = current_user.projects.new
  @budgets = Budget.all
end

def edit
end

def create
  @project = current_user.projects.new(project_params)
  @project.project_status_id = 1
  if @project.save
    redirect_to root_path, notice: 'Your project is being reviewed. We will be in contact soon!'
    AdminMailer.new_project_email(current_user, @project).deliver_now
  else
    render :new
  end
end 

def update
  if @project.update(project_params)
    if admin_signed_in?
      redirect_to admin_projects_list_path, notice: 'Project was successfully updated.'
    else
      redirect_to root_path, notice: 'Project was successfully updated.'
    end
  else
    render :edit
  end
end

def destroy
  @project.destroy
  redirect_to projects_url, notice: 'Project was successfully destroyed.'
end

def cancel
end

def cancel_save
  @project.cancel_reason.update(:project_id, :last_status_id, :comment)
  @project.update_attribute(:project_status_id, 10)

  redirect_to root_path, notice: 'Project has been successfully cancelled.'
end

private
  # Use callbacks to share common setup or constraints between actions.
  def deny_to_visitors
    redirect_to root_path unless user_signed_in? or admin_signed_in?
  end

def correct_user
  if admin_signed_in?
    @project = Project.find_by(id: params[:id])
  else
    @project = current_user.projects.find_by(id: params[:id])
  end
  redirect_to user_projects_path, notice: "You are not authorised to view this project" if @project.nil?
  end

def set_current_status
  @current_status = current_user.projects.find_by(id: params[:id]).project_status_id
end

def project_params
  params.require(:project).permit(:user_id, :project_type_id, :name, :industry_id, :description, :budget_id, :project_status_id, feature_ids:[], addon_ids:[])
end

end

我视图中的链接

<%= link_to 'Edit', edit_user_project_path(current_user, project) %>
<%= link_to 'Cancel', user_project_cancel_path(current_user, project) %>

我现在有一个非常简单的cancel.html.erb页面,目前还没有形式,直到我弄清楚出了什么问题。

<h1>Cancel</h1>
<p><%= @project.name %></p>

已更新

当我点击取消项目的链接时,我会在rails服务器控制台日志中找到它:

    Started GET "/users/1/projects/3/cancel" for ::1 at 2016-09-26 17:21:50 +0200
    Processing by ProjectsController#cancel as HTML
    Parameters: {"user_id"=>"1", "project_id"=>"3"}
    User Load (0.5ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2  [["id", 1], ["LIMIT", 1]]
    Project Load (0.3ms)  SELECT  "projects".* FROM "projects" WHERE "projects"."user_id" = $1 AND "projects"."id" IS NULL LIMIT $2  [["user_id", 1], ["LIMIT", 1]]
    Redirected to http://localhost:3000/users/1/projects
    Filter chain halted as :correct_user rendered or redirected
    Completed 302 Found in 6ms (ActiveRecord: 0.8ms)

当它加载上面的项目时,它会加载AND "projects"."id" IS NULL LIMIT $2 - 为什么值NULL明确地传递到project_id的{​​{1}}?

2 个答案:

答案 0 :(得分:0)

请检查以下关联的输出吗?

  

current_user.projects

答案 1 :(得分:0)

好的,这有点奇怪。我通过执行以下操作修复了它:

routes.rb我更改了行:

get "cancel" => 'projects#cancel'

get "cancel", :on => :member

这改变了我的路线。所以当我rake routes时,我的路线现在看起来像这样:

cancel_user_project GET    /users/:user_id/projects/:id/cancel(.:format)   projects#cancel

现在与RESTful路径一致(例如:对于编辑,路径为edit_user_project)。然后我按如下方式更新了我的链接:

旧链接

<%= link_to 'Cancel', user_project_cancel_path(current_user, project) %>

新链接

<%= link_to 'Cancel', cancel_user_project_path(current_user, project) %>

现在它有效。仍然不完全确定为什么它对路由中的自定义操作不满意,但这显然是问题所在。