到目前为止,对于拥有多年不同语言经验的非常有经验的Java EE开发人员,我遇到了Ruby on Rails的真正困难。我正在使用:ruby 2.3.1p112(2016-04-26修订版54768)[x86_64-darwin15]和Rails 5.0.0。我正在关注构建私有库Web应用程序的非常简单的在线教程,但是为了学习一些东西,而不是使用带有主题链接表的书籍,我将主题更改为作者,因为许多书籍都有相同的作者。我正在使用SQLLite进行开发,使用MySQL进行生产(还没有获得!)。我发现当你完全遵循大多数教程中的指示时,你最终会得到你正在构建的任何应用程序。但是,如果你以任何方式偏离,事情就不会起作用,而且很难弄清楚发生了什么。您在日志中收到错误消息(有时),您有未定义的变量或常量。通常,您将搜索该变量的使用位置,然后确保定义它或正确拼写它。但是,在RoR中,除了日志之外,该常量不会出现在任何地方,如果有的话。 RoR,由于它的惯例,已经创建或假设你有这样一个变量,实际上,你可能已经命名了一个" view"文件夹以单数形式而不是复数形式。它发明了"一个指向该变量的变量,但它与模式不匹配,因此失败并显示非常差的错误消息。
服务器不会抱怨,只是回滚,然后继续。如上所述,日志有一些无意义的消息。我最终会花费数小时为人们建议的路线尝试不同的模式,或者重命名事物,但这完全是猜测。
我喜欢使用我理解它们的框架和系统。这似乎是yml,yaml,erb,rb,sass,haml等解析的不同部分的集合。我尝试过记录,但无济于事。你如何找到简单的错误?
这是我的" books_controller.rb":
class BooksController < ApplicationController
def list
@books = Book.all
end
def show
@book = Book.find(params[:id])
end
def new
@book = Book.new
@authors = Author.all
end
def create
@book = Book.new(book_params)
if @book.save
logger.debug 'Redirecting to list'
redirect_to :action => 'list'
else
@authors = Author.all
render :action => 'new'
end
end
def edit
@book = Book.find(params[:id])
@authors = Author.all
end
def update
@book = Book.find(params[:id])
if @book.update_attributes(book_params)
redirect_to :action => 'show', :id => @book
else
@authors = Author.all
render :action => 'edit'
end
end
def delete
Book.find(params[:id]).destroy
redirect_to :action => 'list'
end
def show_authors
@author = Author.find(params[:id])
end
def book_params
params.require(:books).permit(:title, :description, :author_id)
end
end
app / views / books下的new.html.erb是:
<h1>Add new book</h1>
<%= form_tag :action => 'create' do %>
<p><label for = "book_title">Title</label>:
<%= text_field 'books', 'title' %></p>
<p><label for = "book_author_id">Author</label>:
<%= collection_select(:book, :author_id, @authors, :id, :name, prompt: true) %></p>
<p><label for = "book_description">Description</label><br/>
<%= text_area 'books', 'description' %></p>
<%= submit_tag "Create" %>
<% end -%>
<%= link_to 'Back', {:action => 'list'} %>
routes.rb是:
Rails.application.routes.draw do
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
resources :books
#get 'books/list'
#post 'books/create'
#get 'books/new'
#patch 'books/update'
#get 'books/show'
#get 'books/edit'
#get 'books/delete'
get 'books/show_authors'
get 'authors/list'
post 'authors/create'
get 'authors/new'
patch 'authors/update'
get 'authors/show'
get 'authors/edit'
root :to => 'books#list'
end
当我尝试添加新书时,我输入标题,选择作者,然后输入说明并点击&#34;创建&#34;。然后它返回到新屏幕。控制台有:
Started GET "/books/new" for ::1 at 2016-08-04 17:18:22 -0400
Processing by BooksController#new as HTML
Rendering books/new.html.erb within layouts/application
Author Load (0.1ms) SELECT "authors".* FROM "authors"
Rendered books/new.html.erb within layouts/application (5.4ms)
Completed 200 OK in 26ms (Views: 21.6ms | ActiveRecord: 0.5ms)
Started POST "/books" for ::1 at 2016-08-04 17:18:28 -0400
Processing by BooksController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"noRmEq8rHE6RLs0cPNrlZoQXq//2sr+SAOSHEFc0U3zqbSJZOSKDmdgwpdm5/nVswItHp4Ken0mjggt47ph46Q==", "books"=>{"title"=>"sdfasdf", "description"=>"asdfasdf"}, "book"=>{"author_id"=>"2"}, "commit"=>"Create"}
(0.1ms) begin transaction
(0.1ms) rollback transaction
Rendering books/new.html.erb within layouts/application
Author Load (0.1ms) SELECT "authors".* FROM "authors"
Rendered books/new.html.erb within layouts/application (2.0ms)
Completed 200 OK in 24ms (Views: 20.3ms | ActiveRecord: 0.2ms)
并且开发日志有:
Started GET "/books/new" for ::1 at 2016-08-04 17:18:22 -0400
Processing by BooksController#new as HTML
Rendering books/new.html.erb within layouts/application
[1m[36mAuthor Load (0.1ms)[0m [1m[34mSELECT "authors".* FROM "authors"[0m
Rendered books/new.html.erb within layouts/application (5.4ms)
Completed 200 OK in 26ms (Views: 21.6ms | ActiveRecord: 0.5ms)
Started POST "/books" for ::1 at 2016-08-04 17:18:28 -0400
Processing by BooksController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"noRmEq8rHE6RLs0cPNrlZoQXq//2sr+SAOSHEFc0U3zqbSJZOSKDmdgwpdm5/nVswItHp4Ken0mjggt47ph46Q==", "books"=>{"title"=>"sdfasdf", "description"=>"asdfasdf"}, "book"=>{"author_id"=>"2"}, "commit"=>"Create"}
[1m[35m (0.1ms)[0m [1m[36mbegin transaction[0m
[1m[35m (0.1ms)[0m [1m[31mrollback transaction[0m
Rendering books/new.html.erb within layouts/application
[1m[36mAuthor Load (0.1ms)[0m [1m[34mSELECT "authors".* FROM "authors"[0m
Rendered books/new.html.erb within layouts/application (2.0ms)
Completed 200 OK in 24ms (Views: 20.3ms | ActiveRecord: 0.2ms)
是的,该交易已回滚。为什么?如何获取有关导致数据库导致&#34;回滚的信息?#34;?数据库中的两个表是:
class CreateBooks < ActiveRecord::Migration[5.0]
def change
create_table :books do |t|
t.string :title
t.integer :author_id
t.string :description
t.timestamp :created
t.timestamps
end
end
end
class CreateAuthors < ActiveRecord::Migration[5.0]
def change
create_table :authors do |t|
t.string :name
t.timestamps
end
end
end
class Book < ApplicationRecord
belongs_to :author
validates_presence_of :title
end
class Author < ApplicationRecord
has_many :books
end
我可以在rails控制台中创建一本书:
b=Book.create :title=>'Test', :author_id=>1, :description=>'Desc'
(0.1ms) begin transaction
Author Load (0.1ms) SELECT "authors".* FROM "authors" WHERE "authors"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
SQL (0.3ms) INSERT INTO "books" ("title", "author_id", "description", "created_at", "updated_at") VALUES (?, ?, ?, ?, ?) [["title", "Test"], ["author_id", 1], ["description", "Desc"], ["created_at", 2016-08-04 20:17:40 UTC], ["updated_at", 2016-08-04 20:17:40 UTC]]
(2.4ms) commit transaction
=> #<Book id: 1, title: "Test", author_id: 1, description: "Desc", created: nil, created_at: "2016-08-04 20:17:40", updated_at: "2016-08-04 20:17:40">
我很感激投入,特别是帮助理解为什么发生了什么事实。似乎有一个非常简单的错误,但我无法看到它。
------------------在几个答案之后添加了&#34;猜测&#34;由我。 我将form_tag更改为form_for,如下所示。 ---- new.html.erb ------
<%= form_for(@book) do |f| %>
Title: <%= f.text_field :title %><br/>
Author: <%= select("book", "author_id", Author.all.collect{|p| [p.name,p.id]}, prompt: 'Select') %><br/>
Description: <%= f.text_area :description %><br/>
<%= f.submit "Create" %>
<% end -%>
<%= link_to 'Back', {:action => 'list'} %>
我进入浏览器:
Validation failed: Author must exist, Title can't be blank
Extracted source (around line #18):
16
17
18
19
20
21
def create
@book = Book.new
if @book.save!
redirect_to :action => 'list'
else
@authors = Author.all
Rails.root: /Users/woo/Development/rails/library
Application Trace | Framework Trace | Full Trace
app/controllers/books_controller.rb:18:in `create'
Request
Parameters:
{"utf8"=>"✓",
"authenticity_token"=>"gi+wVGV3MIlkJsRjO8Ig1cS3YV/OIADSevFJg7ItBesokIiHFDThycTO8/kob+2E1fuPFquFUK+b7bGksWRZGQ==",
"book"=>{"title"=>"Book", "author_id"=>"2", "description"=>"test"},
"commit"=>"Create"}
据我所知,本书确实有一个标题,一个author_id和一个描述。为什么&#34;作者必须存在,标题不能为空白&#34;?
答案 0 :(得分:0)
尝试在form_for
视图中使用form_tag
代替books/new
。这是为模型对象创建表单的Rails方法。
查看form_for here上的便捷指南。
答案 1 :(得分:0)
如何调试....
有几种工具可以帮助调试Rails应用程序。您已经发现的一个:log/development.log
中的日志文件。
另一个是Byebug。将gem添加到Gemfile中,并在'else'后面的create动作中插入以下内容:
require 'byebug'
byebug
然后再次发布表格。开发服务器将打开一个Byebug控制台,您可以在其中检查局部变量,实例变量和堆栈跟踪。尝试检查:
@book.errors
当ActiveRecord模型无法保存时,通常是因为验证失败。保存时遇到的错误将添加到模型实例上的errors
对象。
失败的原因可能是表单没有传递预期的参数。按照惯例,Rails期望模型的属性位于散列中,其中键是模型名称,因此params[:book][:title]
,而不是params[:title
]。有关详细信息,请参阅form_for
帮助程序的文档。
答案 2 :(得分:0)
感谢您的帮助。根据您的建议以及准备各种Google网站的大量猜测,我将它们合并到new.html.erb put form_for(@book)中,然后在books_controller.rb的create方法中,我放了@book - Book。 new(book_params),其中book_params是:
def book_params
params.require(:book).permit(:title, :author_id, :description)
end
我猜这是为了处理Rails 4及以上所需的强大归属。在我将书籍作为第一个论点并且因为它存在之前,但书籍没有填写之前,我得到了奇怪的错误。在使用带有@book作为参数的form_for之后,将表单中的值设置为book哈希。然后使用:book作为第一个参数的params.require,查看该哈希以提取title,author_id和description。
再次,非常感谢您的帮助,我了解了再见bug并保存!等等。我发现信息非常粗略,而且没有提到版本,因此多次误入歧途。