2016-08-05 3 views
0

До сих пор для опытного разработчика Java EE с многолетним опытом работы на разных языках у меня возникли реальные трудности с Ruby on Rails. Я использую: ruby ​​2.3.1p112 (2016-04-26 версия 54768) [x86_64-darwin15] и Rails 5.0.0. Я следую очень простому онлайновому учебнику по созданию частного веб-приложения для библиотеки, НО, чтобы что-то узнать, вместо того, чтобы иметь книги со связанной таблицей «Субъекты», я сменил тему на авторов, поскольку у многих книг есть те же авторы. Я использую SQLLite для разработки и MySQL для производства (еще не добрался!). Я нахожу, что, когда вы точно следуете инструкциям в большинстве руководств, вы получаете все, что вы строите. Но, если вы отклоняетесь каким-либо образом, все просто не работает, и очень сложно понять, что произошло. Вы получаете сообщения об ошибках (иногда) в журналах, у которых есть неопределенная переменная или константа. Как правило, вы должны искать, где эта переменная используется, тогда убедитесь, что вы ее определяете или правильно произносите. Однако в RoR эта константа не появляется нигде, кроме журнала, если есть. RoR, из-за своих соглашений, либо создал, либо предположил, что у вас есть такая переменная, когда на самом деле вы можете назвать папку «view» в единственном числе, а не в множественном числе. Он «придумал» переменную, чтобы указать на это, но она не соответствовала шаблону, поэтому она терпит неудачу с очень плохими сообщениями об ошибках.Как отлаживать простое приложение RoR

Сервер не жалуется, просто выполняет откат и продолжает работу. В журнале есть какое-то непередаваемое сообщение, как указано выше. Я в конечном итоге трачу часы, пробую разные шаблоны для маршрутов, предложенных людьми, или переименовывая вещи, но это все догадки.

Мне нравится работать с каркасами и системами, где я их понимаю. Кажется, это коллекция различных частей, которые анализируются в 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 

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 

Когда я пытаюсь добавить новую книгу, я ввожу название, выбираю автора и вставляю описание и нажимаю «Создать». Затем он просто возвращается на новый экран. Консоль имеет:

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) 

Да, сделка откат. ЗАЧЕМ? Как я могу получить информацию о том, что привело к откату базы данных? Эти две таблицы в базе данных являются:

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 

Я могу создать книгу в рельсах консоли как:

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"> 

Я был бы признателен за вклад и особенно помочь в понимании того, почему то, что произошло на самом деле произошло. Похоже, что делается очень простая ошибка, но я не вижу ее.

------------------ Добавлено после нескольких ответов и «догадок» от меня. Я изменил form_tag на form_for, как я покажу ниже. ---- new.html.Еврорадио ------

<%= 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 и описание. Почему «Автор должен существовать, Заголовок не может быть пустым»?

+1

Ok замените '@ book.save' на' @ book.save! ', И вы увидите ошибку прямо там. Это будет ваш первый инструмент отладки. Дайте мне знать, что вы видите, я помогу вам. :) Я предположил, что у вас есть проблемы с созданием книг, нет? Пожалуйста, поправьте меня, если я ошибаюсь в своем предположении. –

ответ

0

Попробуйте использовать form_for вместо form_tag в вашем books/new. Это способ Rails для создания форм для объекта модели.

Проверьте удобное руководство по form_for here.

+0

Когда я попробовал это, у меня возникла ошибка: «undefined method name create for hash» –

+0

Можете ли вы отредактировать свой вопрос с новым представлением, в котором используется form_for? – davideghz

0

Как отлаживать ....

Есть несколько инструментов, чтобы помочь отладить приложение Rails. Вы уже обнаружили: файл журнала в log/development.log.

Другим является Byebug. Добавить камень в ваш Gemfile и вставьте следующее в действие создать после того, как «еще»:

require 'byebug' 
byebug 

затем снова опубликовать форму. Сервер разработки откроет консоль Byebug, где вы сможете проверить локальные переменные, переменные экземпляра и трассировку стека. Попробуйте проверить:

@book.errors 

Когда модель ActiveRecord не удается сохранить, это обычно происходит потому, что проверки не удались. Ошибки, возникающие при сохранении, добавляются к объекту errors экземпляра модели.

Причина отказа, вероятно, в том, что форма не передает ожидаемые параметры. По соглашению, Rails ожидает, что атрибуты для модели будут в хеше, где ключ является именем модели, поэтому params[:book][:title], а не params[:title]. Дополнительную информацию см. В документации для помощника form_for.

+0

Я добавил '!' к @ books.save и получил: ... Обработка BooksController # создать в HTML Параметры: { "utf8" => "✓", "authenticity_token" => "qvgB2E2d9Wvs7bdkfp9lCKtTazEaJleZO3VAOIXQANHeEUWT25RqvKXz36H7u/UC78 + HaW4Kd0KYE8xQPHwrRA ==", «книги "=> {" title "=>" Book2 "," description "=>" A Book "}," book "=> {" author_id "=>" 2 "}," commit "=>" Create "} (0,1 мс) начать транзакцию (0,1 мс) откатить транзакции Завершена 422 Unprocessable Entity в 4ms (ActiveRecord: 0,1 мс) ActiveRecord :: RecordInvalid (Не удалось выполнить проверку Автор должен существовать): приложение/контроллеры/books_controller.rb : 19: in 'create ' –

+0

Не удалось из-за проверки« Автор должен существовать ». Автор_ид не задается в книге, когда он сохраняется. Включает ли модель 'accepts_nested_attributes_for'? См. Руководство Rails http://guides.rubyonrails.org/form_helpers.html, раздел 9.1. – zetetic

+0

Нет, я посмотрю. Учебник, который я посещал, не имел этого, только то, что я показал. –

0

Спасибо за помощь. С вашими предложениями и множеством угадываний из готовых различных сайтов Google я объединил их и в new.html.erb put form_for (@book), а затем в методе create books_controller.rb, я разместил @book-Book. новый (book_params), где book_params является:

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

Я предполагаю, что это, чтобы справиться с сильной атрибуцией требуемого Rails 4 и выше. Раньше у меня были книги в качестве первого аргумента, и поскольку он существовал, но книга не была заполнена, я получил странную ошибку. После использования form_for с @book в качестве аргумента, установите значения из формы в хэш-код книги. Затем paramsrequire с: book в качестве первого аргумента, посмотрел в этом хеше, чтобы извлечь название, author_id и описание.

Снова большое спасибо за помощь, и я узнал об ошибке и спасении! и так далее. Я нахожу, что информация очень отрывочная, и версия не упоминается, что приводит к тому, что она несколько заблуждается.

Смежные вопросы