1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

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

This commit is contained in:
Andrew White 2012-05-11 07:23:24 +01:00
parent 0d48b12fc5
commit 9b4514c3b8
4 changed files with 69 additions and 3 deletions

View file

@ -1,5 +1,10 @@
## Rails 4.0.0 (unreleased) ## ## 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 * `respond_to` and `respond_with` now raise ActionController::UnknownFormat instead
of directly returning head 406. The exception is rescued and converted to 406 of directly returning head 406. The exception is rescued and converted to 406
in the exception handling middleware. *Steven Soroka* in the exception handling middleware. *Steven Soroka*

View file

@ -1,5 +1,6 @@
require 'active_support/core_ext/hash/except' require 'active_support/core_ext/hash/except'
require 'active_support/core_ext/hash/reverse_merge' 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/object/blank'
require 'active_support/core_ext/enumerable' require 'active_support/core_ext/enumerable'
require 'active_support/inflector' require 'active_support/inflector'
@ -100,6 +101,10 @@ module ActionDispatch
raise ArgumentError, "Regexp multiline option not allowed in routing requirements: #{requirement.inspect}" raise ArgumentError, "Regexp multiline option not allowed in routing requirements: #{requirement.inspect}"
end end
end end
if @options[:constraints].is_a?(Hash)
(@options[:defaults] ||= {}).reverse_merge!(defaults_from_constraints(@options[:constraints]))
end
end end
# match "account/overview" # match "account/overview"
@ -245,6 +250,11 @@ module ActionDispatch
def default_action def default_action
@options[:action] || @scope[:action] @options[:action] || @scope[:action]
end 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 end
# Invokes Rack::Mount::Utils.normalize path and ensure that # Invokes Rack::Mount::Utils.normalize path and ensure that
@ -641,6 +651,10 @@ module ActionDispatch
block, options[:constraints] = options[:constraints], {} block, options[:constraints] = options[:constraints], {}
end end
if options[:constraints].is_a?(Hash)
(options[:defaults] ||= {}).reverse_merge!(defaults_from_constraints(options[:constraints]))
end
scope_options.each do |option| scope_options.each do |option|
if value = options.delete(option) if value = options.delete(option)
recover[option] = @scope[option] recover[option] = @scope[option]
@ -849,6 +863,11 @@ module ActionDispatch
def override_keys(child) #:nodoc: def override_keys(child) #:nodoc:
child.key?(:only) || child.key?(:except) ? [:only, :except] : [] child.key?(:only) || child.key?(:except) ? [:only, :except] : []
end 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 end
# Resource routing allows you to quickly declare all of the common routes # Resource routing allows you to quickly declare all of the common routes

View file

@ -47,7 +47,7 @@ class RoutingAssertionsTest < ActionController::TestCase
def test_assert_recognizes_with_extras def test_assert_recognizes_with_extras
assert_recognizes({ :controller => 'articles', :action => 'index', :page => '1' }, '/articles', { :page => '1' }) assert_recognizes({ :controller => 'articles', :action => 'index', :page => '1' }, '/articles', { :page => '1' })
end end
def test_assert_recognizes_with_method def test_assert_recognizes_with_method
assert_recognizes({ :controller => 'articles', :action => 'create' }, { :path => '/articles', :method => :post }) assert_recognizes({ :controller => 'articles', :action => 'create' }, { :path => '/articles', :method => :post })
assert_recognizes({ :controller => 'articles', :action => 'update', :id => '1' }, { :path => '/articles/1', :method => :put }) assert_recognizes({ :controller => 'articles', :action => 'update', :id => '1' }, { :path => '/articles/1', :method => :put })
@ -57,7 +57,7 @@ class RoutingAssertionsTest < ActionController::TestCase
assert_raise(ActionController::RoutingError) do assert_raise(ActionController::RoutingError) do
assert_recognizes({ :controller => 'secure_articles', :action => 'index' }, 'http://test.host/secure/articles') assert_recognizes({ :controller => 'secure_articles', :action => 'index' }, 'http://test.host/secure/articles')
end 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 end
def test_assert_recognizes_with_block_constraint def test_assert_recognizes_with_block_constraint
@ -90,7 +90,7 @@ class RoutingAssertionsTest < ActionController::TestCase
assert_raise(ActionController::RoutingError) do assert_raise(ActionController::RoutingError) do
assert_routing('http://test.host/secure/articles', { :controller => 'secure_articles', :action => 'index' }) assert_routing('http://test.host/secure/articles', { :controller => 'secure_articles', :action => 'index' })
end 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 end
def test_assert_routing_with_block_constraint def test_assert_routing_with_block_constraint

View file

@ -2606,3 +2606,45 @@ class TestNamedRouteUrlHelpers < ActionDispatch::IntegrationTest
assert_raises(ActionController::RoutingError) { product_path(nil) } assert_raises(ActionController::RoutingError) { product_path(nil) }
end end
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