aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib
diff options
context:
space:
mode:
authorYehuda Katz <wycats@Yehuda-Katz.local>2009-12-10 13:11:15 -0800
committerYehuda Katz <wycats@Yehuda-Katz.local>2009-12-10 13:11:15 -0800
commit8b9275340f6845f1fd3ad8fc43d66a95a73b0c2d (patch)
tree2acb83debd9772fb0719dbb9ce23c70c5dd953b5 /actionpack/lib
parent2ecfa817c95f98247d1bd7fb28b208d3f950b43f (diff)
parentec5434c3c2631bb47b568eede397c3bd596eeb88 (diff)
downloadrails-8b9275340f6845f1fd3ad8fc43d66a95a73b0c2d.tar.gz
rails-8b9275340f6845f1fd3ad8fc43d66a95a73b0c2d.tar.bz2
rails-8b9275340f6845f1fd3ad8fc43d66a95a73b0c2d.zip
Merge branch 'master' of github.com:rails/rails
Diffstat (limited to 'actionpack/lib')
-rw-r--r--actionpack/lib/action_controller/metal/render_options.rb101
-rw-r--r--actionpack/lib/action_dispatch/routing/mapper.rb599
-rw-r--r--actionpack/lib/action_dispatch/routing/route_set.rb9
3 files changed, 360 insertions, 349 deletions
diff --git a/actionpack/lib/action_controller/metal/render_options.rb b/actionpack/lib/action_controller/metal/render_options.rb
index 0d69ca10df..b6a7ca0eda 100644
--- a/actionpack/lib/action_controller/metal/render_options.rb
+++ b/actionpack/lib/action_controller/metal/render_options.rb
@@ -1,19 +1,24 @@
module ActionController
+
+ def self.add_renderer(key, &block)
+ RenderOptions.add(key, &block)
+ end
+
module RenderOptions
extend ActiveSupport::Concern
included do
extlib_inheritable_accessor :_renderers
- self._renderers = []
+ self._renderers = {}
end
module ClassMethods
def _write_render_options
- renderers = _renderers.map do |r|
+ renderers = _renderers.map do |name, value|
<<-RUBY_EVAL
- if options.key?(:#{r})
+ if options.key?(:#{name})
_process_options(options)
- return render_#{r}(options[:#{r}], options)
+ return _render_option_#{name}(options[:#{name}], options)
end
RUBY_EVAL
end
@@ -25,79 +30,63 @@ module ActionController
RUBY_EVAL
end
- def _add_render_option(name)
- _renderers << name
+ def use_renderers(*args)
+ args.each do |key|
+ _renderers[key] = RENDERERS[key]
+ end
_write_render_options
end
+ alias use_renderer use_renderers
end
def render_to_body(options)
_handle_render_options(options) || super
end
- end
-
- module RenderOption #:nodoc:
- def self.extended(base)
- base.extend ActiveSupport::Concern
- base.send :include, ::ActionController::RenderOptions
- def base.register_renderer(name)
- included { _add_render_option(name) }
- end
+ RENDERERS = {}
+ def self.add(key, &block)
+ define_method("_render_option_#{key}", &block)
+ RENDERERS[key] = block
+ All._write_render_options
end
- end
- module RenderOptions
- module Json
- extend RenderOption
- register_renderer :json
+ module All
+ extend ActiveSupport::Concern
+ include RenderOptions
- def render_json(json, options)
- json = ActiveSupport::JSON.encode(json) unless json.respond_to?(:to_str)
- json = "#{options[:callback]}(#{json})" unless options[:callback].blank?
- self.content_type ||= Mime::JSON
- self.response_body = json
+ INCLUDED = []
+ included do
+ self._renderers = RENDERERS
+ _write_render_options
+ INCLUDED << self
end
- end
-
- module Js
- extend RenderOption
- register_renderer :js
- def render_js(js, options)
- self.content_type ||= Mime::JS
- self.response_body = js.respond_to?(:to_js) ? js.to_js : js
+ def self._write_render_options
+ INCLUDED.each(&:_write_render_options)
end
end
- module Xml
- extend RenderOption
- register_renderer :xml
-
- def render_xml(xml, options)
- self.content_type ||= Mime::XML
- self.response_body = xml.respond_to?(:to_xml) ? xml.to_xml : xml
- end
+ add :json do |json, options|
+ json = ActiveSupport::JSON.encode(json) unless json.respond_to?(:to_str)
+ json = "#{options[:callback]}(#{json})" unless options[:callback].blank?
+ self.content_type ||= Mime::JSON
+ self.response_body = json
end
- module RJS
- extend RenderOption
- register_renderer :update
-
- def render_update(proc, options)
- generator = ActionView::Helpers::PrototypeHelper::JavaScriptGenerator.new(view_context, &proc)
- self.content_type = Mime::JS
- self.response_body = generator.to_s
- end
+ add :js do |js, options|
+ self.content_type ||= Mime::JS
+ self.response_body = js.respond_to?(:to_js) ? js.to_js : js
end
- module All
- extend ActiveSupport::Concern
+ add :xml do |xml, options|
+ self.content_type ||= Mime::XML
+ self.response_body = xml.respond_to?(:to_xml) ? xml.to_xml : xml
+ end
- include ActionController::RenderOptions::Json
- include ActionController::RenderOptions::Js
- include ActionController::RenderOptions::Xml
- include ActionController::RenderOptions::RJS
+ add :update do |proc, options|
+ generator = ActionView::Helpers::PrototypeHelper::JavaScriptGenerator.new(view_context, &proc)
+ self.content_type = Mime::JS
+ self.response_body = generator.to_s
end
end
end
diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb
index 400039353c..3b185c2576 100644
--- a/actionpack/lib/action_dispatch/routing/mapper.rb
+++ b/actionpack/lib/action_dispatch/routing/mapper.rb
@@ -1,221 +1,193 @@
module ActionDispatch
module Routing
class Mapper
- module Resources
- class Resource #:nodoc:
- attr_reader :plural, :singular
- attr_reader :path_prefix, :name_prefix
-
- def initialize(entities, options = {})
- entities = entities.to_s
-
- @plural = entities.pluralize
- @singular = entities.singularize
-
- @path_prefix = options[:path_prefix]
- @name_prefix = options[:name_prefix]
- end
-
- def name
- plural
- end
-
- def controller
- plural
+ class Constraints
+ def new(app, constraints = [])
+ if constraints.any?
+ super(app, constraints)
+ else
+ app
end
+ end
- def member_name
- if name_prefix
- "#{name_prefix}_#{singular}"
- else
- singular
- end
- end
+ def initialize(app, constraints = [])
+ @app, @constraints = app, constraints
+ end
- def collection_name
- if name_prefix
- "#{name_prefix}_#{plural}"
- else
- plural
- end
- end
+ def call(env)
+ req = Rack::Request.new(env)
- def new_name
- if name_prefix
- "new_#{name_prefix}_#{singular}"
- else
- "new_#{singular}"
+ @constraints.each { |constraint|
+ if constraint.respond_to?(:matches?) && !constraint.matches?(req)
+ return [417, {}, []]
+ elsif constraint.respond_to?(:call) && !constraint.call(req)
+ return [417, {}, []]
end
- end
+ }
- def edit_name
- if name_prefix
- "edit_#{name_prefix}_#{singular}"
- else
- "edit_#{singular}"
- end
- end
+ @app.call(env)
end
+ end
- class SingletonResource < Resource #:nodoc:
- def initialize(entity, options = {})
- super(entity)
- end
+ module Base
+ def initialize(set)
+ @set = set
+ end
- def name
- singular
- end
+ def root(options = {})
+ match '/', options.merge(:as => :root)
end
- def resource(*resources, &block)
- options = resources.extract_options!
+ def match(*args)
+ options = args.extract_options!
- if resources.length > 1
- raise ArgumentError if block_given?
- resources.each { |r| resource(r, options) }
- return self
- end
+ path = args.first
- name_prefix = @scope[:options][:name_prefix] if @scope[:options]
- resource = SingletonResource.new(resources.pop, :name_prefix => name_prefix)
+ conditions, defaults = {}, {}
- if @scope[:scope_level] == :resources
- parent_resource = @scope[:scope_level_options][:name]
- parent_named_prefix = @scope[:scope_level_options][:name_prefix]
- with_scope_level(:member) do
- scope(":#{parent_resource}_id", :name_prefix => parent_named_prefix) do
- resource(resource.name, options, &block)
- end
- end
- return self
- end
+ path = nil if path == ""
+ path = "#{@scope[:path]}#{path}" if @scope[:path]
+ path = Rack::Mount::Utils.normalize_path(path) if path
- controller(resource.controller) do
- namespace(resource.name) do
- with_scope_level(:resource, :name => resource.singular, :name_prefix => resource.member_name) do
- yield if block_given?
+ raise ArgumentError, "path is required" unless path
- get "", :to => :show, :as => resource.member_name
- post "", :to => :create
- put "", :to => :update
- delete "", :to => :destroy
- get "new", :to => :new, :as => resource.new_name
- get "edit", :to => :edit, :as => resource.edit_name
- end
- end
+ constraints = options[:constraints] || {}
+ unless constraints.is_a?(Hash)
+ block, constraints = constraints, {}
end
+ blocks = ((@scope[:blocks] || []) + [block]).compact
+ constraints = (@scope[:constraints] || {}).merge(constraints)
+ options.each { |k, v| constraints[k] = v if v.is_a?(Regexp) }
- self
- end
+ conditions[:path_info] = path
+ requirements = constraints.dup
- def resources(*resources, &block)
- options = resources.extract_options!
+ path_regexp = Rack::Mount::Strexp.compile(path, constraints, SEPARATORS)
+ segment_keys = Rack::Mount::RegexpWithNamedGroups.new(path_regexp).names
+ constraints.reject! { |k, v| segment_keys.include?(k.to_s) }
+ conditions.merge!(constraints)
- if resources.length > 1
- raise ArgumentError if block_given?
- resources.each { |r| resources(r, options) }
- return self
- end
-
- name_prefix = @scope[:options][:name_prefix] if @scope[:options]
- resource = Resource.new(resources.pop, :name_prefix => name_prefix)
+ requirements[:controller] ||= @set.controller_constraints
- if @scope[:scope_level] == :resources
- parent_resource = @scope[:scope_level_options][:name]
- parent_named_prefix = @scope[:scope_level_options][:name_prefix]
- with_scope_level(:member) do
- scope(":#{parent_resource}_id", :name_prefix => parent_named_prefix) do
- resources(resource.name, options, &block)
- end
- end
- return self
+ if via = options[:via]
+ via = Array(via).map { |m| m.to_s.upcase }
+ conditions[:request_method] = Regexp.union(*via)
end
- controller(resource.controller) do
- namespace(resource.name) do
- with_scope_level(:resources, :name => resource.singular, :name_prefix => resource.member_name) do
- yield if block_given?
+ defaults[:controller] ||= @scope[:controller].to_s if @scope[:controller]
- collection do
- get "", :to => :index, :as => resource.collection_name
- post "", :to => :create
- get "new", :to => :new, :as => resource.new_name
- end
+ app = initialize_app_endpoint(options, defaults)
+ validate_defaults!(app, defaults, segment_keys)
+ app = Constraints.new(app, blocks)
- member do
- get "", :to => :show, :as => resource.member_name
- put "", :to => :update
- delete "", :to => :destroy
- get "edit", :to => :edit, :as => resource.edit_name
- end
- end
- end
- end
+ @set.add_route(app, conditions, requirements, defaults, options[:as])
self
end
- def collection
- unless @scope[:scope_level] == :resources
- raise ArgumentError, "can't use collection outside resources scope"
- end
+ private
+ def initialize_app_endpoint(options, defaults)
+ app = nil
+
+ if options[:to].respond_to?(:call)
+ app = options[:to]
+ defaults.delete(:controller)
+ defaults.delete(:action)
+ elsif options[:to].is_a?(String)
+ defaults[:controller], defaults[:action] = options[:to].split('#')
+ elsif options[:to].is_a?(Symbol)
+ defaults[:action] = options[:to].to_s
+ end
- with_scope_level(:collection) do
- yield
+ app || Routing::RouteSet::Dispatcher.new(:defaults => defaults)
end
- end
- def member
- unless @scope[:scope_level] == :resources
- raise ArgumentError, "can't use member outside resources scope"
- end
+ def validate_defaults!(app, defaults, segment_keys)
+ return unless app.is_a?(Routing::RouteSet::Dispatcher)
- with_scope_level(:member) do
- scope(":id") do
- yield
+ unless defaults.include?(:controller) || segment_keys.include?("controller")
+ raise ArgumentError, "missing :controller"
+ end
+
+ unless defaults.include?(:action) || segment_keys.include?("action")
+ raise ArgumentError, "missing :action"
end
end
+ end
+
+ module HttpHelpers
+ def get(*args, &block)
+ map_method(:get, *args, &block)
end
- def match(*args)
- options = args.extract_options!
- args.push(options)
+ def post(*args, &block)
+ map_method(:post, *args, &block)
+ end
- case options.delete(:on)
- when :collection
- return collection { match(*args) }
- when :member
- return member { match(*args) }
- end
+ def put(*args, &block)
+ map_method(:put, *args, &block)
+ end
- if @scope[:scope_level] == :resources
- raise ArgumentError, "can't define route directly in resources scope"
- end
+ def delete(*args, &block)
+ map_method(:delete, *args, &block)
+ end
- super
+ def redirect(path, options = {})
+ status = options[:status] || 301
+ lambda { |env|
+ req = Rack::Request.new(env)
+ url = req.scheme + '://' + req.host + path
+ [status, {'Location' => url, 'Content-Type' => 'text/html'}, ['Moved Permanently']]
+ }
end
private
- def with_scope_level(kind, options = {})
- old, @scope[:scope_level] = @scope[:scope_level], kind
- old_options, @scope[:scope_level_options] = @scope[:scope_level_options], options
- yield
- ensure
- @scope[:scope_level] = old
- @scope[:scope_level_options] = old_options
+ def map_method(method, *args, &block)
+ options = args.extract_options!
+ options[:via] = method
+ args.push(options)
+ match(*args, &block)
+ self
end
end
module Scoping
- def self.extended(object)
- object.instance_eval do
- @scope = {}
- end
+ def initialize(*args)
+ @scope = {}
+ super
end
def scope(*args)
options = args.extract_options!
+ case args.first
+ when String
+ options[:path] = args.first
+ when Symbol
+ options[:controller] = args.first
+ end
+
+ if path = options.delete(:path)
+ path_set = true
+ path, @scope[:path] = @scope[:path], Rack::Mount::Utils.normalize_path(@scope[:path].to_s + path.to_s)
+ else
+ path_set = false
+ end
+
+ if name_prefix = options.delete(:name_prefix)
+ name_prefix_set = true
+ name_prefix, @scope[:name_prefix] = @scope[:name_prefix], (@scope[:name_prefix] ? "#{@scope[:name_prefix]}_#{name_prefix}" : name_prefix)
+ else
+ name_prefix_set = false
+ end
+
+ if controller = options.delete(:controller)
+ controller_set = true
+ controller, @scope[:controller] = @scope[:controller], controller
+ else
+ controller_set = false
+ end
+
constraints = options.delete(:constraints) || {}
unless constraints.is_a?(Hash)
block, constraints = constraints, {}
@@ -225,24 +197,12 @@ module ActionDispatch
options, @scope[:options] = @scope[:options], (@scope[:options] || {}).merge(options)
- path_set = controller_set = false
-
- case args.first
- when String
- path_set = true
- path = args.first
- path, @scope[:path] = @scope[:path], "#{@scope[:path]}#{Rack::Mount::Utils.normalize_path(path)}"
- when Symbol
- controller_set = true
- controller = args.first
- controller, @scope[:controller] = @scope[:controller], controller
- end
-
yield
self
ensure
@scope[:path] = path if path_set
+ @scope[:name_prefix] = name_prefix if name_prefix_set
@scope[:controller] = controller if controller_set
@scope[:options] = options
@scope[:blocks] = blocks
@@ -254,7 +214,7 @@ module ActionDispatch
end
def namespace(path)
- scope(path.to_s) { yield }
+ scope("/#{path}") { yield }
end
def constraints(constraints = {})
@@ -263,172 +223,227 @@ module ActionDispatch
def match(*args)
options = args.extract_options!
+
options = (@scope[:options] || {}).merge(options)
+
+ if @scope[:name_prefix] && !options[:as].blank?
+ options[:as] = "#{@scope[:name_prefix]}_#{options[:as]}"
+ elsif @scope[:name_prefix] && options[:as] == ""
+ options[:as] = @scope[:name_prefix].to_s
+ end
+
args.push(options)
super(*args)
end
end
- module HttpHelpers
- def get(*args, &block)
- map_method(:get, *args, &block)
- end
+ module Resources
+ class Resource #:nodoc:
+ attr_reader :plural, :singular
- def post(*args, &block)
- map_method(:post, *args, &block)
- end
+ def initialize(entities, options = {})
+ entities = entities.to_s
- def put(*args, &block)
- map_method(:put, *args, &block)
- end
+ @plural = entities.pluralize
+ @singular = entities.singularize
+ end
- def delete(*args, &block)
- map_method(:delete, *args, &block)
- end
+ def name
+ plural
+ end
- def redirect(path, options = {})
- status = options[:status] || 301
- lambda { |env|
- req = Rack::Request.new(env)
- url = req.scheme + '://' + req.host + path
- [status, {'Location' => url, 'Content-Type' => 'text/html'}, ['Moved Permanently']]
- }
- end
+ def controller
+ plural
+ end
- private
- def map_method(method, *args, &block)
- options = args.extract_options!
- options[:via] = method
- args.push(options)
- match(*args, &block)
- self
+ def member_name
+ singular
end
- end
- class Constraints
- def new(app, constraints = [])
- if constraints.any?
- super(app, constraints)
- else
- app
+ def collection_name
+ plural
+ end
+
+ def id_segment
+ ":#{singular}_id"
end
end
- def initialize(app, constraints = [])
- @app, @constraints = app, constraints
+ class SingletonResource < Resource #:nodoc:
+ def initialize(entity, options = {})
+ super
+ end
+
+ def name
+ singular
+ end
end
- def call(env)
- req = Rack::Request.new(env)
+ def resource(*resources, &block)
+ options = resources.extract_options!
- @constraints.each { |constraint|
- if constraint.respond_to?(:matches?) && !constraint.matches?(req)
- return [417, {}, []]
- elsif constraint.respond_to?(:call) && !constraint.call(req)
- return [417, {}, []]
+ if resources.length > 1
+ raise ArgumentError if block_given?
+ resources.each { |r| resource(r, options) }
+ return self
+ end
+
+ resource = SingletonResource.new(resources.pop)
+
+ if @scope[:scope_level] == :resources
+ nested do
+ resource(resource.name, options, &block)
end
- }
+ return self
+ end
- @app.call(env)
- end
- end
+ scope(:path => "/#{resource.name}", :controller => resource.controller) do
+ with_scope_level(:resource, resource) do
+ yield if block_given?
- def initialize(set)
- @set = set
+ get "(.:format)", :to => :show, :as => resource.member_name
+ post "(.:format)", :to => :create
+ put "(.:format)", :to => :update
+ delete "(.:format)", :to => :destroy
+ get "/new(.:format)", :to => :new, :as => "new_#{resource.singular}"
+ get "/edit(.:format)", :to => :edit, :as => "edit_#{resource.singular}"
+ end
+ end
- extend HttpHelpers
- extend Scoping
- extend Resources
- end
+ self
+ end
- def root(options = {})
- match '/', options.merge(:as => :root)
- end
+ def resources(*resources, &block)
+ options = resources.extract_options!
- def match(*args)
- options = args.extract_options!
+ if resources.length > 1
+ raise ArgumentError if block_given?
+ resources.each { |r| resources(r, options) }
+ return self
+ end
- if args.length > 1
- args.each { |path| match(path, options) }
- return self
- end
+ resource = Resource.new(resources.pop)
- if args.first.is_a?(Symbol)
- return match(args.first.to_s, options.merge(:to => args.first.to_sym))
- end
+ if @scope[:scope_level] == :resources
+ nested do
+ resources(resource.name, options, &block)
+ end
+ return self
+ end
- path = args.first
+ scope(:path => "/#{resource.name}", :controller => resource.controller) do
+ with_scope_level(:resources, resource) do
+ yield if block_given?
- conditions, defaults = {}, {}
+ with_scope_level(:collection) do
+ get "(.:format)", :to => :index, :as => resource.collection_name
+ post "(.:format)", :to => :create
+ get "/new(.:format)", :to => :new, :as => "new_#{resource.singular}"
+ end
- path = nil if path == ""
- path = Rack::Mount::Utils.normalize_path(path) if path
- path = "#{@scope[:path]}#{path}" if @scope[:path]
+ with_scope_level(:member) do
+ scope("/:id") do
+ get "(.:format)", :to => :show, :as => resource.member_name
+ put "(.:format)", :to => :update
+ delete "(.:format)", :to => :destroy
+ get "/edit(.:format)", :to => :edit, :as => "edit_#{resource.singular}"
+ end
+ end
+ end
+ end
+
+ self
+ end
- raise ArgumentError, "path is required" unless path
+ def collection
+ unless @scope[:scope_level] == :resources
+ raise ArgumentError, "can't use collection outside resources scope"
+ end
- constraints = options[:constraints] || {}
- unless constraints.is_a?(Hash)
- block, constraints = constraints, {}
+ with_scope_level(:collection) do
+ scope(:name_prefix => parent_resource.collection_name, :as => "") do
+ yield
+ end
+ end
end
- blocks = ((@scope[:blocks] || []) + [block]).compact
- constraints = (@scope[:constraints] || {}).merge(constraints)
- options.each { |k, v| constraints[k] = v if v.is_a?(Regexp) }
- conditions[:path_info] = path
- requirements = constraints.dup
+ def member
+ unless @scope[:scope_level] == :resources
+ raise ArgumentError, "can't use member outside resources scope"
+ end
- path_regexp = Rack::Mount::Strexp.compile(path, constraints, SEPARATORS)
- segment_keys = Rack::Mount::RegexpWithNamedGroups.new(path_regexp).names
- constraints.reject! { |k, v| segment_keys.include?(k.to_s) }
- conditions.merge!(constraints)
+ with_scope_level(:member) do
+ scope("/:id", :name_prefix => parent_resource.member_name, :as => "") do
+ yield
+ end
+ end
+ end
- requirements[:controller] ||= @set.controller_constraints
+ def nested
+ unless @scope[:scope_level] == :resources
+ raise ArgumentError, "can't use nested outside resources scope"
+ end
- if via = options[:via]
- via = Array(via).map { |m| m.to_s.upcase }
- conditions[:request_method] = Regexp.union(*via)
+ with_scope_level(:nested) do
+ scope("/#{parent_resource.id_segment}", :name_prefix => parent_resource.member_name) do
+ yield
+ end
+ end
end
- defaults[:controller] ||= @scope[:controller].to_s if @scope[:controller]
+ def match(*args)
+ options = args.extract_options!
- app = initialize_app_endpoint(options, defaults)
- validate_defaults!(app, defaults, segment_keys)
- app = Constraints.new(app, blocks)
+ if args.length > 1
+ args.each { |path| match(path, options) }
+ return self
+ end
- @set.add_route(app, conditions, requirements, defaults, options[:as])
+ if args.first.is_a?(Symbol)
+ begin
+ old_name_prefix, @scope[:name_prefix] = @scope[:name_prefix], "#{args.first}_#{@scope[:name_prefix]}"
+ return match("/#{args.first}(.:format)", options.merge(:to => args.first.to_sym))
+ ensure
+ @scope[:name_prefix] = old_name_prefix
+ end
+ end
- self
- end
+ args.push(options)
- private
- def initialize_app_endpoint(options, defaults)
- app = nil
+ case options.delete(:on)
+ when :collection
+ return collection { match(*args) }
+ when :member
+ return member { match(*args) }
+ end
- if options[:to].respond_to?(:call)
- app = options[:to]
- defaults.delete(:controller)
- defaults.delete(:action)
- elsif options[:to].is_a?(String)
- defaults[:controller], defaults[:action] = options[:to].split('#')
- elsif options[:to].is_a?(Symbol)
- defaults[:action] = options[:to].to_s
+ if @scope[:scope_level] == :resources
+ raise ArgumentError, "can't define route directly in resources scope"
end
- app || Routing::RouteSet::Dispatcher.new(:defaults => defaults)
+ super
end
- def validate_defaults!(app, defaults, segment_keys)
- return unless app.is_a?(Routing::RouteSet::Dispatcher)
-
- unless defaults.include?(:controller) || segment_keys.include?("controller")
- raise ArgumentError, "missing :controller"
+ protected
+ def parent_resource
+ @scope[:scope_level_resource]
end
- unless defaults.include?(:action) || segment_keys.include?("action")
- raise ArgumentError, "missing :action"
+ private
+ def with_scope_level(kind, resource = parent_resource)
+ old, @scope[:scope_level] = @scope[:scope_level], kind
+ old_resource, @scope[:scope_level_resource] = @scope[:scope_level_resource], resource
+ yield
+ ensure
+ @scope[:scope_level] = old
+ @scope[:scope_level_resource] = old_resource
end
- end
+ end
+
+ include Base
+ include HttpHelpers
+ include Scoping
+ include Resources
end
end
end
diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb
index a8073c2105..0e83ea3b7e 100644
--- a/actionpack/lib/action_dispatch/routing/route_set.rb
+++ b/actionpack/lib/action_dispatch/routing/route_set.rb
@@ -216,7 +216,14 @@ module ActionDispatch
def draw(&block)
clear!
- Mapper.new(self).instance_exec(DeprecatedMapper.new(self), &block)
+
+ mapper = Mapper.new(self)
+ if block.arity == 1
+ mapper.instance_exec(DeprecatedMapper.new(self), &block)
+ else
+ mapper.instance_exec(&block)
+ end
+
@set.add_route(NotFound)
install_helpers
@set.freeze