From 10085359058f8b04a061eed1d2c1e44971ae4303 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20L=C3=BCtke?= Date: Sat, 19 May 2007 16:26:44 +0000 Subject: [PATCH] Allow routes to be declared off namespaces git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@6783 5ecf4fe2-1ee6-0310-87b1-e25e094e27de --- actionpack/CHANGELOG | 7 +++ actionpack/lib/action_controller/resources.rb | 20 --------- actionpack/lib/action_controller/routing.rb | 37 ++++++++++++++-- actionpack/test/controller/resources_test.rb | 2 +- actionpack/test/controller/routing_test.rb | 44 ++++++++++++++++++- 5 files changed, 85 insertions(+), 25 deletions(-) diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG index 917874accafcc..567c8d278f698 100644 --- a/actionpack/CHANGELOG +++ b/actionpack/CHANGELOG @@ -1,5 +1,12 @@ *SVN* +* Allow routes to be decalred under namespaces [Tobias Luetke]: + + map.namespace :admin do |admin| + admin.root :controller => "products" + admin.feed 'feed.xml', :controller => 'products', :action => 'feed', :format => 'xml' + end + * Update to script.aculo.us 1.7.1_beta3. [Thomas Fuchs] * observe_form always sends the serialized form. #5271 [manfred, normelton@gmail.com] diff --git a/actionpack/lib/action_controller/resources.rb b/actionpack/lib/action_controller/resources.rb index df0c64d91cc80..bb92684e5c7eb 100644 --- a/actionpack/lib/action_controller/resources.rb +++ b/actionpack/lib/action_controller/resources.rb @@ -339,26 +339,6 @@ def resource(*entities, &block) entities.each { |entity| map_singleton_resource(entity, options.dup, &block) } end - # Enables the use of resources in a module by setting the name_prefix, path_prefix, and namespace for the model. - # Example: - # - # map.namespace(:admin) do |admin| - # admin.resources :products, - # :has_many => [ :tags, :images, :variants ] - # end - # - # This will create admin_products_url pointing to "admin/products", which will look for an Admin::ProductsController. - # It'll also create admin_product_tags_url pointing to "admin/products/#{product_id}/tags", which will look for - # Admin::TagsController. - def namespace(name, options = {}, &block) - if options[:namespace] - with_options({:path_prefix => "#{options.delete(:path_prefix)}/#{name}", :name_prefix => "#{options.delete(:name_prefix)}#{name}_", :namespace => "#{options.delete(:namespace)}#{name}/" }.merge(options), &block) - else - with_options({ :path_prefix => name.to_s, :name_prefix => "#{name}_", :namespace => "#{name}/" }.merge(options), &block) - end - end - - private def map_resource(entities, options = {}, &block) resource = Resource.new(entities, options) diff --git a/actionpack/lib/action_controller/routing.rb b/actionpack/lib/action_controller/routing.rb index be5eb164a119b..00d5050b7eb26 100644 --- a/actionpack/lib/action_controller/routing.rb +++ b/actionpack/lib/action_controller/routing.rb @@ -870,6 +870,14 @@ def segment_for(string) # and requirements. 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 + requirements = (options.delete(:requirements) || {}).dup defaults = (options.delete(:defaults) || {}).dup conditions = (options.delete(:conditions) || {}).dup @@ -879,7 +887,7 @@ def divide_route_options(segments, options) hash = (path_keys.include?(key) && ! value.is_a?(Regexp)) ? defaults : requirements hash[key] = value end - + [defaults, requirements, conditions] end @@ -961,7 +969,9 @@ def ensure_required_segments(segments) def build(path, options) # Wrap the path with slashes path = "/#{path}" unless path[0] == ?/ - path = "#{path}/" unless path[-1] == ?/ + path = "#{path}/" unless path[-1] == ?/ + + path = "/#{options[:path_prefix]}#{path}" if options[:path_prefix] segments = segments_for_route_path(path) defaults, requirements, conditions = divide_route_options(segments, options) @@ -1010,6 +1020,26 @@ def root(options = {}) def named_route(name, path, options = {}) @set.add_named_route(name, path, options) end + + # Enables the use of resources in a module by setting the name_prefix, path_prefix, and namespace for the model. + # Example: + # + # map.namespace(:admin) do |admin| + # admin.resources :products, + # :has_many => [ :tags, :images, :variants ] + # end + # + # This will create admin_products_url pointing to "admin/products", which will look for an Admin::ProductsController. + # It'll also create admin_product_tags_url pointing to "admin/products/#{product_id}/tags", which will look for + # Admin::TagsController. + def namespace(name, options = {}, &block) + if options[:namespace] + with_options({:path_prefix => "#{options.delete(:path_prefix)}/#{name}", :name_prefix => "#{options.delete(:name_prefix)}#{name}_", :namespace => "#{options.delete(:namespace)}#{name}/" }.merge(options), &block) + else + with_options({:path_prefix => name, :name_prefix => "#{name}_", :namespace => "#{name}/" }.merge(options), &block) + end + end + def method_missing(route_name, *args, &proc) super unless args.length >= 1 && proc.nil? @@ -1193,7 +1223,8 @@ def add_route(path, options = {}) end def add_named_route(name, path, options = {}) - named_routes[name] = add_route(path, options) + name = options[:name_prefix] + name.to_s if options[:name_prefix] + named_routes[name.to_sym] = add_route(path, options) end def options_as_params(options) diff --git a/actionpack/test/controller/resources_test.rb b/actionpack/test/controller/resources_test.rb index 1f61377ad9f8d..979008f21b7c6 100644 --- a/actionpack/test/controller/resources_test.rb +++ b/actionpack/test/controller/resources_test.rb @@ -427,7 +427,7 @@ def test_resources_using_namespace assert_simply_restful_for :products, :controller => "backoffice/products" end end - + protected def with_restful_routing(*args) with_routing do |set| diff --git a/actionpack/test/controller/routing_test.rb b/actionpack/test/controller/routing_test.rb index 0197bf10e2bda..2abccd7402f90 100644 --- a/actionpack/test/controller/routing_test.rb +++ b/actionpack/test/controller/routing_test.rb @@ -1691,7 +1691,7 @@ def test_generate_with_default_action url = set.generate(:controller => "people", :action => "list") assert_equal "/people/list", url end - + def test_root_map Object.const_set(:PeopleController, Class.new) @@ -1705,6 +1705,48 @@ def test_root_map ensure Object.send(:remove_const, :PeopleController) end + + + def test_namespace + Object.const_set(:Api, Module.new { |m| m.const_set(:ProductsController, Class.new) }) + + set.draw do |map| + + map.namespace 'api' do |api| + api.route 'inventory', :controller => "products", :action => 'inventory' + end + + end + + request.path = "/api/inventory" + request.method = :get + assert_nothing_raised { set.recognize(request) } + assert_equal("api/products", request.path_parameters[:controller]) + assert_equal("inventory", request.path_parameters[:action]) + ensure + Object.send(:remove_const, :Api) + end + + + def test_namespaced_root_map + Object.const_set(:Api, Module.new { |m| m.const_set(:ProductsController, Class.new) }) + + set.draw do |map| + + map.namespace 'api' do |api| + api.root :controller => "products" + end + + end + + request.path = "/api" + request.method = :get + assert_nothing_raised { set.recognize(request) } + assert_equal("api/products", request.path_parameters[:controller]) + assert_equal("index", request.path_parameters[:action]) + ensure + Object.send(:remove_const, :Api) + end def test_generate_finds_best_fit set.draw do |map|