scopeでtwitterっぽいルーティング
「Ruby on Rails 3 アプリケーションプログラミング」のルーティングの項をパラパラとめくっていたら、scopeを使ってtwitterっぽくトップレベル(?)にユーザ名を持ってくるようなルーティングができることを知ったのでメモ。
概要
例えばroutes.rbには次のように記述したとする。
scope ':uid' do resources :todos end
このとき次のようなURLでアクセスすると、USERNAMEの部分をparams[:uid]で受け取ることができる。
http://scope-routing-sample.dev/USERNAME/todos
サンプルアプリを作ってみた
早速サンプルのTODOアプリを作ってgithubに上げてみた:scope-routing-sample
次の手順で動く、はず(bundler, rvm, pow, powderが導入済みの前提で)。
$ git cloen git@github.com:a2ikm/scope-routing-sample.git $ cd scope-routing-sample $ rvm use 1.8.7@scope-routing-sample --create $ bundle $ powder $ rake db:migrate $ open http://scope-routing-sample.dev/
開いたら、
- 適当にユーザを登録(Uidは半角英数字がベター)
- 一覧の画面でUidをクリックして開く
- さぁURLを確認!
ハマったところ
app/views/todos/_form.html.erbにあるform_forがちょっと面倒くさかった。
ただのresourcesなら
form_for(@todo) do |f|
のような記述でよしなにやってもらえるんだけど、今回の場合には、
- :uidに何が入るのかを指定する必要がある
- Todoのインスタンスが保存済みか否かで:idを指定するか否かが変わる
ため、一工夫する必要があった(form_for and scopes, rails 3 - stackoverflowを参考にした)。
form_for(@todo, :url => (@todo.persisted? ? todo_path(:id => @todo.id, :uid => @uid) : todos_path(:uid => params[:uid]))) do |f|
こうすることで、fには@todoに関するオブジェクトが入り、action属性のURLにはtodo_pathとtodos_pathが適宜切り替えられ、:idと:uidを指定することができる。
まとめ
- scopeを使ったルーティングはカッコイイかもしれない
- form_forで一工夫が必要
scopeをネストすればgithubみたいにUSERNAME/PROJECTNAMEみたいなURLも作れるのかな?今度試してみよう。