前回の記事(#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アクションについて解説しました。
ここまでご覧いただきありがとうございます!