2012年8月20日月曜日

Rails3でクエリパラメータでルーティング(Advanced Constraints)

少し前にsendagaya.rbで発表したRails3のAdvanced Constraintsをここでも紹介。

routes.rbの中でURLを定義する時にsubdomainとかを条件に含めるときに使うのがconstraintsというオプションなんですが、これを使ってURLの「?」以降を条件にしたりもできます。

方法はrequestオブジェクトを受け付けるmatches?というメソッドを実装したクラスを定義してインスタンスをconstraintsに渡してあげるだけです。

class QueryParameterConstraint
def initialize(*keys)
@keys = keys
end
def matches?(request)
result = false
@keys.each do |key|
result = request.query_parameters.has_key?(key)
break unless result
end
result
end
end
MyApp::Application.routes.draw do
resources :posts do
get '/', to: :search, as: :search, on: :collection,
constraints: QueryParameterConstraint.new(:q)
end
end
view raw routes.rb hosted with ❤ by GitHub

ここではpostというリソースの集合であるindex、つまり /posts というURLにGETで ?q=hoge 等のパラメータが付いている時に posts_controller#search というアクションに紐付けるということを行なっています。

ただしこのままだと q に対するvalueが空の状態 /posts?q でもsearchアクションに処理が渡るので、コントローラ側で何かしらの対応が必要です。

基本的にはrequestオブジェクトを使って判別できるならどんな条件でもいいので、Accept-languageで振り分けるとかIPアドレスでブラックリストを作るとかもできてしまいます。

今回はindexアクションの中でifで分岐させておくことでも十分対応可能ですが、render以外はほとんど共通処理がないよとかになると、アクションそのものを分けてしまったほうが綺麗なコードになりそうですよね。

0 コメント:

コメントを投稿