すでにメンバーの場合は

無料会員登録

GitHubアカウントで登録 Pikawakaが許可なくTwitterやFacebookに投稿することはありません。

登録がまだの方はこちらから

Pikawakaにログイン

GitHubアカウントでログイン Pikawakaが許可なくTwitterやFacebookに投稿することはありません。

Rails

【Rails】 resourcesメソッドを使ってルーティングを定義しよう!

ぴっかちゃん
ぴっかちゃん

resourcesメソッドとは、railsで定義されている7つのアクションのルーティングを自動で作成するメソッドです。 resourcesメソッドを使うことにより、簡単にルーティングを作成することができます。

routes.rb | resourcesメソッドの使い方-->
1
2
3
Rails.application.routes.draw do
  resources :コントローラー名
end

resourcesメソッドは、ルーティングを記述するroutes.rbの中で使用します。

resourcesメソッドの使い方

この章では、resourcesメソッドの使い方について解説します。

railsで定義されている7つのアクション

resourcesメソッドの説明の前にrailsで定義されている7つのアクションの確認をしてみましょう。

アクション名 役割
index リソースの一覧を表示させる
show リソースの詳細を表示させる
new 投稿フォームを表示させる
create リソースを追加させる
edit 更新フォームを表示させる
update リソースを更新させる
destroy リソースを削除する

こちらのルーティングをresourcesメソッドを使わず1つずつ定義した一例は下記のようになります。

routes.rb -->
1
2
3
4
5
6
7
8
9
Rails.application.routes.draw do
    get 'tweets'     => 'tweets#index'
    get 'tweets/:id' => 'tweets#show'
    get 'tweets/new' => 'tweets#new'
    post 'tweets' => 'tweets#create'
    get 'tweets/:id/edit' => 'tweets#edit'
    patch 'tweets/:id'  => 'tweets#update'
    delete 'tweets/:id' => 'tweets#destroy'
end

このようにそれぞれのアクションはもともと与えられた主な役割というのがあります。
アプリを作る際、何か機能を追加したい時は、まずは上の7つのアクションに当てはまるかを考えましょう。
できる限り、上の7つのアクションを利用することが大切です。

RESTとは

RESTとは、Representational State Transferの略です。
ユーザーが自分の好き勝手に機能を追加していくのではなく、あらかじめ決められたリソースを定義し、それに沿ってアクションとhttpメソッドを関連づけるという考え方です。

RESTを意識しながらアプリを作成していくとどのアプリも統一された書き方でコードが書かれるので、他人が書いたコードも非常に可読性が上がります。

RailsはこのRESTという概念を強く意識したフレームワークです。
resourcesメソッドは、RESTに基づくルーティングを自動的に作成してくれます。

▼ RESTについては、こちらの参考書で詳しく解説されています。Web系エンジニアになるために必要な知識が詰まっています!

webを支える技術
Webを支える技術 -HTTP、URI、HTML、そしてREST (WEB+DB PRESS plus)

Webサービスの実践的な設計について、包括的に解説されています。

resourcesの使い方

resourcesメソッドはルーティングを記述するroutes.rbの中で使用します。

routes.rb -->
1
2
3
Rails.application.routes.draw do
  resources :コントローラー名
end

上のように記述します。
例を見てみましょう。

routes.rb -->
1
2
3
Rails.application.routes.draw do
  resources :tweets
end

このように記述することによりtweetsコントローラーに上記の7つのアクションが自動で定義されました。
rails routesコマンドで確認すると下記のようになります。

ターミナル -->
1
2
3
4
5
6
7
8
9
             Prefix  Verb       URI Pattern                            Controller#Action
            tweets GET         /tweets(.:format)                tweets#index
                         POST      /tweets(.:format)                 tweets#create
    new_tweet GET         /tweets/new(.:format)        tweets#new
    edit_tweet GET         /tweets/:id/edit(.:format)   tweets#edit
             tweet GET         /tweets/:id(.:format)            tweets#show
                        PATCH    /tweets/:id(.:format)            tweets#update
                        PUT         /tweets/:id(.:format)            tweets#update
                        DELETE   /tweets/:id(.:format)            tweets#destroy

また下記のように記述すると複数のコントローラーのルーティングを一行で定義することができます。

routes.rb -->
1
2
3
4
5
6
Rails.application.routes.draw do
  resources :コントローラー名, :コントローラー名
end

# (例)usersコントローラーとhogesコントローラーの7つのアクションのルーティングが作られる
  resources :users, :hoges

onlyとexcept

resourcesメソッドを使用した際、indexアクションとshowアクションだけを指定したいときには下記のように記述します。

routes.rb -->
1
2
3
Rails.application.routes.draw do
  resources :tweets, only: [:index, :snow]
end

もしくは下記のように記述しても同じです。

routes.rb -->
1
2
3
Rails.application.routes.draw do
  resources :tweets, except: [:new, :create, :edit, :update, :destroy]
end

onlyはホワイトリスト系で、exceptはブラックリスト系になります。
どちらを使っても構いませんが、onlyを使ったほうが使用するアクションを明示的にできるので可読性が上がります。

このときにrails routesコマンドで確認すると下記のようになります。

ターミナル -->
1
2
3
   Prefix      Verb   URI Pattern                      Controller#Action
   tweets   GET    /tweets(.:format)            tweets#index
   tweet     GET    /tweets/:id(.:format)      tweets#show

このように非常にルーティングがスッキリしました。
特定のアクションしか使用しない場合はこのようにonlyexceptを使った方がルーティングの可読性が上がるので積極的に使いましょう。
※ルーティングがスッキリするだけでonlyexceptを絶対に使わなければいけないわけではありません。

Prefixとは?

一番左にPrefixとあります。
このPrefixは接頭辞とも呼ばれ、この後に_pathヘルパーをつけるとパスを返してくれるヘルパーメソッドとして使うことができます。

Prefixを確認するとルートパスを表す/の接頭辞はrootになっています。
なのでlink_toのパスを指定する場所には_pathをつけたroot_pathを書いてあげれば/というパスに変換してくれます。

パスにidが入っているときはidの情報が入っているインスタンスを引数として渡してあげることにより指定ができます。
例えばusersコントローラーのshowアクションを動かすときは通常のパスだとusers/"ユーザーのid"になりますが、Prefixを使って書くとuser_path(@user)のような記述になります。
上の@userはコントローラーで@user = User.find(params[:id])などで記述してあげれば@userの中にはそのユーザーのidも含まれているのでuser_pathの引数として指定できます。

ネストの定義の仕方

ルーティングがネストするときもresourcesメソッドを使うことができます。
その際の記述は下記のようになります。

routes.rb -->
1
2
3
  resources :tweets do
    resources :comments
  end

このように記述した場合のルーティングは下記のようになります。

ターミナル -->
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
                        Prefix   Verb                URI Pattern                  Controller#Action
  tweet_comments    GET         /tweets/:tweet_id/comments(.:format)            comments#index
                                     POST       /tweets/:tweet_id/comments(.:format)          comments#create
 new_tweet_review   GET         /tweets/:tweet_id/comments/new(.:format)      comments#new
edit_tweet_review    GET         /tweets/:tweet_id/comments/:id/edit(.:format) comments#edit
     tweet_review        GET         /tweets/:tweet_id/comments/:id(.:format)      comments#show
                                     PATCH    /tweets/:tweet_id/comments/:id(.:format)      comments#update
                                     PUT         /tweets/:tweet_id/comments/:id(.:format)      comments#update
                                     DELETE   /tweets/:tweet_id/comments/:id(.:format)      comments#destroy
                      tweets   GET         /tweets(.:format)                                                 tweets#index
                                     POST      /tweets(.:format)                                                 tweets#create
              new_tweet   GET         /tweets/new(.:format)                                          tweets#new
              edit_tweet   GET         /tweets/:id/edit(.:format)                                      tweets#edit
                       tweet   GET         /tweets/:id(.:format)                                             tweets#show
                                    PATCH    /tweets/:id(.:format)                                             tweets#update
                                    PUT         /tweets/:id(.:format)                                             tweets#update
                                    DELETE   /tweets/:id(.:format)                                            tweets#destroy

7つのアクション以外のルーティング設計

resoucesメソッドでrailsで定義されている7つのアクションを自動で定義できますが、それ以外のアクションを追加する場合はどうしたら良いでしょうか?

memberとcollection

7つのアクション以外のアクションを追加する場合はルーティングの中でmembercollectionを使用します。

memberの使い方

memberはidで指定した個々のリソースに対するアクションを定義できます。
ユーザーのレビューが見れるreviewアクションを追加したいとき、レビューは必ず1人のユーザーがしているものです。
なのでパスは下記のようにならなければなりません。

URL -->
1
/users/ユーザーのid/review

このようなルーティングを作りたいときは下記のようにmemberを使って記述します。

routes.rb -->
1
2
3
4
5
  resources :tweets do
    member do
      get 'review'
    end
  end

rails routesコマンドでルーティングを確認すると下記のようになります。

ターミナル -->
1
2
             Prefix  Verb   URI Pattern                                  Controller#Action
review_tweet  GET    /tweets/:id/review(.:format)   tweets#review

このようにパスの中にidが入った状態でルーティングが作成されます。

collectionの使い方

collectionはリソース全体に対するアクションを定義します。
今回はsearchアクションを定義してみます。

routes.rb -->
1
2
3
4
5
  resources :tweets do
    collection do
      get 'search'
    end
  end

rails routesコマンドでルーティングを確認すると下記のようになります。

ターミナル -->
1
2
               Prefix   Verb    URI Pattern                            Controller#Action
search_tweets   GET    /tweets/search(.:format)    tweets#search

このように全てのリソースに対してのアクションが定義できました。

membercollectionを使えば自分でアクション名を定義できますが、RESTの概念に沿ってできる限り7つのアクションを使用しましょう。

実際のアプリでresourcesメソッドを使ってみよう

この章では、アプリケーションにresourcesメソッドを使う場合について解説します。手を動かすことで理解が深まるので是非挑戦しましょう。

環境を構築する

それでは実際にアプリの中でresourcesメソッドを使ってみましょう。
下記のコマンドを一つずつ実行していきましょう。
①git clone -b resources https://github.com/miyagit/programan_dojo.git

② cd programan_dojo

③ bundle install
→ rbenv: version ‘2.4.1’ is not installed と表示された場合は、ruby -v と実行してください。

ruby -vと実行し出てきたversion(例: 2.3.1)と出てきたら、

vim .ruby-versionとし、
ruby -vで出てきた値(例: 2.3.1)に書き換えてください。

続いてvim Gemfileとし、ruby 2.4.1と書いてある部分をruby -vで出てきた値(例: 2.3.1)に書き換えてください。

④ rails db:create && rails db:migrate && rails db:seed

環境構築が完了しました。と表示されると、
本当にrails applicationが動作するかrails sコマンドで起動しましょう。

rails sを起動し、ブラウザでlocalhost: 3000と入力して下記のような画面が出てくれば環境構築完了です!

環境構築

ルーティングファイルを確認してみよう

現在ルートパスを入力するとmainコントローラーのtopアクションが動いたのでルーティングではそういう記述があるはずです。
config/routes.rbを開いてみましょう。

routes.rb -->
1
2
3
4
Rails.application.routes.draw do
  root 'main#top'
  get 'main' => 'main#top'
end

現在はこういう記述になっていることが確認できます。
では実際にrails routesコマンドでルーティングを確認してみましょう。

ターミナル -->
1
2
3
Prefix     Verb   URI Pattern           Controller#Action
   root     GET    /                             main#top
  main     GET    /main(.:format)    main#top

では次にresourcesメソッドを使ってルーティングを設定してみましょう。
config/routes.rbを下記のように編集してください。

routes.rb -->
1
2
3
4
Rails.application.routes.draw do
  root 'main#top'
  resources :main
end

ではrails routesコマンドでルーティングを確認してみましょう。

ターミナル -->
1
2
3
4
5
6
7
8
9
10
          Prefix    Verb         URI Pattern                        Controller#Action
             root    GET           /                                         main#top
 main_index    GET          /main(.:format)                main#index
                         POST       /main(.:format)                 main#create
   new_main     GET         /main/new(.:format)        main#new
   edit_main     GET         /main/:id/edit(.:format)   main#edit
            main     GET         /main/:id(.:format)            main#show
                         PATCH    /main/:id(.:format)            main#update
                         PUT         /main/:id(.:format)            main#update
                         DELETE   /main/:id(.:format)            main#destroy

このようにrailsで定義された7つのアクションが自動で定義されました。
ただ今回は7つのアクション以外のtopというアクションを使用しているため、今のままだとtopアクションへのルーティングが指定されていないため、エラーになってしまいます。
こういう場合はどうしたら良いのでしょうか。

railsの7つのアクションで定義されていないアクションを追加するにはmembercollectionを使うのでした。
今回は全てのリソースに対してアクションを追加するのでcollectionを使ってルーティングを定義します。

routes.rb -->
1
2
3
4
5
6
7
8
Rails.application.routes.draw do
  root 'main#top'
  resources :main do
    collection do
        get 'top'
    end
  end
end

rails routesコマンドで確認してみましょう。

ターミナル -->
1
2
3
4
5
6
7
8
9
10
11
                   Prefix   Verb           URI Pattern                        Controller#Action
                     root    GET            /                                         main#top
top_main_index    GET            /main/top(.:format)        main#top
        main_index     GET           /main(.:format)                main#index
                                 POST        /main(.:format)                 main#create
          new_main      GET          /main/new(.:format)        main#new
          edit_main      GET          /main/:id/edit(.:format)   main#edit
                   main      GET          /main/:id(.:format)            main#show
                                  PATCH    /main/:id(.:format)            main#update
                                  PUT         /main/:id(.:format)            main#update
                                  DELETE   /main/:id(.:format)            main#destroy

このようにアクションが追加されました。
今回はルートでもmainコントローラーのtopアクションを指定してるので2つになっています。

この記事のまとめ

  • resourcesメソッドとは、railsで定義されている7つのアクションのルーティングを自動で作成するメソッド
  • 簡単にルーティングを作成することが出来る
  • RESTに基づくルーティングを自動的に作成する