url_for(ポリモーフィックなモデルのインスタンス) をやろうとしたときにちょっとハマったので、自分用めも。
前提としては、
- view/controller以外からurl_forを使いたい
- でも、
Routing
とかUrlHelpers
とかはincludeしたくない...
など。2点めがポイント。
[1] pry(main)> Rails.application.routes.url_helpers.url_for(like.likeable)
ActionController::UrlGenerationError: No route matches ・・・(以下略
😨
url_forの定義
UrlHelperの先でRoutingUrlForみたいなモジュールが読まれてて、そこで
actionview/lib/action_view/routing_url_for.rbから抜粋
method = _generate_paths_by_default ? :path : :url
builder = ActionDispatch::Routing::PolymorphicRoutes::HelperMethodBuilder.send(method)
case options
when Symbol
builder.handle_string_call(self, options)
when Class
builder.handle_class_call(self, options)
else
builder.handle_model_call(self, options)
end
みたいな感じで定義されてる。
ActionDispatch::Routing::PolymorphicRoutes::HelperMethodBuilder を使ってみる
こいつ だ。中でいろいろ頑張ってくれている、うん。(ちゃんと読んでない
ということで、
def path_for(hogeable)
builder = ActionDispatch::Routing::PolymorphicRoutes::HelperMethodBuilder.send(:path)
builder.handle_model_call(Rails.application.routes.url_helpers, hogeable)
end
def url_for(hogeable)
builder = ActionDispatch::Routing::PolymorphicRoutes::HelperMethodBuilder.send(:url)
builder.handle_model_call(Rails.application.routes.url_helpers, hogeable)
end
みたいに定義すれば
[1] pry(main)> path_for(like.likeable)
=> "/blogs/1"
キタ━━━━(゚∀゚)━━━━!!
ってなります。
さいごに
確かに、どこからでもurl_for呼ぶことはできた。
でも、たぶん本来こういう使い方しなくてもいいように考えてね、ってのがRailsの思想なんだろうなー・・・