ActionController::ParameterMissing с пользовательским маршрутом

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

ActionController::ParameterMissing in BooksController#update
param is missing or the value is empty: 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>

Проблема в форме, которую вы используете для отправки. Эта строка @book.soft_delete(book_params) в методе обновления означает, что вы используете book_params, который требует book. Параметры должны выглядеть примерно так: `:book => {title: 'title here',....}}. Если вы посмотрите на отправляемые параметры, в них будет отсутствовать этот внешний объект book, охватывающий атрибуты, которые вы отправляете. Можете ли вы опубликовать, как выглядят отправленные параметры?

Rockwell Rice 21.05.2019 18:44
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
1
162
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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...%>

Спасибо за ваше решение. Я пробовал, но столкнулся с той же проблемой с параметрами, мне пришлось использовать первое решение вопроса.

Promise Preston 22.05.2019 07:39
Ответ принят как подходящий

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

Во-вторых: Я предлагаю вам удалить методы :soft_delete и :undelete из модели. Rails предоставляет методы :toggle! для мгновенной записи в БД и :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 }

Пожалуйста, позвольте мне узнать больше о том, как вы так хорошо изучили рубин? Я хотел бы стать лучшим разработчиком Ruby, пожалуйста.

Promise Preston 22.05.2019 07:38

конечно) Для начала вы можете найти много полезной информации о рельсах здесь Guides.rubyonrails.org. Для изучения рубиновых методов - ruby-doc.org.

Foton 22.05.2019 08:06

Спасибо большое. Пожалуйста, могу ли я связаться с вами любым другим способом или с помощью любой другой платформы, если у меня возникнут проблемы с моим кодом? Ваше решение кажется очень простым и чистым.

Promise Preston 22.05.2019 10:15

Я рад помочь, так что вы можете указать свое имя на facebook

Foton 22.05.2019 19:17

Меня на Facebook зовут Promise Chukwuenyem. Спасибо. fb.com/promisepreston1

Promise Preston 23.05.2019 07:52

Другие вопросы по теме