如何调试简单的RoR应用程序

时间:2016-08-05 15:56:25

标签: ruby-on-rails ruby

到目前为止,对于拥有多年不同语言经验的非常有经验的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;?

3 个答案:

答案 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并保存!等等。我发现信息非常粗略,而且没有提到版本,因此多次误入歧途。