Railsルーティングとは
Webアプリケーションでは、特定のURLにアクセスがあった際にどのコントローラーのどのアクションを呼び出すかを決める役割を持っています。
これをルーティングと言います。
ルーティングの基本的な役割
ルーティングの役割は、URLとコントローラーのアクションを結びつけることです。
例えば、ユーザーがwww.example.com/posts
にアクセスしたときに、PostsController
のindex
アクションを呼び出すことがルーティングの役割です。
ルーティングの書き方
RailsのルーティングはDSL(独自の記法)を用いて記述します。config/routes.rb
の中で、Rails.application.routes.draw do
とend
の間にルーティングの設定を書きます。
基本的なルーティングの書き方
最も基本的なルーティングの書き方は、HTTPメソッド 'URLパターン', to: 'コントローラー名#アクション名'
という形です。
Rails.application.routes.draw do
get '/posts', to: 'posts#index'
end
この設定は、「/posts」へのGETリクエストが来たら、PostsController
のindex
アクションを呼び出すというルーティングを定義しています。
resourcesメソッドによるルーティングの書き方
Railsでは、一般的なCRUD操作を行うためのルーティングを一度に生成するresources
メソッドが用意されています。
Rails.application.routes.draw do
resources :posts
end
この一行の設定で、posts
リソース(PostsController
)に対する7つのアクション(index
, new
, create
, show
, edit
, update
, destroy
)に対応するルーティングが全て生成されます。
可能な限り、resources
メソッドを使ってルーティングを定義することをおすすめします。
ルートパスについて
ルートパスとは、アプリケーションのトップページ(ホームページ)に対応するパスのことを指します。
ルートパスはroot
メソッドを使って設定し、root_path
がヘルパーメソッドになっています。
ルートパスの設定方法
ルートパスは以下のように設定します。
Rails.application.routes.draw do
root 'welcome#index'
end
# viewファイルでの書き方の例
<%= link_to "トップページ", root_path %>
これは、「/」へのGETリクエストが来たらWelcomeController
のindex
アクションを呼び出すというルーティングを定義しています。
そして、この設定によりroot_path
とroot_url
という2つのヘルパーメソッドが自動的に定義されます。
ルートパスはアプリケーションの入口となるため、適切に設定することが重要です。
root
メソッドは、resources
メソッドと併用することもできます。
Rails.application.routes.draw do
root to: 'welcome#index'
resources :posts
end
Railsの基本アクションに対するヘルパーメソッドの詳細
Railsアプリケーションではresources
メソッドでルーティングを定義することにより、基本のアクション(index、showなど)に対するヘルパーメソッドも自動的に作成されます。
以下では、それぞれのアクションと対応するヘルパーメソッドについて詳しく説明します。
なお、ヘルパーメソッドとは、ビュー内やコントローラー内で使用できるメソッドのことを指します。
ヘルパーメソッドを使うことで、パスやURLを簡単に生成できるようになります。
indexアクションのヘルパーメソッド
resources :posts
と定義すると、posts_path
とposts_url
という名前付きルートのヘルパーメソッドが生成されます。これらは、PostsController
のindex
アクション(ブログ一覧ページ)へのパスやURLを返します。
posts_path # => "/posts"
posts_url # => "http://www.example.com/posts"
showアクションのヘルパーメソッド
post_path(post)
とpost_url(post)
は、PostsController
のshow
アクション(ブログ詳細ページ)へのパスやURLを返します。ここで、引数にはパスやURLに含めるリソースのインスタンス(ここではPost
モデルのインスタンス)を渡します。
@post = Post.find(1)
post_path(@post) # => "/posts/1"
post_path(@post.id) # => "/posts/1" # IDを渡しても同じ結果になる
post_url(@post) # => "http://www.example.com/posts/1"
このルーティングはよく使うことになります。
例えば、データ作成に成功した後にそのデータの詳細ページにリダイレクトする場合などに使います。
def create
@post = Post.new(post_params)
if @post.save
redirect_to post_path(@post)
else
render :new
end
end
newアクションのヘルパーメソッド
new_post_path
とnew_post_url
は、新規ブログ作成ページ(new
アクション)へのパスやURLを返します。
new_post_path # => "/posts/new"
new_post_url # => "http://www.example.com/posts/new"
editアクションのヘルパーメソッド
edit_post_path(post)
とedit_post_url(post)
は、ブログ編集ページ(edit
アクション)へのパスやURLを返します。これらのヘルパーメソッドにはパスやURLに含めるブログのインスタンスを引数として渡します。
@post = Post.find(1)
edit_post_path(@post) # => "/posts/1/edit"
edit_post_path(@post.id) # => "/posts/1/edit" # IDを渡しても同じ結果になる
edit_post_url(@post) # => "http://www.example.com/posts/1/edit"
例えば、一覧画面の中に編集ボタンを設置し、そのボタンをクリックしたら編集ページに遷移するような場合に使います。
<% @posts.each do |post| %>
<tr>
<td><%= post.title %></td>
<td><%= post.body %></td>
<td><%= link_to 'Edit', edit_post_path(post) %></td>
</tr>
<% end %>
destroyアクションのヘルパーメソッド
delete_post_path(post)
とdelete_post_url(post)
は、ブログ削除(destroy
アクション)へのパスやURLを返します。これらのヘルパーメソッドには削除対象のブログのインスタンスを引数として渡します。
例えば、削除ボタンを設置し、そのボタンをクリックしたら該当のブログを削除するような場合に使います。
<% @posts.each do |post| %>
<tr>
<td><%= post.title %></td>
<td><%= post.body %></td>
<td><%= link_to 'Delete', delete_post_path(post), method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
以上が、Railsの基本的な7アクションに対するヘルパーメソッドの一覧です。これらのヘルパーメソッドを理解し活用することで、Railsアプリケーションのルーティングを効率的に管理することができます。
名前付きルートとは
名前付きルートとは、特定のURLに名前をつけてパスを生成するためのヘルパーメソッドのことを指します。具体的な名前付きルートの定義の仕方と使用法について見ていきましょう。
名前付きルートの定義
名前付きルートはconfig/routes.rb
の中でas:
オプションを用いて定義します。以下の例では、/
へのGETリクエストをwelcome#index
にルーティングすると共に、そのルートに対するヘルパーメソッドとしてroot_path
とroot_url
を定義しています。
Rails.application.routes.draw do
get '/', to: 'welcome#index', as: 'root'
end
ここで、as:
オプションで指定した名前から_path
と_url
をつけたヘルパーメソッドが生成されます。
名前付きルートの使用
上記で定義した名前付きルートは、ビュー内やコントローラー内で以下のように使用できます。
root_path # => "/"
root_url # => "http://www.example.com/"
_path
と_url
の違いは、_path
が相対パスを、_url
が絶対URLを返す点です。
ルーティングの確認方法と読み方
ルーティングの設定が正しく行われているかを確認するためには、rake routes
コマンド(または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
各カラムの意味は以下の通りです。
Prefix
: 名前付きルートのプレフィクス(ヘルパーメソッドの接頭辞)Verb
: リクエストのHTTPメソッド(GET、POST、PATCH、PUT、DELETE)URI Pattern
: マッチするURLのパターンController#Action
: リクエストがマッチしたときに呼び出されるコントローラーとアクション
よくある間違い
ルーティングの設定は、アプリケーションの動作に大きく影響するため、書き方のミスは重大な問題を引き起こす可能性があります。
ここでは、よくあるルーティングの書き方のミスとその対策について説明します。
ルーティングの重複
一つのリクエストに対して複数のルーティングがマッチすると、予期せぬアクションが呼び出される可能性があります。
ルーティングは上から順にマッチングが行われ、最初にマッチしたルーティングが適用されます。
Rails.application.routes.draw do
get '/posts/:id', to: 'posts#show'
get '/posts/new', to: 'posts#new' # ここが呼び出されない
end
上記の例では、/posts/new
へのリクエストが/posts/:id
のルーティングにマッチしてしまうため、posts#new
は呼び出されません。
この問題を解決するには、具体的なパスのルーティングを先に書くか、resources
メソッドを使ってルーティングを生成します。
resourcesメソッドの使用法の誤り
resources
メソッドは、CRUD操作を一度に定義できる強力なメソッドですが、その使用法を誤ると意図しないルーティングが生成されることがあります。
Rails.application.routes.draw do
resources :posts, only: [:show]
get '/posts', to: 'posts#index'
end
上記の例では、resources
メソッドで:show
アクションのルーティングのみを生成した後で、/posts
へのルーティングを別途定義しています。
しかし、この場合、resources
メソッドで:index
アクションのルーティングも一緒に生成するのが適切です。
indexヘルパーメソッドに引数を渡す
index
アクションのヘルパーメソッドには引数を渡すことができません。
Rails.application.routes.draw do
resources :posts
end
上記の例では、posts_path
というヘルパーメソッドが生成されますが、このヘルパーメソッドに引数を渡すことはできません。
NGの例
posts_path(1) # => ArgumentError
OK の例
post_path(1) # => "/posts/1"
showヘルパーメソッドに引数を渡さない
show
アクションのヘルパーメソッドには引数を渡す必要があります。
Rails.application.routes.draw do
resources :posts
end
上記の例では、post_path
というヘルパーメソッドが生成されますが、このヘルパーメソッドに引数を渡さないとエラーになります。
NGの例
post_path # => ArgumentError
OK の例
post_path(1) # => "/posts/1"