Skip to content

Commit

Permalink
Allow routes to be declared off namespaces
Browse files Browse the repository at this point in the history
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@6783 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
  • Loading branch information
Tobias Lütke committed May 19, 2007
1 parent a995b9c commit 1008535
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 25 deletions.
7 changes: 7 additions & 0 deletions 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]
Expand Down
20 changes: 0 additions & 20 deletions actionpack/lib/action_controller/resources.rb
Expand Up @@ -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)
Expand Down
37 changes: 34 additions & 3 deletions actionpack/lib/action_controller/routing.rb
Expand Up @@ -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
Expand All @@ -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

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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?
Expand Down Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion actionpack/test/controller/resources_test.rb
Expand Up @@ -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|
Expand Down
44 changes: 43 additions & 1 deletion actionpack/test/controller/routing_test.rb
Expand Up @@ -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)

Expand All @@ -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|
Expand Down

0 comments on commit 1008535

Please sign in to comment.