Permalink
Browse files

Ensure shortcuts inside resources also generates helpers.

  • Loading branch information...
1 parent edba51c commit 4a90ecb3adff8426aeddee0594c2b68f408e4af1 @josevalim josevalim committed Aug 24, 2010
Showing with 43 additions and 52 deletions.
  1. +39 −48 actionpack/lib/action_dispatch/routing/mapper.rb
  2. +4 −4 actionpack/test/dispatch/routing_test.rb
View
87 actionpack/lib/action_dispatch/routing/mapper.rb
@@ -43,9 +43,9 @@ def constraint_args(constraint, request)
class Mapping #:nodoc:
IGNORE_OPTIONS = [:to, :as, :via, :on, :constraints, :defaults, :only, :except, :anchor, :shallow, :shallow_path, :shallow_prefix]
- def initialize(set, scope, args)
- @set, @scope = set, scope
- @path, @options = extract_path_and_options(args)
+ def initialize(set, scope, path, options)
+ @set, @scope, @options = set, scope, options
+ @path = normalize_path(path)
normalize_options!
end
@@ -54,31 +54,16 @@ def to_route
end
private
- def extract_path_and_options(args)
- options = args.extract_options!
-
- if using_to_shorthand?(args, options)
- path, to = options.find { |name, value| name.is_a?(String) }
- options.merge!(:to => to).delete(path) if path
- else
- path = args.first
- end
-
- if path.match(':controller')
- raise ArgumentError, ":controller segment is not allowed within a namespace block" if @scope[:module]
-
- # Add a default constraint for :controller path segments that matches namespaced
- # controllers with default routes like :controller/:action/:id(.:format), e.g:
- # GET /admin/products/show/1
- # => { :controller => 'admin/products', :action => 'show', :id => '1' }
- options.reverse_merge!(:controller => /.+?/)
- end
-
- [ normalize_path(path), options ]
- end
def normalize_options!
path_without_format = @path.sub(/\(\.:format\)$/, '')
+ @options = (@scope[:options] || {}).merge(@options)
+
+ if @scope[:as] && !@options[:as].blank?
+ @options[:as] = "#{@scope[:as]}_#{@options[:as]}"
+ elsif @scope[:as] && @options[:as] == ""
+ @options[:as] = @scope[:as].to_s
+ end
if using_match_shorthand?(path_without_format, @options)
to_shorthand = @options[:to].blank?
@@ -89,19 +74,26 @@ def normalize_options!
@options.merge!(default_controller_and_action(to_shorthand))
end
- # match "account" => "account#index"
- def using_to_shorthand?(args, options)
- args.empty? && options.present?
- end
-
# match "account/overview"
def using_match_shorthand?(path, options)
path && options.except(:via, :anchor, :to, :as).empty? && path =~ %r{^/[\w\/]+$}
end
def normalize_path(path)
raise ArgumentError, "path is required" if @scope[:path].blank? && path.blank?
- Mapper.normalize_path("#{@scope[:path]}/#{path}")
+ path = Mapper.normalize_path("#{@scope[:path]}/#{path}")
+
+ if path.match(':controller')
+ raise ArgumentError, ":controller segment is not allowed within a namespace block" if @scope[:module]
+
+ # Add a default constraint for :controller path segments that matches namespaced
+ # controllers with default routes like :controller/:action/:id(.:format), e.g:
+ # GET /admin/products/show/1
+ # => { :controller => 'admin/products', :action => 'show', :id => '1' }
+ @options.reverse_merge!(:controller => /.+?/)
+ end
+
+ path
end
def app
@@ -233,8 +225,8 @@ def root(options = {})
match '/', options.reverse_merge(:as => :root)
end
- def match(*args)
- mapping = Mapping.new(@set, @scope, args).to_route
+ def match(path, options=nil)
+ mapping = Mapping.new(@set, @scope, path, options || {}).to_route
@set.add_route(*mapping)
self
end
@@ -389,21 +381,6 @@ def defaults(defaults = {})
scope(:defaults => defaults) { yield }
end
- def match(*args)
- options = args.extract_options!
-
- options = (@scope[:options] || {}).merge(options)
-
- if @scope[:as] && !options[:as].blank?
- options[:as] = "#{@scope[:as]}_#{options[:as]}"
- elsif @scope[:as] && options[:as] == ""
- options[:as] = @scope[:as].to_s
- end
-
- args.push(options)
- super(*args)
- end
-
private
def scope_options
@scope_options ||= private_methods.grep(/^merge_(.+)_scope$/) { $1.to_sym }
@@ -957,10 +934,24 @@ def name_for_action(action, as=nil)
end
end
+ module Shorthand
+ def match(*args)
+ if args.size == 1 && args.last.is_a?(Hash)
+ options = args.pop
+ path, to = options.find { |name, value| name.is_a?(String) }
+ options.merge!(:to => to).delete(path)
+ super(path, options)
+ else
+ super
+ end
+ end
+ end
+
include Base
include HttpHelpers
include Scoping
include Resources
+ include Shorthand
end
end
end
View
8 actionpack/test/dispatch/routing_test.rb
@@ -203,9 +203,9 @@ def self.matches?(request)
end
resources :customers do
- get "recent" => "customers#recent", :as => :recent, :on => :collection
- get "profile" => "customers#profile", :as => :profile, :on => :member
- post "preview" => "customers#preview", :as => :preview, :on => :new
+ get "recent" => "customers#recent", :on => :collection
+ get "profile" => "customers#profile", :on => :member
+ post "preview" => "customers#preview", :as => :another_preview, :on => :new
resource :avatar do
get "thumbnail(.:format)" => "avatars#thumbnail", :as => :thumbnail, :on => :member
end
@@ -1564,7 +1564,7 @@ def test_custom_resource_routes_are_scoped
with_test_routes do
assert_equal '/customers/recent', recent_customers_path
assert_equal '/customers/1/profile', profile_customer_path(:id => '1')
- assert_equal '/customers/new/preview', preview_new_customer_path
+ assert_equal '/customers/new/preview', another_preview_new_customer_path
assert_equal '/customers/1/avatar/thumbnail.jpg', thumbnail_customer_avatar_path(:customer_id => '1', :format => :jpg)
assert_equal '/customers/1/invoices/outstanding', outstanding_customer_invoices_path(:customer_id => '1')
assert_equal '/customers/1/invoices/2/print', print_customer_invoice_path(:customer_id => '1', :id => '2')

0 comments on commit 4a90ecb

Please sign in to comment.