1

我正在编写一个在后台使用 SQL Lite 数据库的图书库系统。通过控制台,我可以毫无问题地添加和更新书籍。而且我已经提出了一个可以添加新书的视图,并且效果很好。

但是现在我正在尝试创建一个可以更新/编辑书籍的视图,但它不起作用。

我收到一条错误消息,因为它试图在没有 book 的情况下从我的 book_controller.rb 调用 edit 方法:id。有人知道为什么它不使用 : 调用该方法id吗?

错误

Couldn't find Book without an ID 
app/controllers/book_controller.rb:30:in `edit'

路线.rb

Rails.application.routes.draw do   
  get 'users/show'   
  get 'forms/show'
  get 'tabelle/show'   
  get 'photography/show'   
  get 'computer_scientist/show'   
  get 'switzerland/show'   
  get 'book/index', as: 'book_index'   
  get 'book/show'   
  get 'book/new'   
  get 'book/create'   
  get 'book/book_prams'   
  get 'book/edit'
  get 'book/update'   
  get 'book/destroy'   
  get 'subject/show'   
  get '/book/show/:id', to: 'book#show', as: 'show_book'   
  get '/book/new', to: 'book#new', as: 'new_book'   
  get '/book/edit', to: 'book#edit', as: 'edit_book'
  delete '/book/destroy/:id', to: 'book#destroy', as: 'delete_book'   
  root 'pages#home'   
  post 'book/create', as: 'create_book'   
  put 'book/update/:id', to: 'book#update', as: 'update_book' 
end

book_controller.rb

class BookController < ApplicationController   
  def index
    @books = Book.all   
  end

  def show
    @book = Book.find(params[:id])
  end

  def new
    @book = Book.new
    @subjects = Subject.all   
  end

  def create
    @book = Book.new(book_params)
    if @book.save
      redirect_to action: "index"
    else
      @subjects = Subject.all
      render action: "new"
    end   
  end

  def book_params
    params.require(:book).permit(:title, :price, :subject_id, :description)   
  end

  def edit
    @book = Book.find(params[:id])
    @subjects = Subject.all   
  end

  def update
    @book = Book.find(params[:id])
    if @book.update_attributes(book_params)
      redirect_to action: "index"
    else
      @subjects = Subject.all
      render action: "edit"
    end   
  end

  def destroy
    Book.find(params[:id]).destroy
    redirect_to action: "index"   
  end 
end

编辑.html.erb

  <main>   
    <section class="form-group">
      <%= form_with model: @book, url: update_book_path(@book.id) do |f| %>
        <p class="form-control">Title <%= f.text_field :title %></p>
        <p class="form-control">Price <%= f.text_field :price %></p>
        <p class="form-control">Subject <%= f.collection_select :subject_id, @subjects, :id, :name %></p>
        <p class="form-control">Description <%= f.text_area :description %></p>
        <p class="form-control"><%= f.submit "Buch speichern"%></p>
        <p class="form-control"><%= link_to "Abbrechen", book_index_path %></p>
      <% end %>   
    </section> 
  </main>

index.html.erb

<div class="container">   
  <% if @books.blank? %>
    <p>Es sind keine Bücher im System.</p>
  <%else %>
    <table class="table table-hover">
      <thead class="thead-light">
        <tr>
          <th>Buch</th>
          <th colspan="2">Aktion</th>
        </tr>
      </thead>
      <tbody>
        <%@books.each do |b| %>
          <tr>
            <td><%= link_to b.title, show_book_path(b.id) %></td>
            <td><%= link_to "Ändern", edit_book_path(b.id) %></td>
            <td><%= link_to "Löschen", delete_book_path(b.id), method: :delete,
             data: { confirm: "Sind Sie sicher?" } %></td>
          </tr>
        <% end %>
      </tbody>
    </table>
  <%end %>   
  <%= link_to "Neues Buch erfassen", new_book_path %> 
</div>

强文本

<main>   
  <section class="form-group">
    <%= form_with model: Book.new, url: create_book_path do |f| %>
      <p class="form-control">Title <%= f.text_field :title %></p>
      <p class="form-control">Price <%= f.text_field :price %></p>
      <p class="form-control">Subject <%= f.collection_select :subject_id, @subjects, :id, :name %></p>
      <p class="form-control">Description <%= f.text_area :description %></p>
      <p class="form-control"><%= submit_tag "Buch speichern" %></p>
      <p class="form-control"><%= link_to "Abbrechen", book_index_path %></p>
    <% end %>   
  </section> 
</main>
4

2 回答 2

1

您的代码有很多问题。Rails 鼓励“约定优于配置”,您在很多方面都在打破约定。

首先,你应该使用常规的BooksController,而不是BookController.

其次,您应该使用传统的面向资源的路线,而不是手工制作所有book路线。就像是:

Rails.application.routes.draw do

  ...

  resources :books

  ...
 
end

这会给你:

    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

然后,在您的 中index.html.erb,您可以执行以下操作:

<% @books.each do |book| %>
  <tr>
    <td><%= link_to book.title, book %></td>
    <td><%= link_to "Ändern", edit_book_path(book) %></td>
    <td><%= link_to "Löschen", book, method: :delete, data: { confirm: "Sind Sie sicher?" } %></td>
  </tr>
<% end %>
于 2020-09-16T15:00:04.913 回答
1

问题是你的路线。(正如另一个答案中提到的,不遵循 Rails 约定,请注意单数/复数)。

看看在控制器中你是如何在编辑方法中做到这一点的:

@book = Book.find(params[:id])

params 哈希有不同的来源,其中之一是 url。在 Rails 中,您需要通过 url 传递要编辑/更新的记录的 ID。所以你的路线应该是这样的:

get "books/:id/edit", to: "books#edit"

还要注意更新路线,你拥有的不是标准的 Rails 方式。它应该是:

patch 'books/:id/update', to: 'book#update', as: 'update_book'

在此处查看路由的资源方法: https ://guides.rubyonrails.org/routing.html#resource-routing-the-rails-default

于 2020-09-16T15:02:07.220 回答