Ruby on Rails プログラミング 日記投稿サービスを1から作る

【Rails初心者】showの定義/link_toの使い方 日記投稿サービスを作る #3

前回の記事(#2)では、newとcreateの違いに触れつつ、new/createアクションを定義しました。

実際にブラウザから投稿を作成し、投稿一覧で表示させることができました。

今回は、showアクションを定義し、各々の投稿のページを作成していきます。

さらにリンクを作成して、一覧ページから各々の投稿のページに移動できるようにしていきます。

早速やっていきます!

showアクションを定義

posts_controller.rbを開き、以下のように記述します。

  def show
    @post = Post.find(params[:id])
  end

詳しくみていきます。

@postはインスタンス変数ですね。

インスタンス変数については、こちらの記事で詳しく解説しているので、ぜひ参考にしてください。

簡単に言えば、インスタンス変数に格納することで、showメソッドを抜け出しても、変数が使えるというわけです。

findメソッドは、モデルをidによって検索してくれるメソッドです。

paramsメソッドは、送信された値の受け渡しをするメソッドです。

params[:カラム]のように書いて、モデルのカラムを指定してあげることで、送信されたパラメータからそのカラムの値を取り出してくれます。

今回は、params[:id]としているので、idカラムを値として取り出してくれています。

つまり、

@post = Post.find(params[:id])は、

「@post(インスタンス変数)に、idによって探したPost(投稿)を格納する」

という感じですね。

viewの作成

controllerにshowアクションを定義できましたね。

次に、viewを作成していきます。

view/postsフォルダに新たに「show.html.erb」というファイルを作成します。

show.html.erbを開き、次にように記述します。

<h1>投稿</h1>

<p><%= @post.title %></p>
<p><%= @post.body %></p>

@post.titleで、Postモデルのtitleカラムを、

@post.bodyで、Postモデルのbodyカラムを、

それぞれ呼び出してます。

ルーティングの設定

showアクションについて、controllerとviewができましたね。

次に、ルーティングを設定します。

routes.rbを開き、以下のように記述します。

get 'posts/:id', to: 'posts#show', as: 'post'

これの意味は、

「GETメソッド(HTTPメソッドの1つ)で、「posts/:id」というリクエスト(URL)があったら、postsコントローラーのshowアクションを呼び出す。また、パス(path)は「post」に名付ける」

という意味ですね。

HTTPメソッドやルーティングの設定については、こちらの記事で詳しく解説しています。

一応ルーティングがちゃんと設定されているかを確認します。

terminalで以下のコマンドを実行します。

$rails routes

すると、

mbp:ibs_diary miyacha$ rails routes
                               Prefix Verb   URI Pattern                                                                              Controller#Action
                                posts GET    /posts(.:format)                                                                         posts#index
                             new_post GET    /posts/new(.:format)                                                                     posts#new
                                      POST   /posts(.:format)                                                                         posts#create
                                 post GET    /posts/:id(.:format)                                                                     posts#show

となりました。うまくできてるみたいです。

では、ブラウザで確認してみます。

localhost:3000/posts/1

にアクセスします。(idが1のPostのshowページです。)

うまく表示できていますね。

URLにいちいち「localhost:3000/posts/1」と打ち込むのは面倒なので、一覧ページ(index)からshowに飛べるようにします。

link_toを使ってページを移動

index.html.erbを開き、以下のように書き加えます。

<h1>投稿一覧</h1>

<% @posts.each do |post| %>
  <p><%= post.title %></p>
  <p><%= post.body %></p>

<!--ここから追記したやつ-->
  <p><%= link_to post.title, post_path(post) %></p>

<% end %>

ちょっと復習かつ余談(undefined method `title' for nil:NilClass)

上の「@posts.each do |post|」の書き方については、

indexアクションを定義した時に詳しくやりました。

posts_controllerのindexアクションで、@posts = Post.allと定義したので、@postsには作成された投稿の全てが格納されています。

そして、<% @posts.each do |post| %>から、<% end %>までは、各々のPost(投稿)を「post」という文字列で扱うようになってます。

私はこれを忘れて、「@post」としてしまって、なんどもエラーを起こしています。

ちなみに@postとしてしまった時にでたエラーは以下です。

エラー文 「undefined method `title' for nil:NilClass」

は、「nilのtitleメソッドなんぞ定義されてない」という感じですね。

「@post.title」の@postが定義されていないため「nil」となってしまい、「nil.title」という形になっているわけですね。

以上、余談でした。

話に戻ります。

link_toについて

<%= link_to post.title, post_path(post) %>

のように

「link_to 表示する文字、 飛ばす先のURLまたはパス(path)」

と記述することで、「表示する文字」をクリックすると、指定したURLに飛べるようになります。

今回は、

link_to post.title, post_path(post)

としているので、Postモデルのtitleカラムを表示させ、それをクリックすると、そのPostのshowページに飛べるようになっています。

post_path(post)

post_path(post)と、pathの横に(post)がついてますね。

これは引数ですね。

showのpathは、Postモデルのidを必要とします。

terminalでrails routesを実行してみると、

mbp:ibs_diary miyacha$ rails routes
                               Prefix Verb   URI Pattern                                                                              Controller#Action
                                posts GET    /posts(.:format)                                                                         posts#index
                             new_post GET    /posts/new(.:format)                                                                     posts#new
                                      POST   /posts(.:format)                                                                         posts#create
                                 post GET    /posts/:id(.:format)                                                                     posts#show

となりました。

6行目をみると、「/post/:id」となっているので、showのpathは、Postモデルのidを必要とすることがわかりますね。

indexとnewアクションと比べて考えてみても、

Postの一覧を表示する「index」や、Postを新たに作成する「new」とは違い、

「show」は、postの各々のページなので、そのpostのidを必要とするのは明らかですね。

なので、indexやnewのpathを書くときは、「posts_path」や「new_post_path」としたのに対し、

showのpathを書く際は、「post_path(引数)」と引数をあたえる必要があります。

なので、

post_path(post)

と書いてあるのですね。

また余談

またちょっと余談なのですが、

pathに渡す引数で、「post_path(post)」としてありますが、「post_path(post.id)」でも行けました。

引数として渡された変数が、とりあえずidの値を持っていればいいということなんですかね。。謎です。

以上、余談でした。

では、indexのviewからshowのviewに移動するための準備ができたので、ようやくですが、ブラウザを見てみます。

localhost:3000/postsにアクセスしてみます。

いい感じです。

「title

body

リンクのtitle」

という形になっていますね。

titleは2つもいらないので、一番上のtitleをリンクにして、下のlink_toは消しておきます。

いい感じにできましたね。

まとめ

今回は、showアクションについて解説しました。

ここまでご覧いただきありがとうございます!

© 2021 みやちゃのブログ Powered by AFFINGER5