このLessonではコントローラについて学習していきます。
コントローラもモデル同様Classです。コントローラに書かれているPublicなインスタンスメソッドの事をactionと言います。
モデルを操作するためのコントローラ名は必ずModelの複数形で全て小文字にしましょう。resourcesのルーティングと相まってコード記述をシンプルにすることができます。
また、モデル名が複数単語である場合は全て小文字で単語をアンダースコアで区切るスネークケースという記法にし、最後の単語を複数形にしましょう。
例
UserPostモデルを操作するコントローラ※モデルを操作しないコントローラ名は任意の名称で大丈夫です。
コントローラ作成の構文は以下になります。
$ rails generate controller コントローラ名
もちろんgenerateを短縮形にすることができます。以下も同様に動作します。
$ rails g controller コントローラ名
$ rails destroy controller コントローラ名
以下も同じ処理になります。
$ rails d controller コントローラ名
こちらの削除コマンドを実行することで、自動生成されたファイルやルートも削除されます。
基本がわかったところでコントローラを作成しましょう。
Postモデルを操作するためのコントローラ名はモデル名の小文字複数形のpostsコントローラにしましょう。
$ rails g controller posts create app/controllers/posts_controller.rb invoke erb create app/views/posts invoke test_unit create test/controllers/posts_controller_test.rb invoke helper create app/helpers/posts_helper.rb invoke test_unit invoke assets invoke coffee create app/assets/javascripts/posts.coffee invoke scss create app/assets/stylesheets/posts.scss
create表示になっているものが自動で生成されているファイルになります。
app/controllers/posts_controller.rbがコントローラ本体となり、同時にコントローラと同じ名前のhelper、JavaScriptファイル、SCSSファイルが生成されることも覚えておきましょう。
そしてviewsにもコントローラと同名のディレクトリ「app/views/posts」ができていることも重要なポイントです。
それでは投稿一覧ページを作成していきましょう。
resourcesのルーティングで学習したように、一覧ページはindexアクションであると学習しました。
それではindexアクションから作成していきます。
app/controllers/posts_controller.rbを開いて以下のように編集して保存してください。
class PostsController < ApplicationController def index @posts = Post.all end end
indexアクションというのはコントローラ(Class)のインスタンスメソッドのことです。
この中にインスタンス変数@postsを定義しました。インスタンス変数名は任意のもので結構ですが、Postモデルの全てのインスタンスが入るPost.allの結果を代入するものなので、複数形の@postsとしています。
インスタンス変数名はすべて小文字で、単語の区切りを_で繋ぐスネークケース(snake_case)という記法にすると良いでしょう。class名の様に大文字から始めて(UpperCamelCase)はいけません。
では次にviewを作成しましょう。アクションに対応するデフォルトviewのファイルは規則があります。
app/views/コントローラ名/アクション名.html.erb
よってposts#indexのviewは 「app/views/posts/index.html.erb」ファイルとなります。
このファイルを作成し、内容を以下のようにして保存してください。
<h1>みんなの投稿一覧</h1> <% @posts.each do |post| %> <%= post.content %><br> <% end %>
記載できましたらサーバを起動してposts#indexのルーティングになっているURIへアクセスしましょう。
resourcesで生成されるルートを覚えていない方はルートを確認してください(覚えていない方はこちらを暗記できるようになっておきましょう。)。
$ rails routes
Prefix Verb URI Pattern Controller#Action
posts GET /posts(.:format) posts#index
POST /posts(.:format) posts#create
new_post GET /posts/new(.:format) posts#new
edit_post GET /posts/:id/edit(.:format) posts#edit
post GET /posts/:id(.:format) posts#show
PATCH /posts/:id(.:format) posts#update
PUT /posts/:id(.:format) posts#update
DELETE /posts/:id(.:format) posts#destroy
posts#indexは GETで 「/posts」にアクセスすれば良いことがわかりますね。ブラウザのURLの末尾に /posts をつけるとGETメソッドでリクエストされますから、postsコントローラのindexアクションが実行され、対応する views/posts/index.html.erb が表示されます。
「http://localhost:3000/posts」にアクセスするとみんなの投稿ページが表示され、今まで作成した3件の投稿が表示されましたか?
「http://localhost:3000/posts」というURLで投稿一覧を表示することができましたが、TOPページ「http://localhost:3000/ 」はRailsのデフォルトページのままです。
アプリらしくTOPページを作成していきましょう。
今回は今作成したposts#indexの投稿一覧ページをTOPページにしていきたいと思います。
confix/routes.rbファイルを開いて以下のように設定してください。
Rails.application.routes.draw do root 'posts#index' resources :posts end
rootの行を追加してください。
rootの行ではTOPページを表示するコントローラとアクションを指定します。
root 'コントローラ名#アクション名'
保存しましたらルーティングを確認しましょう。
$ rails routes Prefix Verb URI Pattern Controller#Action root GET / posts#index posts GET /posts(.:format) posts#index POST /posts(.:format) posts#create new_post GET /posts/new(.:format) posts#new edit_post GET /posts/:id/edit(.:format) posts#edit post GET /posts/:id(.:format) posts#show PATCH /posts/:id(.:format) posts#update PUT /posts/:id(.:format) posts#update DELETE /posts/:id(.:format) posts#destroy
root の行が増えていますね。
TOPページは「/」のURLでGETリクエストと決まっています。
サーバを起動し、ブラウザでTOPページ(http://localhost:3000/)にアクセスしてみましょう。
デフォルトページではなく「みんなの投稿一覧」が表示されましたか?
これでTOPページの作成ができました。
ここでみんなの投稿一覧ページが「/」と「/posts」の二つのページで表示されるのはちょっと変ですね。そこで、/postsのページのルーティングを削除して、TOPページだけで表示させてみましょう。
config/routes.rbを以下のように編集します。
Rails.application.routes.draw do root 'posts#index' resources :posts, except: [:index] end
exceptオプションは resourcesで自動生成される7つのルートから除外したいルートを指定するオプションとなります。
今回はposts#indexがrootと内容が被るためルートから除外しました。
ルーティングも確認してみましょう。
$ rails routes
Prefix Verb URI Pattern Controller#Action
root GET / posts#index
POST /posts(.:format) posts#create
new_post GET /posts/new(.:format) posts#new
edit_post GET /posts/:id/edit(.:format) posts#edit
post GET /posts/:id(.:format) posts#show
PATCH /posts/:id(.:format) posts#update
PUT /posts/:id(.:format) posts#update
DELETE /posts/:id(.:format) posts#destroy
ルーティングから除外されていますね。
除外した以前のURLにもアクセスしてみましょう。「http://localhost:3000/posts」にアクセスしてみてください。
Routing Errorが出ました。「GET + /posts」のルーティングから除外したためにこのURLが無効になったことを意味します。
使っていないURL、不要なURLはセキュリティ上残しておくのは好ましくありませんので不要なルートは除外するようにしましょう。