提交 e197d6f3 编写于 作者: J José Valim

Finally fix the bug where symbols and strings were not having the same behavior in the router.

If you were using symbols before for methods like match/get/post/put/delete, it is likely that this commit will break your routes.
Everything should behave the same if you are using strings, if not, please open up a ticket.
上级 4a90ecb3
...@@ -44,7 +44,8 @@ class Mapping #:nodoc: ...@@ -44,7 +44,8 @@ class Mapping #:nodoc:
IGNORE_OPTIONS = [:to, :as, :via, :on, :constraints, :defaults, :only, :except, :anchor, :shallow, :shallow_path, :shallow_prefix] IGNORE_OPTIONS = [:to, :as, :via, :on, :constraints, :defaults, :only, :except, :anchor, :shallow, :shallow_path, :shallow_prefix]
def initialize(set, scope, path, options) def initialize(set, scope, path, options)
@set, @scope, @options = set, scope, options @set, @scope = set, scope
@options = (@scope[:options] || {}).merge(options)
@path = normalize_path(path) @path = normalize_path(path)
normalize_options! normalize_options!
end end
...@@ -57,18 +58,11 @@ def to_route ...@@ -57,18 +58,11 @@ def to_route
def normalize_options! def normalize_options!
path_without_format = @path.sub(/\(\.:format\)$/, '') 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) if using_match_shorthand?(path_without_format, @options)
to_shorthand = @options[:to].blank? to_shorthand = @options[:to].blank?
@options[:to] ||= path_without_format[1..-1].sub(%r{/([^/]*)$}, '#\1') @options[:to] ||= path_without_format[1..-1].sub(%r{/([^/]*)$}, '#\1')
@options[:as] ||= path_without_format[1..-1].gsub("/", "_") @options[:as] ||= Mapper.normalize_name(path_without_format)
end end
@options.merge!(default_controller_and_action(to_shorthand)) @options.merge!(default_controller_and_action(to_shorthand))
...@@ -80,8 +74,8 @@ def using_match_shorthand?(path, options) ...@@ -80,8 +74,8 @@ def using_match_shorthand?(path, options)
end end
def normalize_path(path) def normalize_path(path)
raise ArgumentError, "path is required" if @scope[:path].blank? && path.blank? raise ArgumentError, "path is required" if path.blank?
path = Mapper.normalize_path("#{@scope[:path]}/#{path}") path = Mapper.normalize_path(path)
if path.match(':controller') if path.match(':controller')
raise ArgumentError, ":controller segment is not allowed within a namespace block" if @scope[:module] raise ArgumentError, ":controller segment is not allowed within a namespace block" if @scope[:module]
...@@ -93,7 +87,11 @@ def normalize_path(path) ...@@ -93,7 +87,11 @@ def normalize_path(path)
@options.reverse_merge!(:controller => /.+?/) @options.reverse_merge!(:controller => /.+?/)
end end
path if path.include?(":format")
path
else
"#{path}(.:format)"
end
end end
def app def app
...@@ -216,6 +214,10 @@ def self.normalize_path(path) ...@@ -216,6 +214,10 @@ def self.normalize_path(path)
path path
end end
def self.normalize_name(name)
normalize_path(name)[1..-1].gsub("/", "_")
end
module Base module Base
def initialize(set) #:nodoc: def initialize(set) #:nodoc:
@set = set @set = set
...@@ -324,13 +326,7 @@ def scope(*args) ...@@ -324,13 +326,7 @@ def scope(*args)
ActiveSupport::Deprecation.warn ":name_prefix was deprecated in the new router syntax. Use :as instead.", caller ActiveSupport::Deprecation.warn ":name_prefix was deprecated in the new router syntax. Use :as instead.", caller
end end
case args.first options[:path] = args.first if args.first.is_a?(String)
when String
options[:path] = args.first
when Symbol
options[:controller] = args.first
end
recover = {} recover = {}
options[:constraints] ||= {} options[:constraints] ||= {}
...@@ -362,8 +358,9 @@ def scope(*args) ...@@ -362,8 +358,9 @@ def scope(*args)
@scope[:blocks] = recover[:block] @scope[:blocks] = recover[:block]
end end
def controller(controller) def controller(controller, options={})
scope(controller.to_sym) { yield } options[:controller] = controller
scope(options) { yield }
end end
def namespace(path, options = {}) def namespace(path, options = {})
...@@ -444,9 +441,9 @@ def override_keys(child) ...@@ -444,9 +441,9 @@ def override_keys(child)
module Resources module Resources
# CANONICAL_ACTIONS holds all actions that does not need a prefix or # CANONICAL_ACTIONS holds all actions that does not need a prefix or
# a path appended since they fit properly in their scope level. # a path appended since they fit properly in their scope level.
VALID_ON_OPTIONS = [:new, :collection, :member] VALID_ON_OPTIONS = [:new, :collection, :member]
CANONICAL_ACTIONS = [:index, :create, :new, :show, :update, :destroy] RESOURCE_OPTIONS = [:as, :controller, :path, :only, :except]
RESOURCE_OPTIONS = [:as, :controller, :path, :only, :except] CANONICAL_ACTIONS = %w(index create new show update destroy)
class Resource #:nodoc: class Resource #:nodoc:
DEFAULT_ACTIONS = [:index, :create, :new, :show, :update, :destroy, :edit] DEFAULT_ACTIONS = [:index, :create, :new, :show, :update, :destroy, :edit]
...@@ -700,41 +697,27 @@ def match(*args) ...@@ -700,41 +697,27 @@ def match(*args)
return member { match(*args) } return member { match(*args) }
end end
path = options.delete(:path) if resource_scope?
raise ArgumentError, "can't define route directly in resource(s) scope"
end
action = args.first action = args.first
path = path_for_action(action, options.delete(:path))
if action.is_a?(Symbol) || (resource_method_scope? && action.to_s =~ /^[A-Za-z_]\w*$/) if action.to_s =~ /^[\w\/]+$/
path = path_for_action(action, path) options[:action] ||= action unless action.to_s.include?("/")
options[:action] ||= action
options[:as] = name_for_action(action, options[:as]) options[:as] = name_for_action(action, options[:as])
else
with_exclusive_scope do options[:as] = name_for_action(options[:as])
return super(path, options)
end
elsif resource_method_scope?
path = path_for_custom_action
options[:as] = name_for_action(options[:as]) if options[:as]
args.push(options)
with_exclusive_scope do
scope(path) do
return super
end
end
end
if resource_scope?
raise ArgumentError, "can't define route directly in resource(s) scope"
end end
args.push(options) super(path, options)
super
end end
def root(options={}) def root(options={})
if @scope[:scope_level] == :resources if @scope[:scope_level] == :resources
with_scope_level(:nested) do with_scope_level(:root) do
scope(parent_resource.path, :as => parent_resource.collection_name) do scope(parent_resource.path) do
super(options) super(options)
end end
end end
...@@ -871,7 +854,7 @@ def id_constraint ...@@ -871,7 +854,7 @@ def id_constraint
end end
def canonical_action?(action, flag) def canonical_action?(action, flag)
flag && CANONICAL_ACTIONS.include?(action) flag && resource_method_scope? && CANONICAL_ACTIONS.include?(action.to_s)
end end
def shallow_scoping? def shallow_scoping?
...@@ -882,18 +865,10 @@ def path_for_action(action, path) ...@@ -882,18 +865,10 @@ def path_for_action(action, path)
prefix = shallow_scoping? ? prefix = shallow_scoping? ?
"#{@scope[:shallow_path]}/#{parent_resource.path}/:id" : @scope[:path] "#{@scope[:shallow_path]}/#{parent_resource.path}/:id" : @scope[:path]
if canonical_action?(action, path.blank?) path = if canonical_action?(action, path.blank?)
"#{prefix}(.:format)" prefix.to_s
else
"#{prefix}/#{action_path(action, path)}(.:format)"
end
end
def path_for_custom_action
if shallow_scoping?
"#{@scope[:shallow_path]}/#{parent_resource.path}/:id"
else else
@scope[:path] "#{prefix}/#{action_path(action, path)}"
end end
end end
...@@ -913,6 +888,7 @@ def prefix_name_for_action(action, as) ...@@ -913,6 +888,7 @@ def prefix_name_for_action(action, as)
def name_for_action(action, as=nil) def name_for_action(action, as=nil)
prefix = prefix_name_for_action(action, as) prefix = prefix_name_for_action(action, as)
prefix = Mapper.normalize_name(prefix) if prefix
name_prefix = @scope[:as] name_prefix = @scope[:as]
if parent_resource if parent_resource
...@@ -922,15 +898,18 @@ def name_for_action(action, as=nil) ...@@ -922,15 +898,18 @@ def name_for_action(action, as=nil)
name = case @scope[:scope_level] name = case @scope[:scope_level]
when :collection when :collection
[name_prefix, collection_name] [prefix, name_prefix, collection_name]
when :new when :new
[:new, name_prefix, member_name] [prefix, :new, name_prefix, member_name]
when :member
[prefix, shallow_scoping? ? @scope[:shallow_prefix] : name_prefix, member_name]
when :root
[name_prefix, collection_name, prefix]
else else
[shallow_scoping? ? @scope[:shallow_prefix] : name_prefix, member_name] [name_prefix, member_name, prefix]
end end
name.unshift(prefix) name.select(&:present?).join("_").presence
name.select(&:present?).join("_")
end end
end end
......
...@@ -40,6 +40,13 @@ def self.matches?(request) ...@@ -40,6 +40,13 @@ def self.matches?(request)
get :new, :path => "build" get :new, :path => "build"
post :create, :path => "create", :as => "" post :create, :path => "create", :as => ""
put :update put :update
get :remove, :action => :destroy, :as => :remove
end
scope "pagemark", :controller => "pagemarks", :as => :pagemark do
get "new", :path => "build"
post "create", :as => ""
put "update"
get "remove", :action => :destroy, :as => :remove get "remove", :action => :destroy, :as => :remove
end end
...@@ -203,11 +210,12 @@ def self.matches?(request) ...@@ -203,11 +210,12 @@ def self.matches?(request)
end end
resources :customers do resources :customers do
get "recent" => "customers#recent", :on => :collection get :recent, :on => :collection
get "profile" => "customers#profile", :on => :member get "profile", :on => :member
get "secret/profile" => "customers#secret", :on => :member
post "preview" => "customers#preview", :as => :another_preview, :on => :new post "preview" => "customers#preview", :as => :another_preview, :on => :new
resource :avatar do resource :avatar do
get "thumbnail(.:format)" => "avatars#thumbnail", :as => :thumbnail, :on => :member get "thumbnail" => "avatars#thumbnail", :as => :thumbnail, :on => :member
end end
resources :invoices do resources :invoices do
get "outstanding" => "invoices#outstanding", :as => :outstanding, :on => :collection get "outstanding" => "invoices#outstanding", :as => :outstanding, :on => :collection
...@@ -648,15 +656,15 @@ def test_bookmarks ...@@ -648,15 +656,15 @@ def test_bookmarks
with_test_routes do with_test_routes do
get '/bookmark/build' get '/bookmark/build'
assert_equal 'bookmarks#new', @response.body assert_equal 'bookmarks#new', @response.body
assert_equal '/bookmark/build', new_bookmark_path assert_equal '/bookmark/build', bookmark_new_path
post '/bookmark/create' post '/bookmark/create'
assert_equal 'bookmarks#create', @response.body assert_equal 'bookmarks#create', @response.body
assert_equal '/bookmark/create', bookmark_path assert_equal '/bookmark/create', bookmark_path
put '/bookmark' put '/bookmark/update'
assert_equal 'bookmarks#update', @response.body assert_equal 'bookmarks#update', @response.body
assert_equal '/bookmark', update_bookmark_path assert_equal '/bookmark/update', bookmark_update_path
get '/bookmark/remove' get '/bookmark/remove'
assert_equal 'bookmarks#destroy', @response.body assert_equal 'bookmarks#destroy', @response.body
...@@ -664,6 +672,26 @@ def test_bookmarks ...@@ -664,6 +672,26 @@ def test_bookmarks
end end
end end
def test_pagemarks
with_test_routes do
get '/pagemark/build'
assert_equal 'pagemarks#new', @response.body
assert_equal '/pagemark/build', pagemark_new_path
post '/pagemark/create'
assert_equal 'pagemarks#create', @response.body
assert_equal '/pagemark/create', pagemark_path
put '/pagemark/update'
assert_equal 'pagemarks#update', @response.body
assert_equal '/pagemark/update', pagemark_update_path
get '/pagemark/remove'
assert_equal 'pagemarks#destroy', @response.body
assert_equal '/pagemark/remove', pagemark_remove_path
end
end
def test_admin def test_admin
with_test_routes do with_test_routes do
get '/admin', {}, {'REMOTE_ADDR' => '192.168.1.100'} get '/admin', {}, {'REMOTE_ADDR' => '192.168.1.100'}
...@@ -1564,6 +1592,7 @@ def test_custom_resource_routes_are_scoped ...@@ -1564,6 +1592,7 @@ def test_custom_resource_routes_are_scoped
with_test_routes do with_test_routes do
assert_equal '/customers/recent', recent_customers_path assert_equal '/customers/recent', recent_customers_path
assert_equal '/customers/1/profile', profile_customer_path(:id => '1') assert_equal '/customers/1/profile', profile_customer_path(:id => '1')
assert_equal '/customers/1/secret/profile', secret_profile_customer_path(:id => '1')
assert_equal '/customers/new/preview', another_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/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/outstanding', outstanding_customer_invoices_path(:customer_id => '1')
...@@ -1577,6 +1606,9 @@ def test_custom_resource_routes_are_scoped ...@@ -1577,6 +1606,9 @@ def test_custom_resource_routes_are_scoped
get '/customers/1/invoices/overdue' get '/customers/1/invoices/overdue'
assert_equal 'invoices#overdue', @response.body assert_equal 'invoices#overdue', @response.body
get '/customers/1/secret/profile'
assert_equal 'customers#secret', @response.body
end end
end end
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册