map.resources と map.connect における namespace

Controllerクラスを指定したときに微妙に違いがあるので注意、と。


  map.namespace("blog", :path_prefix => "components/blog") do |map2|
    map2.resources :users, :controller => "wj_users"
    map2.connect "blogs/:blog_id/tagged_with/:tagname",
    :controller => "entries", :action => "tagged_with"
  end

上記のように namespace メソッドを呼び出す。この rake routes の結果で期待されるのは

...(略)...
    DELETE /components/blog/users/:id.:format                   {:controller=>"blog/wj_users", :action=>"destroy"}
                                /components/blog/blogs/:blog_id/tagged_with/:tagname {:controller=>"<span style="font-weight:bold;">blog/entries</span>", :action=>"tagged_with"}

であるが、実際には次のようになる。

...(略)...
    DELETE /components/blog/users/:id.:format                   {:controller=>"blog/wj_users", :action=>"destroy"}
                                /components/blog/blogs/:blog_id/tagged_with/:tagname {:controller=>"<span style="font-weight:bold;">components/blog/entries</span>", :action=>"tagged_with"}

これは、:controllerを決定する際に、:namespace と :path_prefix の扱いが多少違うことに起因する。

まず、map.resources のほう。 action_controller/lib/resources.rb に次のようなメソッドで定義されている。

class Resource
  ..(snip)..
  def initialize(entities, options)
    @plural   ||= entities
    @singular ||= options[:singular] || plural.to_s.singularize
    @options = options

  ..(snip)..

  end

  def controller
    @controller ||= "#{options[:namespace]}#{(options[:controller] || plural).to_s}"
  end
end

つまり、:namespace + (:controller || {resources の第一引数}) ということになる。

一方、map.connect のほう。:controllerが決定されるのは、action_controller/lib/routing.rb のdivide_route_optionsというメソッド。

  def divide_route_options(segments, options)
    options = options.dup
    if options[:namespace]
      options[:controller] = "#{options[:path_prefix]}/#{options[:controller]}"
      options.delete(:path_prefix)
      options.delete(:name_prefix)
      options.delete(:namespace)
    end
    ..(snip)..
  end

どういうことか知らないけれど、:path_prefix + :controller になっている。Gitの最新版をみたけど、そちらも同じ。

さてさて。。どういうコンセプトなんだか。