CRUD を作成⑤
CRUD を作成④ の続き。
前回は一覧ページを作成したので、今回は詳細ページを作成する。
詳細ページへのリンクを作成するため、一覧ページを修正する。
そのために、詳細ページへのパスを確認する。
以下のコマンドを実行する。
bundle e rails routes -g book
出力された結果から、詳細ページのルーティングは以下だとわかる。
book GET /books/:id(.:format) books#show
URLヘルパーは一番左側に記載されているため、一覧ページのコードを以下のように修正すれば良いとわかる。
<% @books.each do |book| %>
<%= link_to book.title, book_path(book) %><br />
<% end %>
表示を確認してみる。
以下のように表示されていれば成功。
試しに何かしらのリンクを押してみる。
詳細ページへ遷移できれば成功。
詳細ページを修正して book のデータを表示してみる。
app/views/books/show.html.erb に以下のコードを追加する。
<%= @book.title %>
ページをリロードして確認してみる。
エラーが出てしまった。エラー分によると先ほど追加したコードの部分でエラーが起きている。
rspec を実行してみる。
bundle e rspec spec/requests/books_spec.rb
結果はレッドだ。確かに、先ほど追加したコードが原因でアプリケーションが壊れてしまっている。
.F.....
Failures:
1) Books GET /show returns http success
Failure/Error: expect(response).to have_http_status(:success)
expected the response to have a success status code (2xx) but it was 500
# ./spec/requests/books_spec.rb:14:in `block (3 levels) in <main>'
Finished in 1.15 seconds (files took 4.62 seconds to load)
7 examples, 1 failure
Failed examples:
rspec ./spec/requests/books_spec.rb:12 # Books GET /show returns http success
先ほど追加したコードをコメントアウトしてみる。
<%#= @book.title %>
テストを実行する。
bundle e rspec spec/requests/books_spec.rb
グリーンになる。つまり、追加したコードが原因でエラーが起きていることが確実となる。
.......
Finished in 1.01 seconds (files took 4.76 seconds to load)
7 examples, 0 failures
コメントアウトしたコードを元に戻して修正を行う。
アプリケーションのログを見てみると以下のようなエラーが出ていることがわかる。
ActionView::Template::Error (undefined method `title' for nil:NilClass
'.freeze;@output_buffer.append=( @book.title );
^^^^^^):
1: <h1>Books#show</h1>
2: <p>Find me in app/views/books/show.html.erb</p>
3:
4: <%= @book.title %>
app/views/books/show.html.erb:4
undefined method `title' for nil:NilClass と表示されていることから、nil には title というメソッドが定義されていないということがわかる。
app/views/books/show.html.erb を以下のように修正する。
<%= @book %>
表示を確認する。
エラーが消え、何も表示されていない。そこで、以下のようにコードを修正する。
<%= @book.inspect %>
inspect というメソッドは
と記載されている。表示を確認する。
@book というデータを表示している箇所に nil が表示されている。つまり、@book という変数には nil が代入されている。
Railsではビューにデータを表示する際は、該当のコントローラのアクション内で変数を定義しなければならないというルールがある。 このルールにしたがって、コントローラのアクションを確認する。
def show
end
ルールにしたがって確認したところ、確かにアクション内に @book という変数は定義されていなかった。そのため、変数を定義するコードを追加する。
app/controllers/books_controller.rb に以下のコードを追加する。
def show
@book = Book.find(1)
end
テストを修正する。
spec/requests/books_spec.rb を以下のように修正。
describe "GET /books/:id" do
let(:book) { create(:book, id: 1) }
it "returns http success" do
get "/books/#{book.id}"
expect(response).to have_http_status(:success)
end
end
テストを実行する。グリーンになる。
app/views/books/show.html.erb tを以下のように変更しておく。
<%= @book.title %>
テストを実行する。
bundle e rspec spec/requests/books_spec.rb
グリーンになった。
.......
Finished in 0.95525 seconds (files took 4.8 seconds to load)
7 examples, 0 failures
テストが通ったのでデータが表示されることは担保されている。
表示を確認する。
期待通りデータが表示されている。
しかし問題がまだ残っている。
一覧ページに戻って、他のデータの詳細ページに遷移してみる。どのページに遷移しても 本1 というデータしか表示されない。
次に続く。
この記事が気に入ったらサポートをしてみませんか?