提交 9b4514c3 编写于 作者: A Andrew White

Copy literal route constraints to defaults - fixes #3571 and #6224.

上级 0d48b12f
## Rails 4.0.0 (unreleased) ##
* Copy literal route constraints to defaults so that url generation know about them.
The copied constraints are `:protocol`, `:subdomain`, `:domain`, `:host` and `:port`.
*Andrew White*
* `respond_to` and `respond_with` now raise ActionController::UnknownFormat instead
of directly returning head 406. The exception is rescued and converted to 406
in the exception handling middleware. *Steven Soroka*
......
require 'active_support/core_ext/hash/except'
require 'active_support/core_ext/hash/reverse_merge'
require 'active_support/core_ext/hash/slice'
require 'active_support/core_ext/object/blank'
require 'active_support/core_ext/enumerable'
require 'active_support/inflector'
......@@ -100,6 +101,10 @@ def normalize_options!
raise ArgumentError, "Regexp multiline option not allowed in routing requirements: #{requirement.inspect}"
end
end
if @options[:constraints].is_a?(Hash)
(@options[:defaults] ||= {}).reverse_merge!(defaults_from_constraints(@options[:constraints]))
end
end
# match "account/overview"
......@@ -245,6 +250,11 @@ def default_controller
def default_action
@options[:action] || @scope[:action]
end
def defaults_from_constraints(constraints)
url_keys = [:protocol, :subdomain, :domain, :host, :port]
constraints.slice(*url_keys).select{ |k, v| v.is_a?(String) || v.is_a?(Fixnum) }
end
end
# Invokes Rack::Mount::Utils.normalize path and ensure that
......@@ -641,6 +651,10 @@ def scope(*args)
block, options[:constraints] = options[:constraints], {}
end
if options[:constraints].is_a?(Hash)
(options[:defaults] ||= {}).reverse_merge!(defaults_from_constraints(options[:constraints]))
end
scope_options.each do |option|
if value = options.delete(option)
recover[option] = @scope[option]
......@@ -849,6 +863,11 @@ def merge_shallow_scope(parent, child) #:nodoc:
def override_keys(child) #:nodoc:
child.key?(:only) || child.key?(:except) ? [:only, :except] : []
end
def defaults_from_constraints(constraints)
url_keys = [:protocol, :subdomain, :domain, :host, :port]
constraints.slice(*url_keys).select{ |k, v| v.is_a?(String) || v.is_a?(Fixnum) }
end
end
# Resource routing allows you to quickly declare all of the common routes
......
......@@ -47,7 +47,7 @@ def test_assert_recognizes
def test_assert_recognizes_with_extras
assert_recognizes({ :controller => 'articles', :action => 'index', :page => '1' }, '/articles', { :page => '1' })
end
def test_assert_recognizes_with_method
assert_recognizes({ :controller => 'articles', :action => 'create' }, { :path => '/articles', :method => :post })
assert_recognizes({ :controller => 'articles', :action => 'update', :id => '1' }, { :path => '/articles/1', :method => :put })
......@@ -57,7 +57,7 @@ def test_assert_recognizes_with_hash_constraint
assert_raise(ActionController::RoutingError) do
assert_recognizes({ :controller => 'secure_articles', :action => 'index' }, 'http://test.host/secure/articles')
end
assert_recognizes({ :controller => 'secure_articles', :action => 'index' }, 'https://test.host/secure/articles')
assert_recognizes({ :controller => 'secure_articles', :action => 'index', :protocol => 'https://' }, 'https://test.host/secure/articles')
end
def test_assert_recognizes_with_block_constraint
......@@ -90,7 +90,7 @@ def test_assert_routing_with_hash_constraint
assert_raise(ActionController::RoutingError) do
assert_routing('http://test.host/secure/articles', { :controller => 'secure_articles', :action => 'index' })
end
assert_routing('https://test.host/secure/articles', { :controller => 'secure_articles', :action => 'index' })
assert_routing('https://test.host/secure/articles', { :controller => 'secure_articles', :action => 'index', :protocol => 'https://' })
end
def test_assert_routing_with_block_constraint
......
......@@ -2606,3 +2606,45 @@ def app; Routes end
assert_raises(ActionController::RoutingError) { product_path(nil) }
end
end
class TestUrlConstraints < ActionDispatch::IntegrationTest
Routes = ActionDispatch::Routing::RouteSet.new.tap do |app|
app.draw do
ok = lambda { |env| [200, { 'Content-Type' => 'text/plain' }, []] }
constraints :subdomain => 'admin' do
get '/' => ok, :as => :admin_root
end
scope :constraints => { :protocol => 'https://' } do
get '/' => ok, :as => :secure_root
end
get '/' => ok, :as => :alternate_root, :constraints => { :port => 8080 }
end
end
include Routes.url_helpers
def app; Routes end
test "constraints are copied to defaults when using constraints method" do
assert_equal 'http://admin.example.com/', admin_root_url
get 'http://admin.example.com/'
assert_response :success
end
test "constraints are copied to defaults when using scope constraints hash" do
assert_equal 'https://www.example.com/', secure_root_url
get 'https://www.example.com/'
assert_response :success
end
test "constraints are copied to defaults when using route constraints hash" do
assert_equal 'http://www.example.com:8080/', alternate_root_url
get 'http://www.example.com:8080/'
assert_response :success
end
end
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册