ビューで引数なしでnamed routeを使ったときdefault_url_optionsが無視されるのに対処

Rails2.1 で、ビューで引数なしの named route を使ったときdefault_url_options が無視されるバグがあった。

対処法:

class ApplicationController < ActionController::Base
  ...
  helper_method :default_url_options
  ...
end

してやれば、OK。


解説:
named routeは、action_controller/routing/route_set.rb の define_url_helper() でevalして作成されてるんだけど、

  ...
  @module.module_eval <<-end_eval # We use module_eval to avoid leaks
    def #{selector}(*args)
      #{generate_optimisation_block(route, kind)}
      ...

generate_optimisation_block() は、

  "return #{generation_code} if #{guard_condition}\n"

てな感じになっていて、guard_condition が真なら url_for(遅い)を使わないで文字列連結したURL(generation_code)が返されて速ぇー、というもの。

guard_condition には、

(!defined?(default_url_options) || default_url_options.blank?) && ...

てな感じで、default_url_options は一応考慮されてるんだけれども、これの実行コンテキストが、ビューから named route を呼んだ場合、ActionView::Base になってしまって、ActionView::Base に default_url_options はないので、nil となり、guard_condition が真になって、url_forを使わない方が実行されちゃうって理由。


引数ありの場合は、guard_condition の別の条件に引っかかって、普通に url_for が実行されるので、問題が起こらないという。


疲れた。


あとでパッチ書くかも。
action_controller/routing/route_set.rb の install_helpers() あたりで加えてやればいいんじゃなかろうかと予想。