ActionController :: ParameterMissing с пользовательским маршрутом - PullRequest
1 голос
/ 21 мая 2019

Я создаю цифровую библиотеку, и сейчас я пытаюсь добавить soft_delete в приложение, но у меня возникают проблемы с ошибкой, показывающей

ActionController :: ParameterMissing в BooksController # 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

Контроллер книг (усеченный)

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 ]

2 голосов
/ 21 мая 2019

Я предлагаю вам не использовать явные маршруты, такие как 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' никогда не будет использоваться.Это то, что вызвало ошибку: 'ActionController :: ParameterMissing in BooksController # update' - при щелчке по вашей ссылке сработал вызов действия обновления BooksController #, который требует ключ книги в параметрах.

Во-вторых: я предлагаю вам удалить методы: 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 }
0 голосов
/ 21 мая 2019

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#update и books#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...%>

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...