具有自定义路由的ActionController :: ParameterMissing

时间:2019-05-21 16:37:15

标签: ruby-on-rails soft-delete

我正在建立一个数字图书馆,现在我正在尝试将soft_delete添加到应用程序中,但是出现显示错误的问题

  

BooksController中的ActionController :: ParameterMissing#update
  参数丢失或值为空:book

soft_delete方法的作用是将其数据库中的表从其默认false值更新为true。我已经检查了我的代码,但是找不到问题的根源。

图书模型

class Book < ApplicationRecord
  #add a model scope to fetch only non-deleted records
  scope :not_deleted, -> { where(soft_deleted: false) }
  scope :deleted, -> { where(soft_deleted: true) }

  #create the soft delete method
  def soft_delete 
    update(soft_deleted: true)
    soft_deleted
  end

  # make an undelete method
  def undelete
    update(soft_deleted: false)
  end
end

Books Controller(截断)

class BooksController < ApplicationController
  before_action :set_book, only: [:show, :edit, :update, :soft_delete, :destroy]

  def index
    @books = Book.not_deleted
  end

...

  def destroy
    @book.destroy
    respond_to do |format|
      format.html { redirect_to books_url, notice: 'Book was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  def soft_delete
    respond_to do |format|
      @book.soft_delete(book_params)
        format.html { redirect_to books_url, notice: 'Book was successfully deleted.' }
        format.json { head :no_content }
    end
  end



  private
    # Use callbacks to share common setup or constraints between actions.
    def set_book
      @book = Book.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def book_params
      params.require(:book).permit(:name, :author, :description, :soft_deleted)
    end
end

路线

Rails.application.routes.draw do
  resources :books
  put '/books/:id' => 'books#soft_delete'
end

图书索引视图

<h1>Books</h1>
<tbody>
    <% @books.each do |book| %>
      <tr>
        <td><%= book.name %></td>
        <td><%= book.author %></td>
        <td><%= book.description %></td>
        <td><%= link_to 'Show', book %></td>
        <td><%= link_to 'Edit', edit_book_path(book) %></td>
        <td><%= link_to 'Destroy', book, method: :delete, data: { confirm: 'Are you sure?' } %></td>
        <td><%= link_to 'Soft Delete', book, method: :put, data: { confirm: 'Are you sure?' } %></td>
        soft_delete
      </tr>
    <% end %>
  </tbody>

2 个答案:

答案 0 :(得分:2)

我建议您不要使用诸如 put '/books/:id' => 'books#soft_delete' Rails具有“成员路线”,因此您可以通过以下方式重写路线:

resources :books, only: %i[index destroy] do
  member { put :soft_delete }
end

在这里,我使用了'only'选项,该选项允许您只为您定义必要的路线(不是全部7条路线,而是2条-索引并销毁)

首先:您已经定义了resources :books。此定义为您创建了7条路线:

    books GET    /books(.:format)           -> books#index
          POST   /books(.:format)           -> books#create
 new_book GET    /books/new(.:format)       -> books#new
edit_book GET    /books/:id/edit(.:format)  -> books#edit
     book GET    /books/:id(.:format)       -> books#show
          PATCH  /books/:id(.:format)       -> books#update (this and next route are the same, and considering as 1, so we have 7 routes, not 8)
          PUT    /books/:id(.:format)       -> books#update
          DELETE /books/:id(.:format)       -> books#destroy

因此使用方法PUT和路径'/ books /:id'的路由已经存在,并且将永远不会使用您的put '/books/:id' => 'books#soft_delete'。那就是引发错误的原因:'BooksController#update中的'ActionController :: ParameterMissing'-您的链接单击触发了BooksController#update操作调用,该调用需要在参数中输入书本键。

第二: 我建议您从模型中删除方法:soft_delete和:undelete。 Rails提供方法:切换!可以立即写入数据库,而:toggle可以更改值,而不是立即保存更改。因此,您可以在控制器中直接编写以下代码:

book = Book.find_by(id: params[:id])
book.toggle!(:soft_deleted)

请注意,soft_deleted列应为布尔值才能使其正常工作。

您的链接应为:

link_to 'Soft Delete', soft_delete_book_path(book), data: { method: :put }

答案 1 :(得分:0)

Rails会将<%= link_to 'Soft Delete', book, method: :put...%>路由到update操作,因为resource :books是在您的自定义路由之前定义的,并且Rails使用第一个与请求匹配的路由。

在终端中运行rails routes -g books,您会看到类似的内容:

    books GET    /books(.:format)          books#index
          POST   /books(.:format)          books#create
 new_book GET    /books/new(.:format)      books#new
edit_book GET    /books/:id/edit(.:format) books#edit
     book GET    /books/:id(.:format)      books#show
          PATCH  /books/:id(.:format)      books#update
          PUT    /books/:id(.:format)      books#update
          DELETE /books/:id(.:format)      books#destroy
          PUT    /books/:id(.:format)      books#soft_delete

如您所见,books#updatebooks#soft_delete的路由是相同的。

您可以通过创建命名路由来解决它:put '/books/:id' => 'books#soft_delete', as: 'soft_delete'

      books GET    /books(.:format)          books#index
            POST   /books(.:format)          books#create
   new_book GET    /books/new(.:format)      books#new
  edit_book GET    /books/:id/edit(.:format) books#edit
       book GET    /books/:id(.:format)      books#show
            PATCH  /books/:id(.:format)      books#update
            PUT    /books/:id(.:format)      books#update
            DELETE /books/:id(.:format)      books#destroy
soft_delete PUT    /books/:id(.:format)      books#soft_delete

然后,修改模板以使用新的帮助器:<%= link_to 'Soft Delete', soft_delete_path(book), method: :put...%>