LoginSignup
0
1

More than 5 years have passed since last update.

Railsのルーティングでオプションの優先度をコントロールする記法

Last updated at Posted at 2016-12-13

ルーティングの記法

RailsでオプションのURLを記述する際に括弧をつけるとオプションになることはよく知られていると思います。
例えば/posts/:idではidが必須扱いになりますが、/posts/(:id)ではidがオプション扱いになります。

get '/posts/:id' => 'posts#show' # idは必須
get '/posts/(:id)' => 'posts#show' # idがなくてもposts_controller#showが呼び出される

(このぐらいのルーティングならresourcesで書くことをオススメします)

この時にposts/1ではparams: {id: 1}posts/ではparams: {}となってアクションの処理を行います。

オプションが2つ以上あって複数マッチする時

しかし、オプションが2つあった時に扱いはどうなるでしょうか。

get '/posts/(category_:parent_category_id)/(category_:category_id)/:id' => 'posts#show'

この時、posts/category_1/category_2/3にアクセスするとparams: {parent_category_id: 1, category_id: 2, id: 3}と認識されます。意図通りの動作です。
カテゴリが指定されていない場合posts/3にアクセスするとparams: {id: 3}となりこれも意図通りの動作になります。

しかし、カテゴリが1階層だった場合posts/category_2/3params: {parent_category_id: 2, id: 3}と認識されます。
これは意図通りではなくて

'期待していたもの': {category_id: 2, id: 3}
'実際のもの': {parent_category_id: 2, id: 3}

だと思います。

期待していたルーティングの動作をさせるために以下の記法で書けば大丈夫でした。
(結構長い間ハマってました)

get '/posts/((category_:parent_category_id)/category_:category_id)/:id' => 'posts#show'

括弧の中に括弧で書くと優先度が変わるという話でした。よくよく考えてみると納得の動作です。
これで

posts/category_2/3にアクセスするとparams: {category_id: 2, id: 3}というパラメータが得られます。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1