Ruby rails,无法通过 Web 界面更新数据库
Ruby on rails, can't update database via web interface
我正在编写一个图书图书馆系统,后台有一个 SQL Lite 数据库。通过控制台,我可以毫无问题地添加和更新书籍。我已经制作了一个可以添加新书的视图,效果很好。
但现在我正在尝试制作一个可以 update/edit 书籍的视图,但它不起作用。
我收到一条错误消息,因为它试图从我的 book_controller.rb 调用编辑方法而没有一本书 :id
。有人知道为什么它不使用 :id
?
调用方法吗
错误
Couldn't find Book without an ID
app/controllers/book_controller.rb:30:in `edit'
routs.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
edit.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>
您的代码有很多问题。 Rails 鼓励“约定优于配置”,您正在以多种方式打破约定。
首先,你应该使用常规的BooksController
,而不是BookController
。
其次,您应该使用常规 resource-oriented 路线,而不是 hand-crafting 所有 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 %>
问题出在你的路线上。 (正如另一个答案中提到的,未遵循 Rails 约定,请注意 singular/plural)。
查看在控制器中如何在编辑方法中执行此操作:
@book = Book.find(params[:id])
params hash 有不同的来源,其中之一是url。在 Rails 中,您需要通过 url 传递要 edit/update 的记录 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
我正在编写一个图书图书馆系统,后台有一个 SQL Lite 数据库。通过控制台,我可以毫无问题地添加和更新书籍。我已经制作了一个可以添加新书的视图,效果很好。
但现在我正在尝试制作一个可以 update/edit 书籍的视图,但它不起作用。
我收到一条错误消息,因为它试图从我的 book_controller.rb 调用编辑方法而没有一本书 :id
。有人知道为什么它不使用 :id
?
错误
Couldn't find Book without an ID
app/controllers/book_controller.rb:30:in `edit'
routs.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
edit.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>
您的代码有很多问题。 Rails 鼓励“约定优于配置”,您正在以多种方式打破约定。
首先,你应该使用常规的BooksController
,而不是BookController
。
其次,您应该使用常规 resource-oriented 路线,而不是 hand-crafting 所有 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 %>
问题出在你的路线上。 (正如另一个答案中提到的,未遵循 Rails 约定,请注意 singular/plural)。
查看在控制器中如何在编辑方法中执行此操作:
@book = Book.find(params[:id])
params hash 有不同的来源,其中之一是url。在 Rails 中,您需要通过 url 传递要 edit/update 的记录 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