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

Merge branch 'master' of github.com:rails/rails

This commit is contained in:
Yehuda Katz 2009-12-10 13:11:15 -08:00
commit 8b9275340f
30 changed files with 576 additions and 557 deletions

View file

@ -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
end
end
module RenderOptions
module Json
extend RenderOption
register_renderer :json
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
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
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
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
RENDERERS = {}
def self.add(key, &block)
define_method("_render_option_#{key}", &block)
RENDERERS[key] = block
All._write_render_options
end
module All
extend ActiveSupport::Concern
include RenderOptions
include ActionController::RenderOptions::Json
include ActionController::RenderOptions::Js
include ActionController::RenderOptions::Xml
include ActionController::RenderOptions::RJS
INCLUDED = []
included do
self._renderers = RENDERERS
_write_render_options
INCLUDED << self
end
def self._write_render_options
INCLUDED.each(&:_write_render_options)
end
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
add :js do |js, options|
self.content_type ||= Mime::JS
self.response_body = js.respond_to?(:to_js) ? js.to_js : js
end
add :xml do |xml, options|
self.content_type ||= Mime::XML
self.response_body = xml.respond_to?(:to_xml) ? xml.to_xml : xml
end
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

View file

@ -1,272 +1,118 @@
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
end
def member_name
if name_prefix
"#{name_prefix}_#{singular}"
else
singular
end
end
def collection_name
if name_prefix
"#{name_prefix}_#{plural}"
else
plural
end
end
def new_name
if name_prefix
"new_#{name_prefix}_#{singular}"
else
"new_#{singular}"
end
end
def edit_name
if name_prefix
"edit_#{name_prefix}_#{singular}"
else
"edit_#{singular}"
end
class Constraints
def new(app, constraints = [])
if constraints.any?
super(app, constraints)
else
app
end
end
class SingletonResource < Resource #:nodoc:
def initialize(entity, options = {})
super(entity)
end
def name
singular
end
def initialize(app, constraints = [])
@app, @constraints = app, constraints
end
def resource(*resources, &block)
options = resources.extract_options!
def call(env)
req = Rack::Request.new(env)
if resources.length > 1
raise ArgumentError if block_given?
resources.each { |r| resource(r, options) }
return self
end
name_prefix = @scope[:options][:name_prefix] if @scope[:options]
resource = SingletonResource.new(resources.pop, :name_prefix => name_prefix)
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
@constraints.each { |constraint|
if constraint.respond_to?(:matches?) && !constraint.matches?(req)
return [417, {}, []]
elsif constraint.respond_to?(:call) && !constraint.call(req)
return [417, {}, []]
end
return self
end
}
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?
@app.call(env)
end
end
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
end
self
module Base
def initialize(set)
@set = set
end
def resources(*resources, &block)
options = resources.extract_options!
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)
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
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?
collection do
get "", :to => :index, :as => resource.collection_name
post "", :to => :create
get "new", :to => :new, :as => resource.new_name
end
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
self
end
def collection
unless @scope[:scope_level] == :resources
raise ArgumentError, "can't use collection outside resources scope"
end
with_scope_level(:collection) do
yield
end
end
def member
unless @scope[:scope_level] == :resources
raise ArgumentError, "can't use member outside resources scope"
end
with_scope_level(:member) do
scope(":id") do
yield
end
end
def root(options = {})
match '/', options.merge(:as => :root)
end
def match(*args)
options = args.extract_options!
args.push(options)
case options.delete(:on)
when :collection
return collection { match(*args) }
when :member
return member { match(*args) }
end
path = args.first
if @scope[:scope_level] == :resources
raise ArgumentError, "can't define route directly in resources scope"
end
conditions, defaults = {}, {}
super
end
path = nil if path == ""
path = "#{@scope[:path]}#{path}" if @scope[:path]
path = Rack::Mount::Utils.normalize_path(path) if path
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
end
end
raise ArgumentError, "path is required" unless path
module Scoping
def self.extended(object)
object.instance_eval do
@scope = {}
end
end
def scope(*args)
options = args.extract_options!
constraints = options.delete(:constraints) || {}
constraints = options[:constraints] || {}
unless constraints.is_a?(Hash)
block, constraints = constraints, {}
end
constraints, @scope[:constraints] = @scope[:constraints], (@scope[:constraints] || {}).merge(constraints)
blocks, @scope[:blocks] = @scope[:blocks], (@scope[:blocks] || []) + [block]
blocks = ((@scope[:blocks] || []) + [block]).compact
constraints = (@scope[:constraints] || {}).merge(constraints)
options.each { |k, v| constraints[k] = v if v.is_a?(Regexp) }
options, @scope[:options] = @scope[:options], (@scope[:options] || {}).merge(options)
conditions[:path_info] = path
requirements = constraints.dup
path_set = controller_set = false
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)
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
requirements[:controller] ||= @set.controller_constraints
if via = options[:via]
via = Array(via).map { |m| m.to_s.upcase }
conditions[:request_method] = Regexp.union(*via)
end
yield
defaults[:controller] ||= @scope[:controller].to_s if @scope[:controller]
app = initialize_app_endpoint(options, defaults)
validate_defaults!(app, defaults, segment_keys)
app = Constraints.new(app, blocks)
@set.add_route(app, conditions, requirements, defaults, options[:as])
self
ensure
@scope[:path] = path if path_set
@scope[:controller] = controller if controller_set
@scope[:options] = options
@scope[:blocks] = blocks
@scope[:constraints] = constraints
end
def controller(controller)
scope(controller.to_sym) { yield }
end
private
def initialize_app_endpoint(options, defaults)
app = nil
def namespace(path)
scope(path.to_s) { yield }
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
end
def constraints(constraints = {})
scope(:constraints => constraints) { yield }
end
app || Routing::RouteSet::Dispatcher.new(:defaults => defaults)
end
def match(*args)
options = args.extract_options!
options = (@scope[:options] || {}).merge(options)
args.push(options)
super(*args)
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"
end
unless defaults.include?(:action) || segment_keys.include?("action")
raise ArgumentError, "missing :action"
end
end
end
module HttpHelpers
@ -305,130 +151,299 @@ module ActionDispatch
end
end
class Constraints
def new(app, constraints = [])
if constraints.any?
super(app, constraints)
module Scoping
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
app
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, {}
end
constraints, @scope[:constraints] = @scope[:constraints], (@scope[:constraints] || {}).merge(constraints)
blocks, @scope[:blocks] = @scope[:blocks], (@scope[:blocks] || []) + [block]
options, @scope[:options] = @scope[:options], (@scope[:options] || {}).merge(options)
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
@scope[:constraints] = constraints
end
def controller(controller)
scope(controller.to_sym) { yield }
end
def namespace(path)
scope("/#{path}") { yield }
end
def constraints(constraints = {})
scope(:constraints => constraints) { yield }
end
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 Resources
class Resource #:nodoc:
attr_reader :plural, :singular
def initialize(entities, options = {})
entities = entities.to_s
@plural = entities.pluralize
@singular = entities.singularize
end
def name
plural
end
def controller
plural
end
def member_name
singular
end
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
}
@app.call(env)
end
end
def initialize(set)
@set = set
extend HttpHelpers
extend Scoping
extend Resources
end
def root(options = {})
match '/', options.merge(:as => :root)
end
def match(*args)
options = args.extract_options!
if args.length > 1
args.each { |path| match(path, options) }
return self
end
if args.first.is_a?(Symbol)
return match(args.first.to_s, options.merge(:to => args.first.to_sym))
end
path = args.first
conditions, defaults = {}, {}
path = nil if path == ""
path = Rack::Mount::Utils.normalize_path(path) if path
path = "#{@scope[:path]}#{path}" if @scope[:path]
raise ArgumentError, "path is required" unless path
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) }
conditions[:path_info] = path
requirements = constraints.dup
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)
requirements[:controller] ||= @set.controller_constraints
if via = options[:via]
via = Array(via).map { |m| m.to_s.upcase }
conditions[:request_method] = Regexp.union(*via)
end
defaults[:controller] ||= @scope[:controller].to_s if @scope[:controller]
app = initialize_app_endpoint(options, defaults)
validate_defaults!(app, defaults, segment_keys)
app = Constraints.new(app, blocks)
@set.add_route(app, conditions, requirements, defaults, options[:as])
self
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
return self
end
app || Routing::RouteSet::Dispatcher.new(:defaults => defaults)
end
scope(:path => "/#{resource.name}", :controller => resource.controller) do
with_scope_level(:resource, resource) do
yield if block_given?
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"
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
unless defaults.include?(:action) || segment_keys.include?("action")
raise ArgumentError, "missing :action"
self
end
def resources(*resources, &block)
options = resources.extract_options!
if resources.length > 1
raise ArgumentError if block_given?
resources.each { |r| resources(r, options) }
return self
end
resource = Resource.new(resources.pop)
if @scope[:scope_level] == :resources
nested do
resources(resource.name, options, &block)
end
return self
end
scope(:path => "/#{resource.name}", :controller => resource.controller) do
with_scope_level(:resources, resource) do
yield if block_given?
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
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
def collection
unless @scope[:scope_level] == :resources
raise ArgumentError, "can't use collection outside resources scope"
end
with_scope_level(:collection) do
scope(:name_prefix => parent_resource.collection_name, :as => "") do
yield
end
end
end
def member
unless @scope[:scope_level] == :resources
raise ArgumentError, "can't use member outside resources scope"
end
with_scope_level(:member) do
scope("/:id", :name_prefix => parent_resource.member_name, :as => "") do
yield
end
end
end
def nested
unless @scope[:scope_level] == :resources
raise ArgumentError, "can't use nested outside resources scope"
end
with_scope_level(:nested) do
scope("/#{parent_resource.id_segment}", :name_prefix => parent_resource.member_name) do
yield
end
end
end
def match(*args)
options = args.extract_options!
if args.length > 1
args.each { |path| match(path, options) }
return self
end
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
args.push(options)
case options.delete(:on)
when :collection
return collection { match(*args) }
when :member
return member { match(*args) }
end
if @scope[:scope_level] == :resources
raise ArgumentError, "can't define route directly in resources scope"
end
super
end
protected
def parent_resource
@scope[:scope_level_resource]
end
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
include Base
include HttpHelpers
include Scoping
include Resources
end
end
end

View file

@ -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

View file

@ -83,7 +83,7 @@ class ActiveSupport::TestCase
# have been loaded.
setup_once do
ActionController::Routing::Routes.draw do |map|
map.connect ':controller/:action/:id'
match ':controller(/:action(/:id))'
end
end
end

View file

@ -155,7 +155,7 @@ class ActiveRecordStoreTest < ActionController::IntegrationTest
def with_test_route_set(options = {})
with_routing do |set|
set.draw do |map|
map.connect "/:action", :controller => "active_record_store_test/test"
match ':action', :to => 'active_record_store_test/test'
end
@app = ActiveRecord::SessionStore.new(set, options.reverse_merge(:key => '_session_id'))
yield

View file

@ -221,8 +221,8 @@ class ActionPackAssertionsControllerTest < ActionController::TestCase
def test_assert_redirect_to_named_route
with_routing do |set|
set.draw do |map|
map.route_one 'route_one', :controller => 'action_pack_assertions', :action => 'nothing'
map.connect ':controller/:action/:id'
match 'route_one', :to => 'action_pack_assertions#nothing', :as => :route_one
match ':controller/:action'
end
set.install_helpers
@ -235,9 +235,9 @@ class ActionPackAssertionsControllerTest < ActionController::TestCase
def test_assert_redirect_to_named_route_failure
with_routing do |set|
set.draw do |map|
map.route_one 'route_one', :controller => 'action_pack_assertions', :action => 'nothing', :id => 'one'
map.route_two 'route_two', :controller => 'action_pack_assertions', :action => 'nothing', :id => 'two'
map.connect ':controller/:action/:id'
match 'route_one', :to => 'action_pack_assertions#nothing', :as => :route_one
match 'route_two', :to => 'action_pack_assertions#nothing', :id => 'two', :as => :route_two
match ':controller/:action'
end
process :redirect_to_named_route
assert_raise(ActiveSupport::TestCase::Assertion) do
@ -255,8 +255,8 @@ class ActionPackAssertionsControllerTest < ActionController::TestCase
def test_assert_redirect_to_nested_named_route
with_routing do |set|
set.draw do |map|
map.admin_inner_module 'admin/inner_module', :controller => 'admin/inner_module', :action => 'index'
map.connect ':controller/:action/:id'
match 'admin/inner_module', :to => 'admin/inner_module#index', :as => :admin_inner_module
match ':controller/:action'
end
@controller = Admin::InnerModuleController.new
process :redirect_to_index
@ -268,8 +268,8 @@ class ActionPackAssertionsControllerTest < ActionController::TestCase
def test_assert_redirected_to_top_level_named_route_from_nested_controller
with_routing do |set|
set.draw do |map|
map.top_level '/action_pack_assertions/:id', :controller => 'action_pack_assertions', :action => 'index'
map.connect ':controller/:action/:id'
match '/action_pack_assertions/:id', :to => 'action_pack_assertions#index', :as => :top_level
match ':controller/:action'
end
@controller = Admin::InnerModuleController.new
process :redirect_to_top_level_named_route
@ -282,8 +282,8 @@ class ActionPackAssertionsControllerTest < ActionController::TestCase
with_routing do |set|
set.draw do |map|
# this controller exists in the admin namespace as well which is the only difference from previous test
map.top_level '/user/:id', :controller => 'user', :action => 'index'
map.connect ':controller/:action/:id'
match '/user/:id', :to => 'user#index', :as => :top_level
match ':controller/:action'
end
@controller = Admin::InnerModuleController.new
process :redirect_to_top_level_named_route

View file

@ -179,8 +179,8 @@ class DefaultUrlOptionsTest < ActionController::TestCase
def test_default_url_options_are_used_if_set
with_routing do |set|
set.draw do |map|
map.default_url_options 'default_url_options', :controller => 'default_url_options'
map.connect ':controller/:action/:id'
match 'default_url_options', :to => 'default_url_options#default_url_options_action', :as => :default_url_options
match ':controller/:action'
end
get :default_url_options_action # Make a dummy request so that the controller is initialized properly.
@ -210,7 +210,7 @@ class EnsureNamedRoutesWorksTicket22BugTest < ActionController::TestCase
def test_named_routes_still_work
with_routing do |set|
set.draw do |map|
map.resources :things
resources :things
end
EmptyController.send :include, ActionController::UrlWriter

View file

@ -70,8 +70,8 @@ class PageCachingTest < ActionController::TestCase
def test_page_caching_resources_saves_to_correct_path_with_extension_even_if_default_route
with_routing do |set|
set.draw do |map|
map.main '', :controller => 'posts', :format => nil
map.formatted_posts 'posts.:format', :controller => 'posts'
match 'posts.:format', :to => 'posts#index', :as => :formatted_posts
match '/', :to => 'posts#index', :as => :main
end
@params[:format] = 'rss'
assert_equal '/posts.rss', @rewriter.rewrite(@params)
@ -422,8 +422,7 @@ class ActionCacheTest < ActionController::TestCase
def test_xml_version_of_resource_is_treated_as_different_cache
with_routing do |set|
set.draw do |map|
map.connect ':controller/:action.:format'
map.connect ':controller/:action'
match ':controller(/:action(.:format))'
end
get :index, :format => 'xml'

View file

@ -853,9 +853,11 @@ class RespondWithControllerTest < ActionController::TestCase
def with_test_route_set
with_routing do |set|
set.draw do |map|
map.resources :customers
map.resources :quiz_stores, :has_many => :customers
map.connect ":controller/:action/:id"
resources :customers
resources :quiz_stores do
resources :customers
end
match ":controller/:action"
end
yield
end

View file

@ -233,8 +233,8 @@ class RedirectTest < ActionController::TestCase
def test_redirect_to_record
with_routing do |set|
set.draw do |map|
map.resources :workshops
map.connect ':controller/:action/:id'
resources :workshops
match ':controller/:action'
end
get :redirect_to_existing_record

View file

@ -2,6 +2,11 @@ require 'abstract_unit'
require 'controller/fake_models'
require 'pathname'
ActionController.add_renderer :simon do |says, options|
self.content_type = Mime::TEXT
self.response_body = "Simon says: #{says}"
end
class RenderOtherTest < ActionController::TestCase
class TestController < ActionController::Base
protect_from_forgery
@ -109,6 +114,10 @@ class RenderOtherTest < ActionController::TestCase
end
end
def render_simon_says
render :simon => "foo"
end
private
def default_render
if @alternate_default_render
@ -240,4 +249,9 @@ class RenderOtherTest < ActionController::TestCase
xhr :get, :render_alternate_default
assert_equal %(Element.replace("foo", "partial html");), @response.body
end
def test_using_custom_render_option
get :render_simon_says
assert_equal "Simon says: foo", @response.body
end
end

View file

@ -39,35 +39,35 @@ class TestController < ActionController::Base
render :action => 'hello_world'
end
end
def conditional_hello_with_public_header
if stale?(:last_modified => Time.now.utc.beginning_of_day, :etag => [:foo, 123], :public => true)
render :action => 'hello_world'
end
end
def conditional_hello_with_public_header_and_expires_at
expires_in 1.minute
if stale?(:last_modified => Time.now.utc.beginning_of_day, :etag => [:foo, 123], :public => true)
render :action => 'hello_world'
end
end
def conditional_hello_with_expires_in
expires_in 60.1.seconds
render :action => 'hello_world'
end
def conditional_hello_with_expires_in_with_public
expires_in 1.minute, :public => true
render :action => 'hello_world'
end
def conditional_hello_with_expires_in_with_public_with_more_keys
expires_in 1.minute, :public => true, 'max-stale' => 5.hours
render :action => 'hello_world'
end
def conditional_hello_with_expires_in_with_public_with_more_keys_old_syntax
expires_in 1.minute, :public => true, :private => nil, 'max-stale' => 5.hours
render :action => 'hello_world'
@ -272,7 +272,7 @@ class TestController < ActionController::Base
def builder_layout_test
render :action => "hello", :layout => "layouts/builder"
end
# :move: test this in ActionView
def builder_partial_test
render :action => "hello_world_container"
@ -1093,8 +1093,8 @@ class RenderTest < ActionController::TestCase
def test_head_with_location_object
with_routing do |set|
set.draw do |map|
map.resources :customers
map.connect ':controller/:action/:id'
resources :customers
match ':controller/:action'
end
get :head_with_location_object
@ -1306,22 +1306,22 @@ class ExpiresInRenderTest < ActionController::TestCase
def setup
@request.host = "www.nextangle.com"
end
def test_expires_in_header
get :conditional_hello_with_expires_in
assert_equal "max-age=60, private", @response.headers["Cache-Control"]
end
def test_expires_in_header_with_public
get :conditional_hello_with_expires_in_with_public
assert_equal "max-age=60, public", @response.headers["Cache-Control"]
end
def test_expires_in_header_with_additional_headers
get :conditional_hello_with_expires_in_with_public_with_more_keys
assert_equal "max-age=60, public, max-stale=18000", @response.headers["Cache-Control"]
end
def test_expires_in_old_syntax
get :conditional_hello_with_expires_in_with_public_with_more_keys_old_syntax
assert_equal "max-age=60, public, max-stale=18000", @response.headers["Cache-Control"]
@ -1425,12 +1425,12 @@ class EtagRenderTest < ActionController::TestCase
get :conditional_hello_with_bangs
assert_response :not_modified
end
def test_etag_with_public_true_should_set_header
get :conditional_hello_with_public_header
assert_equal "public", @response.headers['Cache-Control']
end
def test_etag_with_public_true_should_set_header_and_retain_other_headers
get :conditional_hello_with_public_header_and_expires_at
assert_equal "max-age=60, public", @response.headers['Cache-Control']

View file

@ -61,8 +61,8 @@ class RenderXmlTest < ActionController::TestCase
def test_rendering_with_object_location_should_set_header_with_url_for
with_routing do |set|
set.draw do |map|
map.resources :customers
map.connect ':controller/:action/:id'
resources :customers
match ':controller/:action'
end
get :render_with_object_location

View file

@ -456,8 +456,8 @@ XML
def test_array_path_parameter_handled_properly
with_routing do |set|
set.draw do |map|
map.connect 'file/*path', :controller => 'test_test/test', :action => 'test_params'
map.connect ':controller/:action/:id'
match 'file/*path', :to => 'test_test/test#test_params'
match ':controller/:action'
end
get :test_params, :path => ['hello', 'world']
@ -628,17 +628,6 @@ XML
assert_nothing_raised(NoMethodError) { @response.binary_content }
end
end
protected
def with_foo_routing
with_routing do |set|
set.draw do |map|
map.generate_url 'foo', :controller => 'test'
map.connect ':controller/:action/:id'
end
yield set
end
end
end
class InferringClassNameTest < ActionController::TestCase
@ -673,7 +662,7 @@ class NamedRoutesControllerTest < ActionController::TestCase
def test_should_be_able_to_use_named_routes_before_a_request_is_done
with_routing do |set|
set.draw { |map| map.resources :contents }
set.draw { |map| resources :contents }
assert_equal 'http://test.host/contents/new', new_content_url
assert_equal 'http://test.host/contents/1', content_url(:id => 1)
end

View file

@ -247,7 +247,7 @@ class UrlWriterTests < ActionController::TestCase
with_routing do |set|
set.draw do |map|
map.home '/home/sweet/home/:user', :controller => 'home', :action => 'index'
match '/home/sweet/home/:user', :to => 'home#index', :as => :home
end
kls = Class.new { include ActionController::UrlWriter }
@ -264,7 +264,7 @@ class UrlWriterTests < ActionController::TestCase
with_routing do |set|
set.draw do |map|
match 'home/sweet/home/:user', :to => 'home#index', :as => :home
map.connect ':controller/:action/:id'
match ':controller/:action/:id'
end
# We need to create a new class in order to install the new named route.
@ -331,8 +331,8 @@ class UrlWriterTests < ActionController::TestCase
def test_named_routes_with_nil_keys
with_routing do |set|
set.draw do |map|
map.main '', :controller => 'posts', :format => nil
map.resources :posts
match 'posts.:format', :to => 'posts#index', :as => :posts
match '/', :to => 'posts#index', :as => :main
end
# We need to create a new class in order to install the new named route.
@ -350,7 +350,7 @@ class UrlWriterTests < ActionController::TestCase
def test_formatted_url_methods_are_deprecated
with_routing do |set|
set.draw do |map|
map.resources :posts
resources :posts
end
# We need to create a new class in order to install the new named route.
kls = Class.new { include ActionController::UrlWriter }

View file

@ -255,9 +255,7 @@ class WebServiceTest < ActionController::IntegrationTest
def with_test_route_set
with_routing do |set|
set.draw do |map|
map.with_options :controller => "web_service_test/test" do |c|
c.connect "/", :action => "assign_parameters"
end
match '/', :to => 'web_service_test/test#assign_parameters'
end
yield
end

View file

@ -151,7 +151,7 @@ class MultipartParamsParsingTest < ActionController::IntegrationTest
def with_test_routing
with_routing do |set|
set.draw do |map|
map.connect ':action', :controller => "multipart_params_parsing_test/test"
match ':action', :to => 'multipart_params_parsing_test/test'
end
yield
end

View file

@ -14,7 +14,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
stub_controllers do |routes|
Routes = routes
Routes.draw do |map|
Routes.draw do
controller :sessions do
get 'login', :to => :new, :as => :login
post 'login', :to => :create
@ -58,8 +58,10 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
resources :people do
namespace ":access_token" do
resource :avatar
nested do
namespace ":access_token" do
resource :avatar
end
end
member do
@ -93,9 +95,9 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
controller :articles do
scope 'articles' do
scope ':title', :title => /[a-z]+/, :as => :with_title do
match ':id', :to => :with_id
scope '/articles', :name_prefix => 'article' do
scope :path => '/:title', :title => /[a-z]+/, :as => :with_title do
match '/:id', :to => :with_id
end
end
end
@ -194,14 +196,26 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
assert_equal 'projects#index', @response.body
assert_equal '/projects', projects_path
get '/projects.xml'
assert_equal 'projects#index', @response.body
assert_equal '/projects.xml', projects_path(:format => 'xml')
get '/projects/new'
assert_equal 'projects#new', @response.body
assert_equal '/projects/new', new_project_path
get '/projects/new.xml'
assert_equal 'projects#new', @response.body
assert_equal '/projects/new.xml', new_project_path(:format => 'xml')
get '/projects/1'
assert_equal 'projects#show', @response.body
assert_equal '/projects/1', project_path(:id => '1')
get '/projects/1.xml'
assert_equal 'projects#show', @response.body
assert_equal '/projects/1.xml', project_path(:id => '1', :format => 'xml')
get '/projects/1/edit'
assert_equal 'projects#edit', @response.body
assert_equal '/projects/1/edit', edit_project_path(:id => '1')
@ -236,10 +250,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
put '/projects/1/participants/update_all'
assert_equal 'participants#update_all', @response.body
pending do
assert_equal '/projects/1/participants/update_all', update_all_project_participants_path(:project_id => '1')
end
assert_equal '/projects/1/participants/update_all', update_all_project_participants_path(:project_id => '1')
end
end
@ -255,9 +266,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
get '/projects/1/companies/1/avatar'
assert_equal 'avatars#show', @response.body
pending do
assert_equal '/projects/1/companies/1/avatar', project_company_avatar_path(:project_id => '1', :company_id => '1')
end
assert_equal '/projects/1/companies/1/avatar', project_company_avatar_path(:project_id => '1', :company_id => '1')
end
end
@ -269,9 +278,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
post '/projects/1/images/1/revise'
assert_equal 'images#revise', @response.body
pending do
assert_equal '/projects/1/images/1/revise', revise_project_image_path(:project_id => '1', :id => '1')
end
assert_equal '/projects/1/images/1/revise', revise_project_image_path(:project_id => '1', :id => '1')
end
end
@ -287,27 +294,19 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
get '/projects/1/people/1/7a2dec8/avatar'
assert_equal 'avatars#show', @response.body
pending do
assert_equal '/projects/1/people/1/7a2dec8/avatar', project_person_avatar_path(:project_id => '1', :person_id => '1', :access_token => '7a2dec8')
end
assert_equal '/projects/1/people/1/7a2dec8/avatar', project_person_avatar_path(:project_id => '1', :person_id => '1', :access_token => '7a2dec8')
put '/projects/1/people/1/accessible_projects'
assert_equal 'people#accessible_projects', @response.body
pending do
assert_equal '/projects/1/people/1/accessible_projects', accessible_projects_project_person_path(:project_id => '1', :id => '1')
end
assert_equal '/projects/1/people/1/accessible_projects', accessible_projects_project_person_path(:project_id => '1', :id => '1')
post '/projects/1/people/1/resend'
assert_equal 'people#resend', @response.body
pending do
assert_equal '/projects/1/people/1/resend', resend_project_person_path(:project_id => '1', :id => '1')
end
assert_equal '/projects/1/people/1/resend', resend_project_person_path(:project_id => '1', :id => '1')
post '/projects/1/people/1/generate_new_password'
assert_equal 'people#generate_new_password', @response.body
pending do
assert_equal '/projects/1/people/1/generate_new_password', generate_new_password_project_person_path(:project_id => '1', :id => '1')
end
assert_equal '/projects/1/people/1/generate_new_password', generate_new_password_project_person_path(:project_id => '1', :id => '1')
end
end
@ -319,27 +318,19 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
get '/projects/1/posts/archive'
assert_equal 'posts#archive', @response.body
pending do
assert_equal '/projects/1/posts/archive', archive_project_posts_path(:project_id => '1')
end
assert_equal '/projects/1/posts/archive', archive_project_posts_path(:project_id => '1')
get '/projects/1/posts/toggle_view'
assert_equal 'posts#toggle_view', @response.body
pending do
assert_equal '/projects/1/posts/toggle_view', toggle_view_project_posts_path(:project_id => '1')
end
assert_equal '/projects/1/posts/toggle_view', toggle_view_project_posts_path(:project_id => '1')
post '/projects/1/posts/1/preview'
assert_equal 'posts#preview', @response.body
pending do
assert_equal '/projects/1/posts/1/preview', preview_project_post_path(:project_id => '1', :id => '1')
end
assert_equal '/projects/1/posts/1/preview', preview_project_post_path(:project_id => '1', :id => '1')
get '/projects/1/posts/1/subscription'
assert_equal 'subscriptions#show', @response.body
pending do
assert_equal '/projects/1/posts/1/subscription', project_post_subscription_path(:project_id => '1', :post_id => '1')
end
assert_equal '/projects/1/posts/1/subscription', project_post_subscription_path(:project_id => '1', :post_id => '1')
get '/projects/1/posts/1/comments'
assert_equal 'comments#index', @response.body
@ -347,9 +338,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
post '/projects/1/posts/1/comments/preview'
assert_equal 'comments#preview', @response.body
pending do
assert_equal '/projects/1/posts/1/comments/preview', preview_project_post_comments_path(:project_id => '1', :post_id => '1')
end
assert_equal '/projects/1/posts/1/comments/preview', preview_project_post_comments_path(:project_id => '1', :post_id => '1')
end
end
@ -407,7 +396,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
assert_raise(ActionController::RoutingError) { get '/articles/123/1' }
assert_equal '/articles/rails/1', with_title_path(:title => 'rails', :id => 1)
assert_equal '/articles/rails/1', article_with_title_path(:title => 'rails', :id => 1)
end
end

View file

@ -187,10 +187,9 @@ class ScrollsController < ActionController::Base
end
protected
def rescue_action(e)
raise(e)
end
def rescue_action(e)
raise(e)
end
end
class AtomFeedTest < ActionController::TestCase
@ -311,11 +310,12 @@ class AtomFeedTest < ActionController::TestCase
assert_select "summary div p", :text => "after 2"
end
end
private
private
def with_restful_routing(resources)
with_routing do |set|
set.draw do |map|
map.resources(resources)
resources(resources)
end
yield
end

View file

@ -114,7 +114,7 @@ module ActionView
test "is able to use named routes" do
with_routing do |set|
set.draw { |map| map.resources :contents }
set.draw { |map| resources :contents }
assert_equal 'http://test.host/contents/new', new_content_url
assert_equal 'http://test.host/contents/1', content_url(:id => 1)
end
@ -122,7 +122,7 @@ module ActionView
test "named routes can be used from helper included in view" do
with_routing do |set|
set.draw { |map| map.resources :contents }
set.draw { |map| resources :contents }
_helpers.module_eval do
def render_from_helper
new_content_url

View file

@ -451,7 +451,7 @@ class UrlHelperControllerTest < ActionController::TestCase
def with_url_helper_routing
with_routing do |set|
set.draw do |map|
map.show_named_route 'url_helper_controller_test/url_helper/show_named_route', :controller => 'url_helper_controller_test/url_helper', :action => 'show_named_route'
match 'url_helper_controller_test/url_helper/show_named_route', :to => 'url_helper_controller_test/url_helper#show_named_route', :as => :show_named_route
end
yield
end
@ -505,7 +505,7 @@ class LinkToUnlessCurrentWithControllerTest < ActionController::TestCase
def with_restful_routing
with_routing do |set|
set.draw do |map|
map.resources :tasks
resources :tasks
end
yield
end
@ -625,8 +625,8 @@ class PolymorphicControllerTest < ActionController::TestCase
def with_restful_routing
with_routing do |set|
set.draw do |map|
map.resources :workshops do |w|
w.resources :sessions
resources :workshops do
resources :sessions
end
end
yield

View file

@ -269,7 +269,7 @@ module Rails
#
# === Example
#
# route "map.root :controller => :welcome"
# route "root :to => 'welcome'"
#
def route(routing_code)
log :route, routing_code

View file

@ -1,43 +1,60 @@
ActionController::Routing::Routes.draw do |map|
# The priority is based upon order of creation: first created -> highest priority.
# The priority is based upon order of creation:
# first created -> highest priority.
# Sample of regular route:
# map.connect 'products/:id', :controller => 'catalog', :action => 'view'
# match 'products/:id', :to => 'catalog#view'
# Keep in mind you can assign values other than :controller and :action
# Sample of named route:
# map.purchase 'products/:id/purchase', :controller => 'catalog', :action => 'purchase'
# match 'products/:id/purchase', :to => 'catalog#purchase', :as => :purchase
# This route can be invoked with purchase_url(:id => product.id)
# Sample resource route (maps HTTP verbs to controller actions automatically):
# map.resources :products
# resources :products
# Sample resource route with options:
# map.resources :products, :member => { :short => :get, :toggle => :post }, :collection => { :sold => :get }
# resources :products do
# member do
# get :short
# post :toggle
# end
#
# collection do
# get :sold
# end
# end
# Sample resource route with sub-resources:
# map.resources :products, :has_many => [ :comments, :sales ], :has_one => :seller
# resources :products do
# resources :comments, :sales
# resource :seller
# end
# Sample resource route with more complex sub-resources
# map.resources :products do |products|
# products.resources :comments
# products.resources :sales, :collection => { :recent => :get }
# resources :products do
# resources :comments
# resources :sales do
# get :recent, :on => :collection
# end
# end
# Sample resource route within a namespace:
# map.namespace :admin do |admin|
# # Directs /admin/products/* to Admin::ProductsController (app/controllers/admin/products_controller.rb)
# admin.resources :products
# namespace :admin do
# # Directs /admin/products/* to Admin::ProductsController
# # (app/controllers/admin/products_controller.rb)
# resources :products
# end
# You can have the root of your site routed with map.root -- just remember to delete public/index.html.
# map.root :controller => "welcome"
# You can have the root of your site routed with "root"
# just remember to delete public/index.html.
# root :to => "welcome"
# See how all your routes lay out with "rake routes"
# Install the default routes as the lowest priority.
# Note: These default routes make all actions in every controller accessible via GET requests. You should
# consider removing or commenting them out if you're using named routes and resources.
map.connect ':controller/:action/:id'
map.connect ':controller/:action/:id.:format'
# Install the default route as the lowest priority.
# Note: The default route make all actions in every controller accessible
# via GET requests. You should consider removing or commenting it out if
# you're using named routes and resources.
match ':controller(/:action(/:id(.:format)))'
end

View file

@ -16,7 +16,7 @@ module Rails
class_option :singleton, :type => :boolean, :desc => "Supply to create a singleton controller"
def add_resource_route
route "map.resource#{:s unless options[:singleton]} :#{pluralize?(file_name)}"
route "resource#{:s unless options[:singleton]} :#{pluralize?(file_name)}"
end
protected

View file

@ -17,7 +17,7 @@ Description:
For example, 'scaffold post title:string body:text published:boolean'
gives you a model with those three attributes, a controller that handles
the create/show/update/destroy, forms to create and edit your posts, and
an index that lists them all, as well as a map.resources :posts
an index that lists them all, as well as a resources :posts
declaration in config/routes.rb.
If you want to remove all the generated files, run

View file

@ -1,3 +1,3 @@
ActionController::Routing::Routes.draw do |map|
map.connect '/engine', :controller => "engine"
match '/engine', :to => "engine"
end

View file

@ -171,7 +171,7 @@ class ActionsTest < GeneratorsTestCase
def test_route_should_add_data_to_the_routes_block_in_config_routes
run_generator
route_command = "map.route '/login', :controller => 'sessions', :action => 'new'"
route_command = "route '/login', :controller => 'sessions', :action => 'new'"
action :route, route_command
assert_file 'config/routes.rb', /#{Regexp.escape(route_command)}/
end

View file

@ -62,7 +62,7 @@ class ResourceGeneratorTest < GeneratorsTestCase
run_generator
assert_file "config/routes.rb" do |route|
assert_match /map\.resources :accounts$/, route
assert_match /resources :accounts$/, route
end
end
@ -70,7 +70,7 @@ class ResourceGeneratorTest < GeneratorsTestCase
run_generator ["account", "--singleton"]
assert_file "config/routes.rb" do |route|
assert_match /map\.resource :account$/, route
assert_match /resource :account$/, route
end
end
@ -93,7 +93,7 @@ class ResourceGeneratorTest < GeneratorsTestCase
run_generator ["account"], :behavior => :revoke
assert_file "config/routes.rb" do |route|
assert_no_match /map\.resources :accounts$/, route
assert_no_match /resources :accounts$/, route
end
end

View file

@ -25,7 +25,7 @@ class ScaffoldGeneratorTest < GeneratorsTestCase
# Route
assert_file "config/routes.rb" do |route|
assert_match /map\.resources :product_lines$/, route
assert_match /resources :product_lines$/, route
end
# Controller
@ -99,7 +99,7 @@ class ScaffoldGeneratorTest < GeneratorsTestCase
# Route
assert_file "config/routes.rb" do |route|
assert_no_match /map\.resources :product_lines$/, route
assert_no_match /resources :product_lines$/, route
end
# Controller

View file

@ -16,7 +16,7 @@ class InfoControllerTest < ActionController::TestCase
def setup
ActionController::Routing::Routes.draw do |map|
map.connect ':controller/:action/:id'
match ':controller/:action'
end
@controller.stubs(:consider_all_requests_local => false, :local_request? => true)
end