少し前にsendagaya.rbで発表したRails3のAdvanced Constraintsをここでも紹介。
routes.rbの中でURLを定義する時にsubdomainとかを条件に含めるときに使うのがconstraintsというオプションなんですが、これを使ってURLの「?」以降を条件にしたりもできます。
方法はrequestオブジェクトを受け付けるmatches?というメソッドを実装したクラスを定義してインスタンスをconstraintsに渡してあげるだけです。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
ここではpostというリソースの集合であるindex、つまり /posts というURLにGETで ?q=hoge 等のパラメータが付いている時に posts_controller#search というアクションに紐付けるということを行なっています。
ただしこのままだと q に対するvalueが空の状態 /posts?q でもsearchアクションに処理が渡るので、コントローラ側で何かしらの対応が必要です。
基本的にはrequestオブジェクトを使って判別できるならどんな条件でもいいので、Accept-languageで振り分けるとかIPアドレスでブラックリストを作るとかもできてしまいます。
今回はindexアクションの中でifで分岐させておくことでも十分対応可能ですが、render以外はほとんど共通処理がないよとかになると、アクションそのものを分けてしまったほうが綺麗なコードになりそうですよね。
0 コメント:
コメントを投稿