見出し画像

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 というメソッドは

オブジェクトを人間が読める形式に変換した文字列を返します。

https://docs.ruby-lang.org/ja/latest/method/Object/i/inspect.html

と記載されている。表示を確認する。


@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 というデータしか表示されない。
次に続く。


この記事が気に入ったらサポートをしてみませんか?