Skip to content

Commit

Permalink
A hopefully more successful attempt at the Routing branch merge
Browse files Browse the repository at this point in the history
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@617 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
  • Loading branch information
dhh committed Feb 15, 2005
1 parent 88a3343 commit b1999be
Show file tree
Hide file tree
Showing 62 changed files with 1,803 additions and 480 deletions.
Expand Up @@ -141,7 +141,7 @@ def assert_redirected_to(options = {}, message=nil)
end end
end end
end end

# ensure our redirection url is an exact match # ensure our redirection url is an exact match
def assert_redirect_url(url=nil, message=nil) def assert_redirect_url(url=nil, message=nil)
assert_redirect(message) assert_redirect(message)
Expand All @@ -158,6 +158,36 @@ def assert_redirect_url_match(pattern=nil, message=nil)
assert_block(msg) { response.redirect_url_match?(pattern) } assert_block(msg) { response.redirect_url_match?(pattern) }
end end


# -- routing assertions --------------------------------------------------

# Asserts that the routing of the given path is handled correctly and that the parsed options match.
# Also verifies that the provided options can be used to generate the provided path.
def assert_routing(path, options, defaults={}, extras={}, message=nil)
defaults[:controller] ||= options[:controller] # Assume given controller,
request = ActionController::TestRequest.new({}, {}, nil)
request.path_parameters = defaults.clone

ActionController::Routing::Routes.reload if ActionController::Routing::Routes.empty? # Load routes.rb if it hasn't been loaded.

generated_path, found_extras = ActionController::Routing::Routes.generate(options, request)
generated_path = generated_path.join('/')
msg = build_message(message, "found extras <?>, not <?>", found_extras, extras)
assert_block(msg) { found_extras == extras }

msg = build_message(message, "The generated path <?> did not match <?>", generated_path, path)
assert_block(msg) { path == generated_path }

request = ActionController::TestRequest.new({}, {}, nil)
request.path = path
ActionController::Routing::Routes.recognize!(request)

expected_options = options.clone
extras.each {|k,v| expected_options.delete k}

msg = build_message(message, "The recognized options <?> did not match <?>", request.path_parameters, expected_options)
assert_block(msg) { request.path_parameters == expected_options }
end

# -- template assertions ------------------------------------------------ # -- template assertions ------------------------------------------------


# ensure that a template object with the given name exists # ensure that a template object with the given name exists
Expand Down
32 changes: 26 additions & 6 deletions actionpack/lib/action_controller/base.rb
@@ -1,5 +1,6 @@
require 'action_controller/request' require 'action_controller/request'
require 'action_controller/response' require 'action_controller/response'
require 'action_controller/routing'
require 'action_controller/url_rewriter' require 'action_controller/url_rewriter'
require 'action_controller/support/class_attribute_accessors' require 'action_controller/support/class_attribute_accessors'
require 'action_controller/support/class_inheritable_attributes' require 'action_controller/support/class_inheritable_attributes'
Expand All @@ -13,6 +14,15 @@ class SessionRestoreError < ActionControllerError #:nodoc:
end end
class MissingTemplate < ActionControllerError #:nodoc: class MissingTemplate < ActionControllerError #:nodoc:
end end
class RoutingError < ActionControllerError
attr_reader :failures
def initialize(message, failures=[])
super(message)
@failures = failures
end
end
class UnknownController < ActionControllerError #:nodoc:
end
class UnknownAction < ActionControllerError #:nodoc: class UnknownAction < ActionControllerError #:nodoc:
end end
class MissingFile < ActionControllerError #:nodoc: class MissingFile < ActionControllerError #:nodoc:
Expand Down Expand Up @@ -205,6 +215,12 @@ class Base
# should instead be implemented in the controller to determine when debugging screens should be shown. # should instead be implemented in the controller to determine when debugging screens should be shown.
@@consider_all_requests_local = true @@consider_all_requests_local = true
cattr_accessor :consider_all_requests_local cattr_accessor :consider_all_requests_local

# Enable or disable the collection of failure information for RoutingErrors.
# This information can be extremely useful when tweaking custom routes, but is
# pointless once routes have been tested and verified.
@@debug_routes = true
cattr_accessor :debug_routes


# Template root determines the base from which template references will be made. So a call to render("test/template") # Template root determines the base from which template references will be made. So a call to render("test/template")
# will be converted to "#{template_root}/test/template.rhtml". # will be converted to "#{template_root}/test/template.rhtml".
Expand Down Expand Up @@ -261,6 +277,14 @@ def controller_class_name
def controller_name def controller_name
Inflector.underscore(controller_class_name.sub(/Controller/, "")) Inflector.underscore(controller_class_name.sub(/Controller/, ""))
end end

# Convert the class name from something like "OneModule::TwoModule::NeatController" to "one_module/two_module/neat".
def controller_path
components = self.name.to_s.split('::').collect { |name| name.underscore }
components[-1] = $1 if /^(.*)_controller$/ =~ components[-1]
components.shift if components.first == 'controllers' # Transitional conditional to accomodate root Controllers module
components.join('/')
end
end end


public public
Expand Down Expand Up @@ -337,10 +361,6 @@ def url_for(options = {}, *parameters_for_method_reference) #:doc:
end end
end end


def module_name
@params["module"]
end

# Converts the class name from something like "OneModule::TwoModule::NeatController" to "NeatController". # Converts the class name from something like "OneModule::TwoModule::NeatController" to "NeatController".
def controller_class_name def controller_class_name
self.class.controller_class_name self.class.controller_class_name
Expand Down Expand Up @@ -594,7 +614,7 @@ def assign_shortcuts(request, response)
end end


def initialize_current_url def initialize_current_url
@url = UrlRewriter.new(@request, controller_name, action_name) @url = UrlRewriter.new(@request, @params.clone())
end end


def log_processing def log_processing
Expand Down Expand Up @@ -691,7 +711,7 @@ def send_file_headers!(options)
end end


def default_template_name(default_action_name = action_name) def default_template_name(default_action_name = action_name)
module_name ? "#{module_name}/#{controller_name}/#{default_action_name}" : "#{controller_name}/#{default_action_name}" "#{self.class.controller_path}/#{default_action_name}"
end end
end end
end end
10 changes: 9 additions & 1 deletion actionpack/lib/action_controller/cgi_process.rb
Expand Up @@ -46,8 +46,16 @@ def initialize(cgi, session_options = {})
super() super()
end end


def query_string
return @cgi.query_string unless @cgi.query_string.nil? || @cgi.query_string.empty?
parts = env['REQUEST_URI'].split('?')
parts.shift
return parts.join('?')
end

def query_parameters def query_parameters
@cgi.query_string ? CGIMethods.parse_query_parameters(@cgi.query_string) : {} qs = self.query_string
qs.empty? ? {} : CGIMethods.parse_query_parameters(query_string)
end end


def request_parameters def request_parameters
Expand Down
35 changes: 16 additions & 19 deletions actionpack/lib/action_controller/helpers.rb
Expand Up @@ -48,25 +48,22 @@ def add_template_helper(helper_module) #:nodoc:
def helper(*args, &block) def helper(*args, &block)
args.flatten.each do |arg| args.flatten.each do |arg|
case arg case arg
when Module when Module
add_template_helper(arg) add_template_helper(arg)
when String, Symbol when String, Symbol
file_name = Inflector.underscore(arg.to_s.downcase) + '_helper' file_name = arg.to_s.underscore + '_helper'
class_name = Inflector.camelize(file_name) class_name = file_name.camelize
begin
require_dependency(file_name) begin
rescue LoadError => load_error require_dependency(file_name)
requiree = / -- (.*?)(\.rb)?$/.match(load_error).to_a[1] rescue LoadError => load_error
if requiree == file_name requiree = / -- (.*?)(\.rb)?$/.match(load_error).to_a[1]
raise LoadError, "Missing helper file helpers/#{file_name}.rb" raise LoadError, requiree == file_name ? "Missing helper file helpers/#{file_name}.rb" : "Can't load file: #{requiree}"
else
raise LoadError, "Can't load file: #{requiree}"
end end
end
raise ArgumentError, "Missing #{class_name} module in helpers/#{file_name}.rb" unless Object.const_defined?(class_name) add_template_helper(class_name.constantize)
add_template_helper(Object.const_get(class_name)) else
else raise ArgumentError, 'helper expects String, Symbol, or Module argument'
raise ArgumentError, 'helper expects String, Symbol, or Module argument'
end end
end end


Expand Down Expand Up @@ -95,7 +92,7 @@ def helper_attr(*attrs)
def inherited(child) def inherited(child)
inherited_without_helper(child) inherited_without_helper(child)
begin begin
child.helper(child.controller_name) child.helper(child.controller_path)
rescue ArgumentError, LoadError rescue ArgumentError, LoadError
# No default helper available for this controller # No default helper available for this controller
end end
Expand Down
16 changes: 13 additions & 3 deletions actionpack/lib/action_controller/request.rb
Expand Up @@ -3,7 +3,8 @@ module ActionController
class AbstractRequest class AbstractRequest
# Returns both GET and POST parameters in a single hash. # Returns both GET and POST parameters in a single hash.
def parameters def parameters
@parameters ||= request_parameters.update(query_parameters) # puts "#{request_parameters.inspect} | #{query_parameters.inspect} | #{path_parameters.inspect}"
@parameters ||= request_parameters.merge(query_parameters).merge(path_parameters).with_indifferent_access
end end


def method def method
Expand Down Expand Up @@ -73,7 +74,7 @@ def raw_post
end end


def request_uri def request_uri
env['REQUEST_URI'] (%r{^\w+\://[^/]+(/.*|$)$} =~ env['REQUEST_URI']) ? $1 : env['REQUEST_URI'] # Remove domain, which webrick puts into the request_uri.
end end


def protocol def protocol
Expand All @@ -85,7 +86,7 @@ def ssl?
end end


def path def path
request_uri ? request_uri.split('?').first : '' path = request_uri ? request_uri.split('?').first : ''
end end


def port def port
Expand All @@ -100,7 +101,16 @@ def port_string
def host_with_port def host_with_port
env['HTTP_HOST'] || host + port_string env['HTTP_HOST'] || host + port_string
end end

def path_parameters=(parameters)
@path_parameters = parameters
@parameters = nil
end


def path_parameters
@path_parameters ||= {}
end

#-- #--
# Must be implemented in the concrete request # Must be implemented in the concrete request
#++ #++
Expand Down
18 changes: 15 additions & 3 deletions actionpack/lib/action_controller/rescue.rb
Expand Up @@ -48,7 +48,11 @@ def log_error(exception) #:doc:


# Overwrite to implement public exception handling (for requests answering false to <tt>local_request?</tt>). # Overwrite to implement public exception handling (for requests answering false to <tt>local_request?</tt>).
def rescue_action_in_public(exception) #:doc: def rescue_action_in_public(exception) #:doc:
render_text "<html><body><h1>Application error (Rails)</h1></body></html>" case exception
when RoutingError, UnknownAction then
render_text(IO.read(File.join(RAILS_ROOT, 'public', '404.html')), "404 Not Found")
else render_text "<html><body><h1>Application error (Rails)</h1></body></html>"
end
end end


# Overwrite to expand the meaning of a local request in order to show local rescues on other occurences than # Overwrite to expand the meaning of a local request in order to show local rescues on other occurences than
Expand All @@ -66,7 +70,7 @@ def rescue_action_locally(exception)
@contents = @template.render_file(template_path_for_local_rescue(exception), false) @contents = @template.render_file(template_path_for_local_rescue(exception), false)


@headers["Content-Type"] = "text/html" @headers["Content-Type"] = "text/html"
render_file(rescues_path("layout"), "500 Internal Error") render_file(rescues_path("layout"), response_code_for_rescue(exception))
end end


private private
Expand Down Expand Up @@ -110,13 +114,21 @@ def template_path_for_local_rescue(exception)
rescues_path( rescues_path(
case exception case exception
when MissingTemplate then "missing_template" when MissingTemplate then "missing_template"
when RoutingError then "routing_error"
when UnknownAction then "unknown_action" when UnknownAction then "unknown_action"
when ActionView::TemplateError then "template_error" when ActionView::TemplateError then "template_error"
else "diagnostics" else raise ;"diagnostics"
end end
) )
end end


def response_code_for_rescue(exception)
case exception
when UnknownAction, RoutingError then "404 Page Not Found"
else "500 Internal Error"
end
end

def clean_backtrace(exception) def clean_backtrace(exception)
exception.backtrace.collect { |line| Object.const_defined?(:RAILS_ROOT) ? line.gsub(RAILS_ROOT, "") : line } exception.backtrace.collect { |line| Object.const_defined?(:RAILS_ROOT) ? line.gsub(RAILS_ROOT, "") : line }
end end
Expand Down

0 comments on commit b1999be

Please sign in to comment.