我已经在edit.html.erb中创建了一个编辑表单,但是每次我提交它都会创建一个新元素。我已经尝试检查路线,相关的控制器动作,模型中的验证等。在这里我无法弄清楚自己在做什么错。我以为可能需要在表格的开头放置<form action="/books/<%= @book.id %>" method="post">
,或者将方法更改为“补丁”,但是这两种方法都不能解决问题。我也尝试注释掉验证,但这也无济于事。只有一个模型。谢谢,如果您发现我做错了,请告诉我!
这是我在不同文件中所拥有的:
routes.rb:
Rails.application.routes.draw do
resources :books
root 'books#index'
end
book.rb:
class Book < ApplicationRecord
validates :title, :author, :total_pages, :dewey, :status, presence: true
end
books_controller.rb:
class BooksController < ApplicationController
before_action :find_book, only: [:show, :edit, :update, :destroy]
def index
@books = Book.all
end
def show
end
def new
@book = Book.new
end
def create
@book = Book.create(book_params)
if @book.status == 'Incomplete'
@book.pages_read = @book.total_pages / 2
elsif @book.status = 'Unread'
@book.pages_read = 0
else
@book.pages_read = @book.total_pages
end
# Save by category
# Must save as a string to maintain leading zeros
if @book.dewey.to_s.split('').map { |digit| digit.to_i }.first == 0
@book.category = "Computer Science, Information & General Works"
elsif @book.dewey.to_s.split('').map { |digit| digit.to_i }.first == 1
@book.category = "Philosophy & Psychology"
elsif @book.dewey.to_s.split('').map { |digit| digit.to_i }.first == 2
@book.category = "Religion"
elsif @book.dewey.to_s.split('').map { |digit| digit.to_i }.first == 3
@book.category = "Social Science"
elsif @book.dewey.to_s.split('').map { |digit| digit.to_i }.first == 4
@book.category = "Language"
elsif @book.dewey.to_s.split('').map { |digit| digit.to_i }.first == 5
@book.category = "Pure Science"
elsif @book.dewey.to_s.split('').map { |digit| digit.to_i }.first == 6
@book.category = "Applied Science"
elsif @book.dewey.to_s.split('').map { |digit| digit.to_i }.first == 7
@book.category = "Arts & Recreation"
elsif @book.dewey.to_s.split('').map { |digit| digit.to_i }.first == 8
@book.category = "Literature"
elsif @book.dewey.to_s.split('').map { |digit| digit.to_i }.first == 9
@book.category = "History & Geography"
end
if @book.valid?
@book.save
flash[:message] = "Book saved"
redirect_to @book
else
render :new
end
end
def edit
end
def update
if @book.status == 'Incomplete'
@book.pages_read = @book.total_pages / 2
elsif @book.status = 'Unread'
@book.pages_read = 0
else
@book.pages_read = @book.total_pages
end
# Save by category
# Must save as a string to maintain leading zeros
if @book.dewey.to_s.split('').map { |digit| digit.to_i }.first == 0
@book.category = "Computer Science, Information & General Works"
elsif @book.dewey.to_s.split('').map { |digit| digit.to_i }.first == 1
@book.category = "Philosophy & Psychology"
elsif @book.dewey.to_s.split('').map { |digit| digit.to_i }.first == 2
@book.category = "Religion"
elsif @book.dewey.to_s.split('').map { |digit| digit.to_i }.first == 3
@book.category = "Social Science"
elsif @book.dewey.to_s.split('').map { |digit| digit.to_i }.first == 4
@book.category = "Language"
elsif @book.dewey.to_s.split('').map { |digit| digit.to_i }.first == 5
@book.category = "Pure Science"
elsif @book.dewey.to_s.split('').map { |digit| digit.to_i }.first == 6
@book.category = "Applied Science"
elsif @book.dewey.to_s.split('').map { |digit| digit.to_i }.first == 7
@book.category = "Arts & Recreation"
elsif @book.dewey.to_s.split('').map { |digit| digit.to_i }.first == 8
@book.category = "Literature"
elsif @book.dewey.to_s.split('').map { |digit| digit.to_i }.first == 9
@book.category = "History & Geography"
end
@book.update(book_params)
if @book.update(book_params)
flash[:message] = "Successfully updated."
redirect_to @book
else
flash[:errors] = @book.errors.full_messages
render :edit
end
end
def destroy
@book.destroy
flash[:message] = "Book deleted."
redirect_to books_path
end
private
def book_params
params.require(:book).permit(:title, :author, :total_pages, :pages_read, :dewey, :category, :status)
end
def find_book
@book = Book.find(params[:id])
end
end
edit.html.erb:
<form action="/books" method="post">
<%=hidden_field_tag :authenticity_token, form_authenticity_token %>
<div class="container">
<h2 id="form-h2">Editing <%= @book.title %> by <%= @book.author %></h2>
<div class="form-group row">
<div class="col-sm-6">
<input type="text" class="form-control" id="title" placeholder="Title" name="book[title]" value="<%= @book.title %>">
</div>
<div class="col-sm-6">
<input type="text" class="form-control" id="author" placeholder="Author" name="book[author]" value="<%= @book.author %>">
</div>
</div>
<div class="form-group row">
<div class="col-sm-6">
<input type="text" class="form-control" id="total_pages" placeholder="Number of pages" name="book[total_pages]" value="<%= @book.total_pages %>">
</div>
<div class="col-sm-6">
<input type="text" class="form-control" id="dewey" placeholder="Dewey Decimal number" name="book[dewey]" value="<%= @book.dewey %>">
</div>
</div>
<p id="form-question">Have you finished this book?</p>
<div id="radios">
<div class="custom-control custom-radio">
<input type="radio" id="customRadio1" name="book[status]" value="Read" class="custom-control-input">
<label class="custom-control-label"for="customRadio1">Yes!</label>
</div>
<div class="custom-control custom-radio">
<input type="radio" id="customRadio2" name="book[status]" value="Incomplete" class="custom-control-input">
<label class="custom-control-label"for="customRadio2">I'm still reading it</label>
</div>
<div class="custom-control custom-radio">
<input type="radio" id="customRadio3" name="book[status]" value="Unread" class="custom-control-input">
<label class="custom-control-label" for="customRadio3">I haven't started it yet</label>
</div>
</div>
<div class="form-group row">
<div class="col-sm-4">
<button type="submit" id="add-button" class="btn btn-primary">Done</button>
</div>
</div>
</div>
</form>
我亲自尝试过,我认为使用专用的表单帮助程序会更好:
<%= form_for @book do |f| %>
<%= f.text_field :title %>
<%= f.submit %>
<!-- all the rest of your fields -->
<% end %>
这是生成的内容:
<form class="edit_book" id="edit_book_4" action="/books/4" accept-charset="UTF-8" method="post">
<input name="utf8" type="hidden" value="✓">
<input type="hidden" name="_method" value="patch">
<input type="hidden" name="authenticity_token" value="oyzBuqICn/+p8IENt1Dh02UOBzNyCxQ707JwcZdz/BnxocRL4wCzb18Q26DAoDqCFAuqWExII4K1ENGENEPWFA==">
<input type="text" value="new" name="book[title]" id="book_title">
<input type="submit" name="commit" value="Update Book" data-disable-with="Update Book">
</form>
请注意此处使用方法patch
的额外隐藏字段。
唯一的method
属性不理解patch
或put
,您只能在其中使用get
和post
(https://www.w3schools.com/tags/att_form_method.asp)
只有设置了特殊的_method
参数,您才能正确路由到update
方法。
我不确定您为什么决定努力按照自己的方式编写html表单,但是如果您要继续-保持框架的最新状态将遇到很大的问题。想象一下,从现在开始,Rails团队决定该字段不是_method
,而是__method
。采用“ canonical”方式-您甚至不会注意到。按照您的方式进行-您将拥有所有要更新的表格。
要更新记录,请使用PATCH /books/:id
。
<%= form_with(model: @book) do |form|>
<div class="container">
<h2 id="form-h2">Editing <%= @book.title %> by <%= @book.author %></h2>
<div class="form-group row">
<div class="col-sm-6">
<%= f.label :title %>
<%= f.text_field :title %>
</div>
</div>
# ...
</div>
<% end %>
form_with(model: @book)
足够聪明,可以根据模型是否已保存到数据库来设置操作和方法。它还负责创建真实性令牌和Rails用来伪造PUT,PATCH和DELETE请求的特殊_method
输入。
这使您可以在视图之间共享表单代码。使用form helpers创建带有数据绑定的输入。
如果您手动完成所有操作,则使用框架确实毫无用处-尤其是由配置约定驱动的rails,这使得它如此高效。