Railsのroutesを読む

最近既存のコードを引き継ぐ形でRailsを触り始めました。
Railsの経験はなかったのですが、まあコード読めばわかるだろう、と思っていたら大間違い。
どうも不思議な魔法で動いているみたいで、コードを読んでもさっぱりわかりません。というか読むコードがありません。
そんな状態だった私がチュートリアルなどを読んで、とりあえずroutesについてわかったことをまとめてみます。
わかったことだけなので網羅はしてないです。間違いもあるかもしれないので、あったら指摘してもらえるとうれしいです。

[Ruby on Rails チュートリアル](https://railstutorial.jp/)
このチュートリアルとても良くできています。
テストのことはもちろん、GitとかBootstrapなどRails以外の周辺知識にも触れています。
最終的にTwitterもどきを作るのですが、ログイン周りとかフォロワーをどうモデル化するかとか、題材が実用的でとても役立ちそうな感じがします。

# routes.rbとは
名前の通りですが、ルーティングを記述するファイルです。
URLをどのコントローラのどのアクションで処理するかを記述します。

## 特定のパスへのマッピング
見た目わかりやすくて助かります。

```rb:config/routes.rb
get   '/about', to: 'static_pages#about' # 例1
post  '/about', controller: 'static_pages', action: 'about' # 例2
match '/about', to: 'static_pages#about', via: [:get, :post] # 例3
match '/about', to: 'static_pages#about', via: :all # 例4
get   '/about', to: 'static_pages#about', as: 'aboutabout' # 例5
```

上記の例は、`/about`というURLへのアクセスを`StaticPages`(コントローラ)の`about`(アクション)で処理する、という意味になります。
メソッドは、`get`,`post`,`patch`,`put`,`delete`が使えます。
例1はコントローラとアクションをまとめて書く方法で、`to:`のあとに`'コントローラ名#アクション'`と書きます。コントローラの名前の謎については[こちら](http://railstutorial.jp/chapters/static_pages?version=5.0#sec-generated_static_pages)をどうぞ。
例2のように、コントローラとアクションは別々に書くこともできます。
例3のように、`match`を使うと複数のメソッドを同じアクションに紐付けることができます。全てのメソッドを紐付けるには、例4のように`:all`が使えます。あまり使う機会はなさそうですが。
Railsでは名前付きルートというものがあるのですが、例5のように`:as`を使うことで名前付きルートの名前を変えることができます。
名前付きルートについては下記が分かりやすかったです。
[Railsにおけるリンクの記述方法とそのテスト](http://qiita.com/kidach1/items/d704e7eb63513c3831ae)

パラメータを使う場合は以下になります。単一セグメントにマッチするものと複数セグメントにマッチするものがあります。併用することもできます。

```rb:config/routes.rb
get   '/about/:id', to: 'static_pages#about' # 例1
get   '/about/*segment', to: 'static_pages#about' # 例2
get   '/about/*segment/:id', to: 'static_pages#about' # 例3
```

例1では`/about/1`や`/about/hoge`などにマッチします。`params[:id]`は`1`や`hoge`になります。
例2では`/about/hoge/fuga`や`/about/Fizz/Buzz/FizzBuzz`などにマッチします。`params[:segment]`は`hoge/fuga`や`Fizz/Buzz/FizzBuzz`になります。
例3では、例えば`/about/a/b/c/1`にマッチし、`params[:segment]`は`a/b/c`、`params[:id]`は`1`になります。

APIサーバなんかだとjsonを返したいことは多いと思いますが、そんなときは以下のように書くと良いです。

```rb:config/routes.rb
get   '/about', to: 'static_pages#about', defaults: {format: :json}
```

こうすることで、`/about`にアクセスした時に、`/about.json`にアクセスしたことにしてくれます。

## ルートへのマッピング
ルートについては特別な記法が用意されています。

```rb:config/routes.rb
root  'static_pages#home'
```

これで`/`へのアクセスを`StaticPages`(コントローラ)の`home`(アクション)で処理させることができます。

## リソース(複数)へのマッピング
こちらの方がRails的にはスタンダードらしいです。RESTfulなリソースにするために必要なマッピングを定義してくれます。例えばリソースがユーザの場合こうです。

```rb:config/routes.rb
resources :users
```

なんと一行書くだけで、以下と同じ効果があります。

```rb
get    '/users',          to: 'users#index'   # ユーザ一覧ページ
get    '/users/:id',      to: 'users#show'    # 特定のユーザページ
get    '/users/new',      to: 'users#new'     # ユーザ登録ページ
post   '/users',          to: 'users#create'  # ユーザ作成
get    '/users/:id/edit', to: 'users#edit'    # 特定のユーザ編集ページ
patch  '/users/:id',      to: 'users#update'  # 特定のユーザ更新
delete '/users/:id',      to: 'users#destroy' # 特定のユーザ削除
```

Ha ha ha,it's magic!!すごいですね。

ただ、いつもいつも全部必要なわけではありません。そんなときは`only:`と`except:`が使えます。
単語の意味どおり、`only:`は書いたものだけ、`except:`は書いたもの以外のマッピングが定義されます。

```rb:config/routes.rb
resources :users, only: [:index, :show]
resources :devices, except: [:destroy]
```

## リソース(単一)へのマッピング
ものによっては特定のリソースごとのページは必要ないということもあります。そんなときはこちらを使います。
例えばウルトラユーザと言うものが一人だけいたとすると以下のようになります。

```rb:config/routes.rb
resource :ultra_user
```

以下と同じ効果があります。複数のときにあった`:id`が軒並み消えます。

```rb
get    '/ultra_user',          to: 'ultra_users#show'    # ウルトラユーザページ
get    '/ultra_user/new',      to: 'ultra_users#new'     # ウルトラユーザ登録ページ
post   '/ultra_user',          to: 'ultra_users#create'  # ウルトラユーザ作成
get    '/ultra_user/edit',     to: 'ultra_users#edit'    # ウルトラユーザ編集ページ
patch  '/ultra_user',          to: 'ultra_users#update'  # ウルトラユーザ更新
delete '/ultra_user',          to: 'ultra_users#destroy' # ウルトラユーザ削除
```

## 名前空間を作る
グループ化したいときに名前空間を使用できます。

```rb:config/routes.rb
namespace :admin do
  root  'static_pages#home'
  get 'about', to: 'static_pages#about'
end
```

上の例だと、`/admin/`が`StaticPages`の`home`に、`/admin/about`が`StaticPages`の`about`にそれぞれマッピングされます。

# おわりに
一応最低限は書いたつもりでいますが、まだまだルーティングは色々あります。
ちゃんと知りたい方は下の参考を見てみてください。
Railsは初期学習コストは高めだなあと思いました。なんとなく既存のコードを読むだけでは理解できませんでした。ちゃんとルールを把握する必要があります。
ただ、開発効率はすごくいいんだろうなあ、とも思います。なんたってあんまりコード書かなくて済むので。
早く慣れてサクサク開発ができるようになりたいです。

## 参考
[Ruby on Rails チュートリアル](https://railstutorial.jp/)
[Rails のルーティング](https://railsguides.jp/routing.html)