aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--actionpack/lib/action_dispatch/routing/mapper.rb10
-rw-r--r--actionpack/test/dispatch/routing_test.rb43
2 files changed, 49 insertions, 4 deletions
diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb
index 388f695187..62fb7977cc 100644
--- a/actionpack/lib/action_dispatch/routing/mapper.rb
+++ b/actionpack/lib/action_dispatch/routing/mapper.rb
@@ -433,6 +433,8 @@ module ActionDispatch
end
module Resources
+ MERGE_FROM_SCOPE_OPTIONS = [:shallow, :constraints]
+
class Resource #:nodoc:
def self.default_actions
[:index, :create, :new, :show, :update, :destroy, :edit]
@@ -591,8 +593,6 @@ module ActionDispatch
def resource(*resources, &block)
options = resources.extract_options!
- options = (@scope[:options] || {}).merge(options)
- options[:shallow] = true if @scope[:shallow] && !options.has_key?(:shallow)
if apply_common_behavior_for(:resource, resources, options, &block)
return self
@@ -619,8 +619,6 @@ module ActionDispatch
def resources(*resources, &block)
options = resources.extract_options!
- options = (@scope[:options] || {}).merge(options)
- options[:shallow] = true if @scope[:shallow] && !options.has_key?(:shallow)
if apply_common_behavior_for(:resources, resources, options, &block)
return self
@@ -804,6 +802,10 @@ module ActionDispatch
return true
end
+ scope_options = @scope.slice(*MERGE_FROM_SCOPE_OPTIONS).delete_if{ |k,v| v.blank? }
+ options.reverse_merge!(scope_options) unless scope_options.empty?
+ options.reverse_merge!(@scope[:options]) unless @scope[:options].blank?
+
if resource_scope?
nested do
send(method, resources.pop, options, &block)
diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb
index 0548456b63..b5653a391a 100644
--- a/actionpack/test/dispatch/routing_test.rb
+++ b/actionpack/test/dispatch/routing_test.rb
@@ -334,6 +334,13 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
get '/tickets', :to => 'tickets#index', :as => :tickets
end
+ scope :constraints => { :id => /\d{4}/ } do
+ resources :movies do
+ resources :reviews
+ resource :trailer
+ end
+ end
+
match '/:locale/*file.:format', :to => 'files#show', :file => /path\/to\/existing\/file/
end
end
@@ -1558,6 +1565,42 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
end
+ def test_constraints_are_merged_from_scope
+ with_test_routes do
+ get '/movies/0001'
+ assert_equal 'movies#show', @response.body
+ assert_equal '/movies/0001', movie_path(:id => '0001')
+
+ get '/movies/00001'
+ assert_equal 'Not Found', @response.body
+ assert_raises(ActionController::RoutingError){ movie_path(:id => '00001') }
+
+ get '/movies/0001/reviews'
+ assert_equal 'reviews#index', @response.body
+ assert_equal '/movies/0001/reviews', movie_reviews_path(:movie_id => '0001')
+
+ get '/movies/00001/reviews'
+ assert_equal 'Not Found', @response.body
+ assert_raises(ActionController::RoutingError){ movie_reviews_path(:movie_id => '00001') }
+
+ get '/movies/0001/reviews/0001'
+ assert_equal 'reviews#show', @response.body
+ assert_equal '/movies/0001/reviews/0001', movie_review_path(:movie_id => '0001', :id => '0001')
+
+ get '/movies/00001/reviews/0001'
+ assert_equal 'Not Found', @response.body
+ assert_raises(ActionController::RoutingError){ movie_path(:movie_id => '00001', :id => '00001') }
+
+ get '/movies/0001/trailer'
+ assert_equal 'trailers#show', @response.body
+ assert_equal '/movies/0001/trailer', movie_trailer_path(:movie_id => '0001')
+
+ get '/movies/00001/trailer'
+ assert_equal 'Not Found', @response.body
+ assert_raises(ActionController::RoutingError){ movie_trailer_path(:movie_id => '00001') }
+ end
+ end
+
private
def with_test_routes
yield