aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Heinemeier Hansson <david@loudthinking.com>2005-02-15 00:51:02 +0000
committerDavid Heinemeier Hansson <david@loudthinking.com>2005-02-15 00:51:02 +0000
commitc844755e5a0c3d4edfcc78f9c30ef91fa0de550a (patch)
tree4cf4890fc5af5f58dd0a6a19c0a6fea6ed39a1df
parenta3298e5efdf33398b49933323ea3fef7ff4e9a9c (diff)
downloadrails-c844755e5a0c3d4edfcc78f9c30ef91fa0de550a.tar.gz
rails-c844755e5a0c3d4edfcc78f9c30ef91fa0de550a.tar.bz2
rails-c844755e5a0c3d4edfcc78f9c30ef91fa0de550a.zip
Merged back the Routing branch
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@614 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
-rw-r--r--actionpack/lib/action_controller/assertions/action_pack_assertions.rb32
-rwxr-xr-xactionpack/lib/action_controller/base.rb27
-rw-r--r--actionpack/lib/action_controller/cgi_process.rb10
-rw-r--r--actionpack/lib/action_controller/helpers.rb35
-rwxr-xr-xactionpack/lib/action_controller/request.rb15
-rw-r--r--actionpack/lib/action_controller/rescue.rb16
-rw-r--r--actionpack/lib/action_controller/scaffolding.rb2
-rw-r--r--actionpack/lib/action_controller/templates/rescues/routing_error.rhtml8
-rw-r--r--actionpack/lib/action_controller/test_process.rb22
-rw-r--r--actionpack/lib/action_controller/url_rewriter.rb23
-rw-r--r--actionpack/lib/action_view/partials.rb2
-rw-r--r--actionpack/test/controller/cookie_test.rb9
-rw-r--r--actionpack/test/controller/helper_test.rb37
-rw-r--r--actionpack/test/controller/render_test.rb136
-rw-r--r--actionpack/test/controller/request_test.rb22
-rw-r--r--actionpack/test/controller/routing_tests.rb401
-rw-r--r--actionpack/test/controller/url_obsolete.rb (renamed from actionpack/test/controller/url_test.rb)38
-rw-r--r--actionpack/test/fixtures/fun/games/hello_world.rhtml1
-rw-r--r--actionpack/test/fixtures/helpers/fun/games_helper.rb3
-rw-r--r--activesupport/CHANGELOG4
-rw-r--r--activesupport/lib/core_ext/hash/indifferent_access.rb10
-rw-r--r--activesupport/lib/core_ext/string/inflections.rb4
-rw-r--r--activesupport/lib/dependencies.rb67
-rw-r--r--activesupport/lib/inflector.rb12
-rw-r--r--activesupport/test/inflector_test.rb31
-rw-r--r--activesupport/test/loading_module/admin/access_controller.rb2
-rw-r--r--activesupport/test/loading_module/admin/user_controller.rb2
-rw-r--r--activesupport/test/loading_module/content_controller.rb2
-rw-r--r--activesupport/test/loading_module/resource_controller.rb2
-rw-r--r--activesupport/test/loading_module_tests.rb63
-rw-r--r--railties/bin/destroy3
-rwxr-xr-xrailties/bin/generate3
-rwxr-xr-xrailties/bin/rails3
-rw-r--r--railties/bin/update3
-rwxr-xr-xrailties/configs/apache.conf59
-rw-r--r--railties/environments/shared.rb2
-rw-r--r--railties/environments/shared_for_gem.rb2
-rw-r--r--railties/generators/model/USAGE0
-rw-r--r--railties/lib/dispatcher.rb52
-rw-r--r--railties/lib/rails_generator.rb6
-rw-r--r--railties/lib/rails_generator/base.rb21
-rw-r--r--railties/lib/rails_generator/generators/applications/app/app_generator.rb6
-rw-r--r--railties/lib/rails_generator/generators/components/controller/controller_generator.rb5
-rw-r--r--railties/lib/rails_generator/generators/components/controller/templates/functional_test.rb3
-rw-r--r--railties/lib/rails_generator/generators/components/mailer/mailer_generator.rb21
-rw-r--r--railties/lib/rails_generator/generators/components/model/model_generator.rb5
-rw-r--r--railties/lib/rails_generator/generators/components/model/templates/fixtures.yml6
-rw-r--r--railties/lib/rails_generator/generators/components/model/templates/unit_test.rb4
-rw-r--r--railties/lib/rails_generator/generators/components/scaffold/scaffold_generator.rb29
-rw-r--r--railties/lib/rails_generator/generators/components/scaffold/templates/functional_test.rb18
-rw-r--r--railties/lib/rails_generator/generators/components/scaffold/templates/view_list.rhtml2
-rw-r--r--railties/lib/rails_generator/lookup.rb30
-rw-r--r--railties/lib/rails_generator/options.rb19
-rw-r--r--railties/lib/rails_generator/scripts.rb28
-rw-r--r--railties/lib/rails_generator/scripts/destroy.rb4
-rw-r--r--railties/lib/rails_generator/scripts/generate.rb4
-rw-r--r--railties/lib/rails_generator/scripts/update.rb3
-rw-r--r--railties/test/rails_generator_test.rb25
58 files changed, 1042 insertions, 362 deletions
diff --git a/actionpack/lib/action_controller/assertions/action_pack_assertions.rb b/actionpack/lib/action_controller/assertions/action_pack_assertions.rb
index c26941cd6b..7d27240244 100644
--- a/actionpack/lib/action_controller/assertions/action_pack_assertions.rb
+++ b/actionpack/lib/action_controller/assertions/action_pack_assertions.rb
@@ -141,7 +141,7 @@ module Test #:nodoc:
end
end
end
-
+
# ensure our redirection url is an exact match
def assert_redirect_url(url=nil, message=nil)
assert_redirect(message)
@@ -158,6 +158,36 @@ module Test #:nodoc:
assert_block(msg) { response.redirect_url_match?(pattern) }
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
+
+ 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(defaults.merge(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 ------------------------------------------------
# ensure that a template object with the given name exists
diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb
index cfcd46d985..a30f3b94d7 100755
--- a/actionpack/lib/action_controller/base.rb
+++ b/actionpack/lib/action_controller/base.rb
@@ -13,6 +13,13 @@ module ActionController #:nodoc:
end
class MissingTemplate < ActionControllerError #:nodoc:
end
+ class RoutingError < ActionControllerError
+ attr_reader :failures
+ def initialize(message, failures=[])
+ super(message)
+ @failures = failures
+ end
+ end
class UnknownAction < ActionControllerError #:nodoc:
end
class MissingFile < ActionControllerError #:nodoc:
@@ -205,6 +212,12 @@ module ActionController #:nodoc:
# should instead be implemented in the controller to determine when debugging screens should be shown.
@@consider_all_requests_local = true
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")
# will be converted to "#{template_root}/test/template.rhtml".
@@ -261,6 +274,14 @@ module ActionController #:nodoc:
def controller_name
Inflector.underscore(controller_class_name.sub(/Controller/, ""))
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
public
@@ -337,10 +358,6 @@ module ActionController #:nodoc:
end
end
- def module_name
- @params["module"]
- end
-
# Converts the class name from something like "OneModule::TwoModule::NeatController" to "NeatController".
def controller_class_name
self.class.controller_class_name
@@ -691,7 +708,7 @@ module ActionController #:nodoc:
end
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
diff --git a/actionpack/lib/action_controller/cgi_process.rb b/actionpack/lib/action_controller/cgi_process.rb
index 92b19fbf18..c301b322e5 100644
--- a/actionpack/lib/action_controller/cgi_process.rb
+++ b/actionpack/lib/action_controller/cgi_process.rb
@@ -46,8 +46,16 @@ module ActionController #:nodoc:
super()
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
- @cgi.query_string ? CGIMethods.parse_query_parameters(@cgi.query_string) : {}
+ qs = self.query_string
+ qs.empty? ? {} : CGIMethods.parse_query_parameters(query_string)
end
def request_parameters
diff --git a/actionpack/lib/action_controller/helpers.rb b/actionpack/lib/action_controller/helpers.rb
index 1201d31946..a97fd93410 100644
--- a/actionpack/lib/action_controller/helpers.rb
+++ b/actionpack/lib/action_controller/helpers.rb
@@ -48,25 +48,22 @@ module ActionController #:nodoc:
def helper(*args, &block)
args.flatten.each do |arg|
case arg
- when Module
- add_template_helper(arg)
- when String, Symbol
- file_name = Inflector.underscore(arg.to_s.downcase) + '_helper'
- class_name = Inflector.camelize(file_name)
- begin
- require_dependency(file_name)
- rescue LoadError => load_error
- requiree = / -- (.*?)(\.rb)?$/.match(load_error).to_a[1]
- if requiree == file_name
- raise LoadError, "Missing helper file helpers/#{file_name}.rb"
- else
- raise LoadError, "Can't load file: #{requiree}"
+ when Module
+ add_template_helper(arg)
+ when String, Symbol
+ file_name = arg.to_s.underscore + '_helper'
+ class_name = file_name.camelize
+
+ begin
+ require_dependency(file_name)
+ rescue LoadError => load_error
+ requiree = / -- (.*?)(\.rb)?$/.match(load_error).to_a[1]
+ raise LoadError, requiree == file_name ? "Missing helper file helpers/#{file_name}.rb" : "Can't load file: #{requiree}"
end
- end
- raise ArgumentError, "Missing #{class_name} module in helpers/#{file_name}.rb" unless Object.const_defined?(class_name)
- add_template_helper(Object.const_get(class_name))
- else
- raise ArgumentError, 'helper expects String, Symbol, or Module argument'
+
+ add_template_helper(class_name.constantize)
+ else
+ raise ArgumentError, 'helper expects String, Symbol, or Module argument'
end
end
@@ -95,7 +92,7 @@ module ActionController #:nodoc:
def inherited(child)
inherited_without_helper(child)
begin
- child.helper(child.controller_name)
+ child.helper(child.controller_path)
rescue ArgumentError, LoadError
# No default helper available for this controller
end
diff --git a/actionpack/lib/action_controller/request.rb b/actionpack/lib/action_controller/request.rb
index 3e2344c3cb..2ac6081a96 100755
--- a/actionpack/lib/action_controller/request.rb
+++ b/actionpack/lib/action_controller/request.rb
@@ -3,7 +3,7 @@ module ActionController
class AbstractRequest
# Returns both GET and POST parameters in a single hash.
def parameters
- @parameters ||= request_parameters.update(query_parameters)
+ @parameters ||= request_parameters.merge(query_parameters).merge(path_parameters).with_indifferent_access
end
def method
@@ -73,7 +73,7 @@ module ActionController
end
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
def protocol
@@ -85,7 +85,7 @@ module ActionController
end
def path
- request_uri ? request_uri.split('?').first : ''
+ path = request_uri ? request_uri.split('?').first : ''
end
def port
@@ -100,7 +100,16 @@ module ActionController
def host_with_port
env['HTTP_HOST'] || host + port_string
end
+
+ def path_parameters=(parameters)
+ @path_parameters = parameters
+ @parameters = nil
+ end
+ def path_parameters
+ @path_parameters ||= {}
+ end
+
#--
# Must be implemented in the concrete request
#++
diff --git a/actionpack/lib/action_controller/rescue.rb b/actionpack/lib/action_controller/rescue.rb
index eb7f614de0..9eb64ba7cc 100644
--- a/actionpack/lib/action_controller/rescue.rb
+++ b/actionpack/lib/action_controller/rescue.rb
@@ -48,7 +48,11 @@ module ActionController #:nodoc:
# Overwrite to implement public exception handling (for requests answering false to <tt>local_request?</tt>).
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
# Overwrite to expand the meaning of a local request in order to show local rescues on other occurences than
@@ -110,13 +114,21 @@ module ActionController #:nodoc:
rescues_path(
case exception
when MissingTemplate then "missing_template"
+ when RoutingError then "routing_error"
when UnknownAction then "unknown_action"
when ActionView::TemplateError then "template_error"
- else "diagnostics"
+ else raise ;"diagnostics"
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)
exception.backtrace.collect { |line| Object.const_defined?(:RAILS_ROOT) ? line.gsub(RAILS_ROOT, "") : line }
end
diff --git a/actionpack/lib/action_controller/scaffolding.rb b/actionpack/lib/action_controller/scaffolding.rb
index 9c1311efa3..140df73972 100644
--- a/actionpack/lib/action_controller/scaffolding.rb
+++ b/actionpack/lib/action_controller/scaffolding.rb
@@ -149,7 +149,7 @@ module ActionController
private
def render#{suffix}_scaffold(action = caller_method_name(caller))
- if template_exists?("\#{controller_name}/\#{action}")
+ if template_exists?("\#{self.class.controller_path}/\#{action}")
render_action(action)
else
@scaffold_class = #{class_name}
diff --git a/actionpack/lib/action_controller/templates/rescues/routing_error.rhtml b/actionpack/lib/action_controller/templates/rescues/routing_error.rhtml
new file mode 100644
index 0000000000..82c01e10c9
--- /dev/null
+++ b/actionpack/lib/action_controller/templates/rescues/routing_error.rhtml
@@ -0,0 +1,8 @@
+<h1>Routing Error</h1>
+<p><%=h @exception.message %></p>
+<% unless @exception.failures.empty? %><p>
+ <h2>Failure reasons:</h2>
+ <% @exception.failures.each do |route, reason| %>
+ <%=h route.inspect.gsub('\\', '') %> failed because <%=h reason.downcase %><br />
+ <% end %>
+</p><% end %>
diff --git a/actionpack/lib/action_controller/test_process.rb b/actionpack/lib/action_controller/test_process.rb
index d4dfe7933d..3223da198c 100644
--- a/actionpack/lib/action_controller/test_process.rb
+++ b/actionpack/lib/action_controller/test_process.rb
@@ -31,8 +31,8 @@ module ActionController #:nodoc:
class TestRequest < AbstractRequest #:nodoc:
attr_accessor :cookies
- attr_accessor :query_parameters, :request_parameters, :session, :env
- attr_accessor :host, :path, :request_uri, :remote_addr
+ attr_accessor :query_parameters, :request_parameters, :path, :session, :env
+ attr_accessor :host, :remote_addr
def initialize(query_parameters = nil, request_parameters = nil, session = nil)
@query_parameters = query_parameters || {}
@@ -58,11 +58,28 @@ module ActionController #:nodoc:
@parameters = nil
end
+ # Used to check AbstractRequest's request_uri functionality.
+ # Disables the use of @path and @request_uri so superclass can handle those.
+ def set_REQUEST_URI(value)
+ @env["REQUEST_URI"] = value
+ @request_uri = nil
+ @path = nil
+ end
+
def request_uri=(uri)
@request_uri = uri
@path = uri.split("?").first
end
+ def request_uri
+ @request_uri || super()
+ end
+
+ def path
+ @path || super()
+ end
+
+
private
def initialize_containers
@env, @cookies = {}, {}
@@ -237,6 +254,7 @@ module Test
def process(action, parameters = nil, session = nil)
@request.env['REQUEST_METHOD'] ||= "GET"
@request.action = action.to_s
+ @request.path_parameters = { :controller => @controller.class.controller_path }
@request.parameters.update(parameters) unless parameters.nil?
@request.session = ActionController::TestSession.new(session) unless session.nil?
@controller.process(@request, @response)
diff --git a/actionpack/lib/action_controller/url_rewriter.rb b/actionpack/lib/action_controller/url_rewriter.rb
index 3451e6acc9..3364262e4c 100644
--- a/actionpack/lib/action_controller/url_rewriter.rb
+++ b/actionpack/lib/action_controller/url_rewriter.rb
@@ -1,10 +1,9 @@
module ActionController
# Rewrites URLs for Base.redirect_to and Base.url_for in the controller.
class UrlRewriter #:nodoc:
- VALID_OPTIONS = [:action, :action_prefix, :action_suffix, :application_prefix, :module, :controller, :controller_prefix, :anchor, :params, :path_params, :id, :only_path, :overwrite_params, :host, :protocol ]
-
- def initialize(request, controller, action)
- @request, @controller, @action = request, controller, action
+ RESERVED_OPTIONS = [:anchor, :params, :path_params, :only_path, :host, :protocol]
+ def initialize(request, parameters)
+ @request, @parameters = request, parameters
@rewritten_path = @request.path ? @request.path.dup : ""
end
@@ -22,7 +21,7 @@ module ActionController
end
def to_str
- "#{@request.protocol}, #{@request.host_with_port}, #{@request.path}, #{@controller}, #{@action}, #{@request.parameters.inspect}"
+ "#{@request.protocol}, #{@request.host_with_port}, #{@request.path}, #{@parameters[:controller]}, #{@parameters[:action]}, #{@request.parameters.inspect}"
end
private
@@ -48,12 +47,14 @@ module ActionController
return rewritten_url
end
- def rewrite_path(path, options)
- include_id_in_path_params(options)
-
- path = rewrite_action(path, options) if options[:action] || options[:action_prefix]
- path = rewrite_path_params(path, options) if options[:path_params]
- path = rewrite_controller(path, options) if options[:controller] || options[:controller_prefix]
+ def rewrite_path(options)
+ options = options.symbolize_keys
+ RESERVED_OPTIONS.each {|k| options.delete k}
+
+ path, extras = Routing::Routes.generate(options, @request)
+ path = "/#{path.join('/')}"
+ path += build_query_string(extras)
+
return path
end
diff --git a/actionpack/lib/action_view/partials.rb b/actionpack/lib/action_view/partials.rb
index f771f0a826..bbb38778b7 100644
--- a/actionpack/lib/action_view/partials.rb
+++ b/actionpack/lib/action_view/partials.rb
@@ -60,7 +60,7 @@ module ActionView
if partial_path.include?('/')
return File.dirname(partial_path), File.basename(partial_path)
else
- return controller.send(:controller_name), partial_path
+ return controller.class.controller_path, partial_path
end
end
diff --git a/actionpack/test/controller/cookie_test.rb b/actionpack/test/controller/cookie_test.rb
index 3f9dafacd6..2b5b1cae9f 100644
--- a/actionpack/test/controller/cookie_test.rb
+++ b/actionpack/test/controller/cookie_test.rb
@@ -28,10 +28,6 @@ class CookieTest < Test::Unit::TestCase
render_text "hello world"
end
- def access_frozen_cookies
- @cookies["wont"] = "work"
- end
-
def rescue_action(e) raise end
end
@@ -67,11 +63,6 @@ class CookieTest < Test::Unit::TestCase
assert_equal 2, process_request.headers["cookie"].size
end
- def test_setting_cookie_on_frozen_instance_variable
- @request.action = "access_frozen_cookies"
- assert_raises(TypeError) { process_request }
- end
-
private
def process_request
TestController.process(@request, @response)
diff --git a/actionpack/test/controller/helper_test.rb b/actionpack/test/controller/helper_test.rb
index b824e40125..0a9840f705 100644
--- a/actionpack/test/controller/helper_test.rb
+++ b/actionpack/test/controller/helper_test.rb
@@ -1,20 +1,30 @@
require File.dirname(__FILE__) + '/../abstract_unit'
+$:.unshift(File.dirname(__FILE__) + '/../fixtures/helpers')
-class HelperTest < Test::Unit::TestCase
- HELPER_PATHS = %w(/../fixtures/helpers)
+class TestController < ActionController::Base
+ attr_accessor :delegate_attr
+ def delegate_method() end
+ def rescue_action(e) raise end
+end
+
+module Fun
+ class GamesController < ActionController::Base
+ def render_hello_world
+ render_template "hello: <%= stratego %>"
+ end
- class TestController < ActionController::Base
- attr_accessor :delegate_attr
- def delegate_method() end
def rescue_action(e) raise end
end
+end
- module LocalAbcHelper
- def a() end
- def b() end
- def c() end
- end
+module LocalAbcHelper
+ def a() end
+ def b() end
+ def c() end
+end
+class HelperTest < Test::Unit::TestCase
+ HELPER_PATHS = %w(/../fixtures/helpers)
def setup
# Increment symbol counter.
@@ -102,6 +112,13 @@ class HelperTest < Test::Unit::TestCase
assert template_methods.include?('delegate_attr=')
end
+ def test_helper_for_nested_controller
+ @request = ActionController::TestRequest.new
+ @response = ActionController::TestResponse.new
+ @request.action = "render_hello_world"
+
+ assert_equal "hello: Iz guuut!", Fun::GamesController.process(@request, @response).body
+ end
private
def helper_methods; TestHelper.instance_methods end
diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb
index f983960e2e..afffd15793 100644
--- a/actionpack/test/controller/render_test.rb
+++ b/actionpack/test/controller/render_test.rb
@@ -2,86 +2,91 @@ require File.dirname(__FILE__) + '/../abstract_unit'
Customer = Struct.new("Customer", :name)
-class RenderTest < Test::Unit::TestCase
- class TestController < ActionController::Base
- layout :determine_layout
-
+module Fun
+ class GamesController < ActionController::Base
def hello_world
end
+ end
+end
- def render_hello_world
- render "test/hello_world"
- end
-
- def render_hello_world_from_variable
- @person = "david"
- render_text "hello #{@person}"
- end
- def render_action_hello_world
- render_action "hello_world"
- end
-
- def render_text_hello_world
- render_text "hello world"
- end
+class TestController < ActionController::Base
+ layout :determine_layout
- def render_custom_code
- render_text "hello world", "404 Moved"
- end
-
- def render_xml_hello
- @name = "David"
- render "test/hello"
- end
+ def hello_world
+ end
- def greeting
- # let's just rely on the template
- end
+ def render_hello_world
+ render "test/hello_world"
+ end
- def layout_test
- render_action "hello_world"
- end
-
- def builder_layout_test
- render_action "hello"
- end
+ def render_hello_world_from_variable
+ @person = "david"
+ render_text "hello #{@person}"
+ end
- def partials_list
- @customers = [ Customer.new("david"), Customer.new("mary") ]
- render_action "list"
- end
+ def render_action_hello_world
+ render_action "hello_world"
+ end
+
+ def render_text_hello_world
+ render_text "hello world"
+ end
- def modgreet
- end
+ def render_custom_code
+ render_text "hello world", "404 Moved"
+ end
+
+ def render_xml_hello
+ @name = "David"
+ render "test/hello"
+ end
- def rescue_action(e) raise end
-
- private
- def determine_layout
- case action_name
- when "layout_test": "layouts/standard"
- when "builder_layout_test": "layouts/builder"
- end
- end
+ def greeting
+ # let's just rely on the template
end
- TestController.template_root = File.dirname(__FILE__) + "/../fixtures/"
+ def layout_test
+ render_action "hello_world"
+ end
- class TestLayoutController < ActionController::Base
- layout "layouts/standard"
-
- def hello_world
- end
+ def builder_layout_test
+ render_action "hello"
+ end
+
+ def partials_list
+ @customers = [ Customer.new("david"), Customer.new("mary") ]
+ render_action "list"
+ end
+
+ def rescue_action(e) raise end
- def hello_world_outside_layout
+ private
+ def determine_layout
+ case action_name
+ when "layout_test": "layouts/standard"
+ when "builder_layout_test": "layouts/builder"
+ end
end
+end
- def rescue_action(e)
- raise unless ActionController::MissingTemplate === e
- end
+TestController.template_root = File.dirname(__FILE__) + "/../fixtures/"
+
+class TestLayoutController < ActionController::Base
+ layout "layouts/standard"
+
+ def hello_world
end
+
+ def hello_world_outside_layout
+ end
+
+ def rescue_action(e)
+ raise unless ActionController::MissingTemplate === e
+ end
+end
+class RenderTest < Test::Unit::TestCase
def setup
@request = ActionController::TestRequest.new
@response = ActionController::TestResponse.new
@@ -170,10 +175,9 @@ class RenderTest < Test::Unit::TestCase
assert_equal "Hello: davidHello: mary", process_request.body
end
- def test_module_rendering
- @request.action = "modgreet"
- @request.parameters["module"] = "scope"
- assert_equal "<p>Beautiful modules!</p>", process_request.body
+ def test_nested_rendering
+ @request.action = "hello_world"
+ assert_equal "Living in a nested world", Fun::GamesController.process(@request, @response).body
end
private
diff --git a/actionpack/test/controller/request_test.rb b/actionpack/test/controller/request_test.rb
index ebab660eab..c31cdd460b 100644
--- a/actionpack/test/controller/request_test.rb
+++ b/actionpack/test/controller/request_test.rb
@@ -31,6 +31,28 @@ class RequestTest < Test::Unit::TestCase
@request.port = 8080
assert_equal ":8080", @request.port_string
end
+
+ def test_request_uri
+ @request.set_REQUEST_URI "http://www.rubyonrails.org/path/of/some/uri?mapped=1"
+ assert_equal "/path/of/some/uri?mapped=1", @request.request_uri
+ assert_equal "/path/of/some/uri", @request.path
+
+ @request.set_REQUEST_URI "http://www.rubyonrails.org/path/of/some/uri"
+ assert_equal "/path/of/some/uri", @request.request_uri
+ assert_equal "/path/of/some/uri", @request.path
+
+ @request.set_REQUEST_URI "/path/of/some/uri"
+ assert_equal "/path/of/some/uri", @request.request_uri
+ assert_equal "/path/of/some/uri", @request.path
+
+ @request.set_REQUEST_URI "/"
+ assert_equal "/", @request.request_uri
+ assert_equal "/", @request.path
+
+ @request.set_REQUEST_URI "/?m=b"
+ assert_equal "/?m=b", @request.request_uri
+ assert_equal "/", @request.path
+ end
def test_host_with_port
@request.env['HTTP_HOST'] = "rubyonrails.org:8080"
diff --git a/actionpack/test/controller/routing_tests.rb b/actionpack/test/controller/routing_tests.rb
new file mode 100644
index 0000000000..307881554f
--- /dev/null
+++ b/actionpack/test/controller/routing_tests.rb
@@ -0,0 +1,401 @@
+# Code Generated by ZenTest v. 2.3.0
+# Couldn't find class for name Routing
+# classname: asrt / meth = ratio%
+# ActionController::Routing::RouteSet: 0 / 16 = 0.00%
+# ActionController::Routing::RailsRoute: 0 / 4 = 0.00%
+# ActionController::Routing::Route: 0 / 8 = 0.00%
+
+RAILS_ROOT = ""
+require File.dirname(__FILE__) + '/../abstract_unit'
+require 'test/unit'
+require 'cgi'
+
+class FakeController
+ attr_reader :controller_path
+ attr_reader :name
+ def initialize(name, controller_path)
+ @name = name
+ @controller_path = controller_path
+ end
+ def kind_of?(x)
+ x === Class || x == FakeController
+ end
+end
+
+module Controllers
+ module Admin
+ UserController = FakeController.new 'Admin::UserController', 'admin/user'
+ AccessController = FakeController.new 'Admin::AccessController', 'admin/access'
+ end
+ module Editing
+ PageController = FakeController.new 'Editing::PageController', 'editing/page'
+ ImageController = FakeController.new 'Editing::ImageController', 'editing/image'
+ end
+ module User
+ NewsController = FakeController.new 'User::NewsController', 'user/news'
+ PaymentController = FakeController.new 'User::PaymentController', 'user/payment'
+ end
+ ContentController = FakeController.new 'ContentController', 'content'
+ ResourceController = FakeController.new 'ResourceController', 'resource'
+end
+
+# Extend the modules with the required methods...
+[Controllers, Controllers::Admin, Controllers::Editing, Controllers::User].each do |mod|
+ mod.instance_eval('alias :const_available? :const_defined?')
+ mod.constants.each {|k| Object.const_set(k, mod.const_get(k))} # export the modules & controller classes.
+end
+
+
+class RouteTests < Test::Unit::TestCase
+ def route(*args)
+ return @route if @route && (args.empty? || @args == args)
+ @args = args
+ @route = ActionController::Routing::Route.new(*args)
+ return @route
+ end
+
+ def setup
+ self.route '/:controller/:action/:id'
+ @defaults = {:controller => 'content', :action => 'show', :id => '314'}
+ end
+
+ # Don't put a leading / on the url.
+ # Make sure the controller is one from the above fake Controllers module.
+ def verify_recognize(url, expected_options, reason='')
+ url = url.split('/') if url.kind_of? String
+ reason = ": #{reason}" unless reason.empty?
+ controller_class, options = @route.recognize(url)
+ assert_not_equal nil, controller_class, "#{@route.inspect} didn't recognize #{url}#{reason}\n #{options}"
+ assert_equal expected_options, options, "#{@route.inspect} produced wrong options for #{url}#{reason}"
+ end
+
+ # The expected url should not have a leading /
+ # You can use @defaults if you want a set of plausible defaults
+ def verify_generate(expected_url, expected_extras, options, defaults, reason='')
+ reason = "#{reason}: " unless reason.empty?
+ components, extras = @route.generate(options, defaults)
+ assert_not_equal nil, components, "#{reason}#{@route.inspect} didn't generate for \n options = #{options.inspect}\n defaults = #{defaults.inspect}\n #{extras}"
+ assert_equal expected_extras, extras, "#{reason} #{@route.inspect}.generate: incorrect extra's"
+ assert_equal expected_url, components.join('/'), "#{reason} #{@route.inspect}.generate: incorrect url"
+ end
+
+ def test_recognize_default_unnested_with_action_and_id
+ verify_recognize('content/action/id', {:controller => 'content', :action => 'action', :id => 'id'})
+ verify_recognize('content/show/10', {:controller => 'content', :action => 'show', :id => '10'})
+ end
+ def test_generate_default_unnested_with_action_and_id_no_extras
+ verify_generate('content/action/id', {}, {:controller => 'content', :action => 'action', :id => 'id'}, @defaults)
+ verify_generate('content/show/10', {}, {:controller => 'content', :action => 'show', :id => '10'}, @defaults)
+ end
+ def test_generate_default_unnested_with_action_and_id
+ verify_generate('content/action/id', {:a => 'a'}, {:controller => 'content', :action => 'action', :id => 'id', :a => 'a'}, @defaults)
+ verify_generate('content/show/10', {:a => 'a'}, {:controller => 'content', :action => 'show', :id => '10', :a => 'a'}, @defaults)
+ end
+
+ # Note that we can't put tests here for proper relative controller handline
+ # because that is handled by RouteSet.
+ def test_recognize_default_nested_with_action_and_id
+ verify_recognize('admin/user/action/id', {:controller => 'admin/user', :action => 'action', :id => 'id'})
+ verify_recognize('admin/user/show/10', {:controller => 'admin/user', :action => 'show', :id => '10'})
+ end
+ def test_generate_default_nested_with_action_and_id_no_extras
+ verify_generate('admin/user/action/id', {}, {:controller => 'admin/user', :action => 'action', :id => 'id'}, @defaults)
+ verify_generate('admin/user/show/10', {}, {:controller => 'admin/user', :action => 'show', :id => '10'}, @defaults)
+ end
+ def test_generate_default_nested_with_action_and_id_relative_to_root
+ verify_generate('admin/user/action/id', {:a => 'a'}, {:controller => 'admin/user', :action => 'action', :id => 'id', :a => 'a'}, @defaults)
+ verify_generate('admin/user/show/10', {:a => 'a'}, {:controller => 'admin/user', :action => 'show', :id => '10', :a => 'a'}, @defaults)
+ end
+
+ def test_recognize_default_nested_with_action
+ verify_recognize('admin/user/action', {:controller => 'admin/user', :action => 'action'})
+ verify_recognize('admin/user/show', {:controller => 'admin/user', :action => 'show'})
+ end
+ def test_generate_default_nested_with_action_no_extras
+ verify_generate('admin/user/action', {}, {:controller => 'admin/user', :action => 'action'}, @defaults)
+ verify_generate('admin/user/show', {}, {:controller => 'admin/user', :action => 'show'}, @defaults)
+ end
+ def test_generate_default_nested_with_action
+ verify_generate('admin/user/action', {:a => 'a'}, {:controller => 'admin/user', :action => 'action', :a => 'a'}, @defaults)
+ verify_generate('admin/user/show', {:a => 'a'}, {:controller => 'admin/user', :action => 'show', :a => 'a'}, @defaults)
+ end
+
+ def test_recognize_default_nested_with_id_and_index
+ verify_recognize('admin/user/index/hello', {:controller => 'admin/user', :id => 'hello', :action => 'index'})
+ verify_recognize('admin/user/index/10', {:controller => 'admin/user', :id => "10", :action => 'index'})
+ end
+ def test_generate_default_nested_with_id_no_extras
+ verify_generate('admin/user/index/hello', {}, {:controller => 'admin/user', :id => 'hello'}, @defaults)
+ verify_generate('admin/user/index/10', {}, {:controller => 'admin/user', :id => 10}, @defaults)
+ end
+ def test_generate_default_nested_with_id
+ verify_generate('admin/user/index/hello', {:a => 'a'}, {:controller => 'admin/user', :id => 'hello', :a => 'a'}, @defaults)
+ verify_generate('admin/user/index/10', {:a => 'a'}, {:controller => 'admin/user', :id => 10, :a => 'a'}, @defaults)
+ end
+
+ def test_recognize_default_nested
+ verify_recognize('admin/user', {:controller => 'admin/user', :action => 'index'})
+ verify_recognize('admin/user', {:controller => 'admin/user', :action => 'index'})
+ end
+ def test_generate_default_nested_no_extras
+ verify_generate('admin/user/', {}, {:controller => 'admin/user'}, @defaults)
+ verify_generate('admin/user/', {}, {:controller => 'admin/user'}, @defaults)
+ end
+ def test_generate_default_nested
+ verify_generate('admin/user/', {:a => 'a'}, {:controller => 'admin/user', :a => 'a'}, @defaults)
+ verify_generate('admin/user/', {:a => 'a'}, {:controller => 'admin/user', :a => 'a'}, @defaults)
+ end
+
+ # Test generate with a default controller set.
+ def test_generate_default_controller
+ route '/:controller/:action/:id', :action => 'index', :id => nil, :controller => 'content'
+ @defaults[:controller] = 'resource'
+
+ verify_generate('', {}, {:controller => 'content'}, @defaults)
+ verify_generate('', {}, {:controller => 'content', :action => 'index'}, @defaults)
+ verify_generate('content/not-index', {}, {:controller => 'content', :action => 'not-index'}, @defaults)
+ verify_generate('content/index/10', {}, {:controller => 'content', :id => 10}, @defaults)
+ verify_generate('content/index/hi', {}, {:controller => 'content', :action => 'index', :id => 'hi'}, @defaults)
+ verify_generate('', {:a => 'a'}, {:controller => 'content', :a => 'a'}, @defaults)
+ verify_generate('', {:a => 'a'}, {:controller => 'content', :a => 'a'}, @defaults)
+
+ # Call some other generator tests
+ test_generate_default_unnested_with_action_and_id
+ test_generate_default_nested_with_action_and_id_no_extras
+ test_generate_default_nested_with_id
+ test_generate_default_nested_with_id_no_extras
+ end
+
+ # Test generate with a default controller set.
+ def test_generate_default_controller
+ route '/:controller/:action/:id', :action => 'index', :id => nil, :controller => 'content'
+ @defaults[:controller] = 'resource'
+ verify_recognize('', {:controller => 'content', :action => 'index'})
+ verify_recognize('content', {:controller => 'content', :action => 'index'})
+ verify_recognize('content/index', {:controller => 'content', :action => 'index'})
+ verify_recognize('content/index/10', {:controller => 'content', :action => 'index', :id => '10'})
+ end
+ # Make sure generation & recognition don't happen in some cases:
+ def test_no_generate_on_no_options
+ assert_equal nil, @route.generate({}, {})[0]
+ end
+ def test_requirements
+ route 'some_static/route', :controller => 'content'
+ assert_equal nil, @route.generate({}, {})[0]
+ assert_equal nil, @route.generate({:controller => "dog"}, {})[0]
+ assert_equal nil, @route.recognize([])[0]
+ assert_equal nil, @route.recognize(%w{some_static route with more than expected})[0]
+ end
+
+ def test_basecamp
+ route 'clients/', :controller => 'content'
+ verify_generate('clients', {}, {:controller => 'content'}, {}) # Would like to have clients/
+ verify_generate('clients', {}, {:controller => 'content'}, @defaults)
+ end
+
+ def test_basecamp2
+ route 'clients/:client_name/:project_name/', :controller => 'content', :action => 'start_page_redirect'
+ verify_recognize('clients/projects/2', {:controller => 'content', :client_name => 'projects', :project_name => '2', :action => 'start_page_redirect'})
+ end
+
+ def test_xal_style_dates
+ route 'articles/:category/:year/:month/:day', :controller => 'content', :action => 'list_articles', :category => 'all', :year => nil, :month => nil, :day =>nil
+ verify_recognize('articles', {:controller => 'content', :action => 'list_articles', :category => 'all'})
+ verify_recognize('articles/porn', {:controller => 'content', :action => 'list_articles', :category => 'porn'})
+ verify_recognize('articles/news/2005/08', {:controller => 'content', :action => 'list_articles', :category => 'news', :year => '2005', :month => '08'})
+ verify_recognize('articles/news/2005/08/04', {:controller => 'content', :action => 'list_articles', :category => 'news', :year => '2005', :month => '08', :day => '04'})
+ assert_equal nil, @route.recognize(%w{articles too many components are here})[0]
+ assert_equal nil, @route.recognize('')[0]
+
+ verify_generate('articles', {}, {:controller => 'content', :action => 'list_articles'}, @defaults)
+ verify_generate('articles', {}, {:controller => 'content', :action => 'list_articles', :category => 'all'}, @defaults)
+ verify_generate('articles/news', {}, {:controller => 'content', :action => 'list_articles', :category => 'news'}, @defaults)
+ verify_generate('articles/news/2005', {}, {:controller => 'content', :action => 'list_articles', :category => 'news', :year => '2005'}, @defaults)
+ verify_generate('articles/news/2005/05', {}, {:controller => 'content', :action => 'list_articles', :category => 'news', :year => '2005', :month => '05'}, @defaults)
+ verify_generate('articles/news/2005/05/16', {}, {:controller => 'content', :action => 'list_articles', :category => 'news', :year => '2005', :month => '05', :day => '16'}, @defaults)
+
+ assert_equal nil, @route.generate({:controller => 'content', :action => 'list_articles', :day => '2'}, @defaults)[0]
+ # The above case should fail because a nil value cannot be present in a path.
+ # In other words, since :day is given, :month and :year must be given too.
+ end
+
+
+ def test_no_controller
+ route 'some/:special/:route', :controller => 'a/missing/controller', :action => 'anything'
+ assert_raises(ActionController::RoutingError, "Should raise due to nonexistant controller") {@route.recognize(%w{some matching path})}
+ end
+ def test_bad_controller_path
+ assert_equal nil, @route.recognize(%w{no such controller fake_action id})[0]
+ end
+ def test_too_short_path
+ assert_equal nil, @route.recognize([])[0]
+ route 'some/static/route', :controller => 'content', :action => 'show'
+ assert_equal nil, route.recognize([])[0]
+ end
+ def test_too_long_path
+ assert_equal nil, @route.recognize(%w{content action id some extra components})[0]
+ end
+ def test_incorrect_static_component
+ route 'some/static/route', :controller => 'content', :action => 'show'
+ assert_equal nil, route.recognize(%w{an non_matching path})[0]
+ end
+ def test_no_controller_defined
+ route 'some/:path/:without/a/controller'
+ assert_equal nil, route.recognize(%w{some matching path a controller})[0]
+ end
+
+ def test_mismatching_requirements
+ route 'some/path', :controller => 'content', :action => 'fish'
+ assert_equal nil, route.generate({:controller => 'admin/user', :action => 'list'})[0]
+ assert_equal nil, route.generate({:controller => 'content', :action => 'list'})[0]
+ assert_equal nil, route.generate({:controller => 'admin/user', :action => 'fish'})[0]
+ end
+
+ def test_missing_value_for_generate
+ assert_equal nil, route.generate({})[0] # :controller is missing
+ end
+ def test_nils_inside_generated_path
+ route 'show/:year/:month/:day', :month => nil, :day => nil, :controller => 'content', :action => 'by_date'
+ assert_equal nil, route.generate({:year => 2005, :day => 10})[0]
+ end
+
+ def test_expand_controller_path_non_nested_no_leftover
+ controller, leftovers = @route.send :eat_path_to_controller, %w{content}
+ assert_equal Controllers::ContentController, controller
+ assert_equal [], leftovers
+ end
+ def test_expand_controller_path_non_nested_with_leftover
+ controller, leftovers = @route.send :eat_path_to_controller, %w{content action id}
+ assert_equal Controllers::ContentController, controller
+ assert_equal %w{action id}, leftovers
+ end
+ def test_expand_controller_path_nested_no_leftover
+ controller, leftovers = @route.send :eat_path_to_controller, %w{admin user}
+ assert_equal Controllers::Admin::UserController, controller
+ assert_equal [], leftovers
+ end
+ def test_expand_controller_path_nested_no_leftover
+ controller, leftovers = @route.send :eat_path_to_controller, %w{admin user action id}
+ assert_equal Controllers::Admin::UserController, controller
+ assert_equal %w{action id}, leftovers
+ end
+end
+
+class RouteSetTests < Test::Unit::TestCase
+ def setup
+ @set = ActionController::Routing::RouteSet.new
+ @rails_route = ActionController::Routing::Route.new '/:controller/:action/:id', :action => 'index', :id => nil
+ @request = ActionController::TestRequest.new({}, {}, nil)
+ end
+ def test_emptyness
+ assert_equal true, @set.empty?, "New RouteSets should respond to empty? with true."
+ @set.each { flunk "New RouteSets should be empty." }
+ end
+ def test_add_illegal_route
+ assert_raises(TypeError) {@set.add_route "I'm not actually a route."}
+ end
+ def test_add_normal_route
+ @set.add_route @rails_route
+ seen = false
+ @set.each do |route|
+ assert_equal @rails_route, route
+ flunk("Each should have yielded only a single route!") if seen
+ seen = true
+ end
+ end
+
+ def test_expand_controller_path_non_relative
+ defaults = {:controller => 'admin/user', :action => 'list'}
+ options = {:controller => '/content'}
+ @set.expand_controller_path!(options, defaults)
+ assert_equal({:controller => 'content'}, options)
+ end
+ def test_expand_controller_path_relative_to_nested
+ defaults = {:controller => 'admin/user', :action => 'list'}
+ options = {:controller => 'access'}
+ @set.expand_controller_path!(options, defaults)
+ assert_equal({:controller => 'admin/access'}, options)
+ end
+ def test_expand_controller_path_relative_to_root
+ defaults = {:controller => 'content', :action => 'list'}
+ options = {:controller => 'resource'}
+ @set.expand_controller_path!(options, defaults)
+ assert_equal({:controller => 'resource'}, options)
+ end
+ def test_expand_controller_path_into_module
+ defaults = {:controller => 'content', :action => 'list'}
+ options = {:controller => 'admin/user'}
+ @set.expand_controller_path!(options, defaults)
+ assert_equal({:controller => 'admin/user'}, options)
+ end
+ def test_expand_controller_path_switch_module_with_absolute
+ defaults = {:controller => 'user/news', :action => 'list'}
+ options = {:controller => '/admin/user'}
+ @set.expand_controller_path!(options, defaults)
+ assert_equal({:controller => 'admin/user'}, options)
+ end
+ def test_expand_controller_no_default
+ options = {:controller => 'content'}
+ @set.expand_controller_path!(options, {})
+ assert_equal({:controller => 'content'}, options)
+ end
+
+ # Don't put a leading / on the url.
+ # Make sure the controller is one from the above fake Controllers module.
+ def verify_recognize(expected_controller, expected_path_parameters=nil, path=nil)
+ @set.add_route(@rails_route) if @set.empty?
+ @request.path = path if path
+ controller = @set.recognize!(@request)
+ assert_equal expected_controller, controller
+ assert_equal expected_path_parameters, @request.path_parameters if expected_path_parameters
+ end
+
+ # The expected url should not have a leading /
+ # You can use @defaults if you want a set of plausible defaults
+ def verify_generate(expected_url, options, expected_extras={})
+ @set.add_route(@rails_route) if @set.empty?
+ components, extras = @set.generate(options, @request)
+ assert_equal expected_extras, extras, "#incorrect extra's"
+ assert_equal expected_url, components.join('/'), "incorrect url"
+ end
+ def typical_request
+ @request.path_parameters = {:controller => 'content', :action => 'show', :id => '10'}
+ end
+ def typical_nested_request
+ @request.path_parameters = {:controller => 'admin/user', :action => 'grant', :id => '02seckar'}
+ end
+
+ def test_generate_typical_controller_action_path
+ typical_request
+ verify_generate('content/list', {:controller => 'content', :action => 'list'})
+ end
+ def test_generate_typical_controller_index_path_explicit_index
+ typical_request
+ verify_generate('content/', {:controller => 'content', :action => 'index'})
+ end
+ def test_generate_typical_controller_index_path_explicit_index
+ typical_request
+ verify_generate('content/', {:controller => 'content', :action => 'index'})
+ end
+ def test_generate_typical_controller_index_path_implicit_index
+ typical_request
+ @request.path_parameters[:controller] = 'resource'
+ verify_generate('content/', {:controller => 'content'})
+ end
+
+ def test_generate_no_perfect_route
+ typical_request
+ verify_generate('admin/user/show/43seckar', {:controller => 'admin/user', :action => 'show', :id => '43seckar', :likes_fishing => 'fuzzy(0.3)'}, {:likes_fishing => 'fuzzy(0.3)'})
+ end
+
+ def test_generate_no_match
+ @set.add_route(@rails_route)
+ @request.path_parameters = {}
+ assert_raises(ActionController::RoutingError) {@set.generate({}, @request)}
+ end
+
+
+ def test_encoded_strings
+ verify_recognize(Controllers::Admin::UserController, {:controller => 'admin/user', :action => 'info', :id => "Nicholas Seckar"}, path='/admin/user/info/Nicholas%20Seckar')
+ end
+end
diff --git a/actionpack/test/controller/url_test.rb b/actionpack/test/controller/url_obsolete.rb
index f7f08a2fe5..4b6544dbf7 100644
--- a/actionpack/test/controller/url_test.rb
+++ b/actionpack/test/controller/url_obsolete.rb
@@ -1,7 +1,7 @@
require File.dirname(__FILE__) + '/../abstract_unit'
require 'action_controller/url_rewriter'
-MockRequest = Struct.new("MockRequest", :protocol, :host, :port, :path, :parameters)
+MockRequest = Struct.new("MockRequest", :protocol, :host, :port, :path, :parameters, :path_parameters)
class MockRequest
def host_with_port
if (protocol == "http://" && port == 80) || (protocol == "https://" && port == 443)
@@ -16,14 +16,24 @@ class UrlMockFactory
def self.create(path, parameters)
ActionController::UrlRewriter.new(
MockRequest.new("http://", "example.com", 80, path, parameters),
- parameters["controller"], parameters["action"]
+ parameters
)
end
end
+# old-style support for .new
+module ActionController
+ class UrlRewriter
+ def self.old_new(request, controller, action)
+ request.parameters[:controller] = controller
+ request.parameters[:action] = action
+ return new(request, request.parameters)
+ end
+ end
+end
class UrlTest < Test::Unit::TestCase
def setup
- @library_url = ActionController::UrlRewriter.new(MockRequest.new(
+ @library_url = ActionController::UrlRewriter.old_new(MockRequest.new(
"http://",
"www.singlefile.com",
80,
@@ -31,7 +41,7 @@ class UrlTest < Test::Unit::TestCase
{ "type" => "ISBN", "code" => "0743536703" }
), "books", "show")
- @library_url_using_module = ActionController::UrlRewriter.new(MockRequest.new(
+ @library_url_using_module = ActionController::UrlRewriter.old_new(MockRequest.new(
"http://",
"www.singlefile.com",
80,
@@ -39,7 +49,7 @@ class UrlTest < Test::Unit::TestCase
{ "type" => "ISBN", "code" => "0743536703", "module" => "library" }
), "books", "show")
- @library_url_on_index = ActionController::UrlRewriter.new(MockRequest.new(
+ @library_url_on_index = ActionController::UrlRewriter.old_new(MockRequest.new(
"http://",
"www.singlefile.com",
80,
@@ -48,27 +58,27 @@ class UrlTest < Test::Unit::TestCase
), "books", "index")
@clean_urls = [
- ActionController::UrlRewriter.new(MockRequest.new(
+ ActionController::UrlRewriter.old_new(MockRequest.new(
"http://", "www.singlefile.com", 80, "/identity/", {}
), "identity", "index"),
- ActionController::UrlRewriter.new(MockRequest.new(
+ ActionController::UrlRewriter.old_new(MockRequest.new(
"http://", "www.singlefile.com", 80, "/identity", {}
), "identity", "index")
]
- @clean_url_with_id = ActionController::UrlRewriter.new(MockRequest.new(
+ @clean_url_with_id = ActionController::UrlRewriter.old_new(MockRequest.new(
"http://", "www.singlefile.com", 80, "/identity/show/5", { "id" => "5" }
), "identity", "show")
- @clean_url_with_same_action_and_controller_name = ActionController::UrlRewriter.new(MockRequest.new(
+ @clean_url_with_same_action_and_controller_name = ActionController::UrlRewriter.old_new(MockRequest.new(
"http://", "www.singlefile.com", 80, "/login/login", { }
), "login", "login")
- @clean_url_with_same_action_and_controller_and_module_name = ActionController::UrlRewriter.new(MockRequest.new(
+ @clean_url_with_same_action_and_controller_and_module_name = ActionController::UrlRewriter.old_new(MockRequest.new(
"http://", "www.singlefile.com", 80, "/login/login/login", { "module" => "login" }
), "login", "login")
- @clean_url_with_id_as_char = ActionController::UrlRewriter.new(MockRequest.new(
+ @clean_url_with_id_as_char = ActionController::UrlRewriter.old_new(MockRequest.new(
"http://", "www.singlefile.com", 80, "/teachers/show/t", { "id" => "t" }
), "teachers", "show")
end
@@ -386,7 +396,7 @@ class UrlTest < Test::Unit::TestCase
end
def test_from_another_port
- @library_url = ActionController::UrlRewriter.new(MockRequest.new(
+ @library_url = ActionController::UrlRewriter.old_new(MockRequest.new(
"http://",
"www.singlefile.com",
8080,
@@ -403,7 +413,7 @@ class UrlTest < Test::Unit::TestCase
end
def test_basecamp
- basecamp_url = ActionController::UrlRewriter.new(MockRequest.new(
+ basecamp_url = ActionController::UrlRewriter.old_new(MockRequest.new(
"http://",
"projects.basecamp",
80,
@@ -418,7 +428,7 @@ class UrlTest < Test::Unit::TestCase
end
def test_on_explicit_index_page # My index page is very modest, thank you...
- url = ActionController::UrlRewriter.new(
+ url = ActionController::UrlRewriter.old_new(
MockRequest.new(
"http://", "example.com", 80, "/controller/index",
{"controller"=>"controller", "action"=>"index"}
diff --git a/actionpack/test/fixtures/fun/games/hello_world.rhtml b/actionpack/test/fixtures/fun/games/hello_world.rhtml
new file mode 100644
index 0000000000..1ebfbe2539
--- /dev/null
+++ b/actionpack/test/fixtures/fun/games/hello_world.rhtml
@@ -0,0 +1 @@
+Living in a nested world \ No newline at end of file
diff --git a/actionpack/test/fixtures/helpers/fun/games_helper.rb b/actionpack/test/fixtures/helpers/fun/games_helper.rb
new file mode 100644
index 0000000000..bf60d9db0c
--- /dev/null
+++ b/actionpack/test/fixtures/helpers/fun/games_helper.rb
@@ -0,0 +1,3 @@
+module Fun::GamesHelper
+ def stratego() "Iz guuut!" end
+end \ No newline at end of file
diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG
index 7a005ce970..cf9fc0a728 100644
--- a/activesupport/CHANGELOG
+++ b/activesupport/CHANGELOG
@@ -2,6 +2,10 @@
* Added IndifferentAccess as a way to wrap a hash by a symbol-based store that also can be accessed by string keys
+* Added Inflector.constantize to turn "Admin::User" into a reference for the constant Admin::User
+
+* Added that Inflector.camelize and Inflector.underscore can deal with modules like turning "Admin::User" into "admin/user" and back
+
* Added Inflector.humanize to turn attribute names like employee_salary into "Employee salary". Used by automated error reporting in AR.
* Added availability of class inheritable attributes to the masses #477 [bitsweat]
diff --git a/activesupport/lib/core_ext/hash/indifferent_access.rb b/activesupport/lib/core_ext/hash/indifferent_access.rb
index 3fe0999866..2353cfaf3b 100644
--- a/activesupport/lib/core_ext/hash/indifferent_access.rb
+++ b/activesupport/lib/core_ext/hash/indifferent_access.rb
@@ -8,17 +8,17 @@ class HashWithIndifferentAccess < Hash
end
end
- alias_method :regular_read, :[]
+ alias_method :regular_reader, :[] unless method_defined?(:regular_reader)
def [](key)
case key
- when Symbol: regular_read(key) || regular_read(key.to_s)
- when String: regular_read(key) || regular_read(key.to_sym)
- else regular_read(key)
+ when Symbol: regular_reader(key) || regular_reader(key.to_s)
+ when String: regular_reader(key) || regular_reader(key.to_sym)
+ else regular_reader(key)
end
end
- alias_method :regular_writer, :[]=
+ alias_method :regular_writer, :[]= unless method_defined?(:regular_writer)
def []=(key, value)
regular_writer(key.is_a?(String) ? key.to_sym : key, value)
diff --git a/activesupport/lib/core_ext/string/inflections.rb b/activesupport/lib/core_ext/string/inflections.rb
index 5d1070b00a..aa4ff3a74d 100644
--- a/activesupport/lib/core_ext/string/inflections.rb
+++ b/activesupport/lib/core_ext/string/inflections.rb
@@ -39,6 +39,10 @@ module ActiveSupport #:nodoc:
def foreign_key(separate_class_name_and_id_with_underscore = true)
Inflector.foreign_key(self, separate_class_name_and_id_with_underscore)
end
+
+ def constantize
+ Inflector.constantize(self)
+ end
end
end
end
diff --git a/activesupport/lib/dependencies.rb b/activesupport/lib/dependencies.rb
index 7f53998e7a..0a9b8e1d3d 100644
--- a/activesupport/lib/dependencies.rb
+++ b/activesupport/lib/dependencies.rb
@@ -2,7 +2,7 @@ require File.dirname(__FILE__) + '/module_attribute_accessors'
module Dependencies
extend self
-
+
@@loaded = [ ]
mattr_accessor :loaded
@@ -41,6 +41,68 @@ module Dependencies
def remove_subclasses_for(*classes)
classes.each { |klass| klass.remove_subclasses }
end
+
+ # LoadingModules implement namespace-safe dynamic loading.
+ # They support automatic loading via const_missing, allowing contained items to be automatically
+ # loaded when required. No extra syntax is required, as expressions such as Controller::Admin::UserController
+ # load the relavent files automatically.
+ #
+ # Ruby-style modules are supported, as a folder named 'submodule' will load 'submodule.rb' when available.
+ class LoadingModule < Module
+ attr_reader :path
+
+ def initialize(filesystem_root, path=[])
+ @path = path
+ @filesystem_root = filesystem_root
+ end
+
+ # The path to this module in the filesystem.
+ # Any subpath provided is taken to be composed of filesystem names.
+ def filesystem_path(subpath=[])
+ File.join(@filesystem_root, self.path, subpath)
+ end
+
+ # Load missing constants if possible.
+ def const_missing(name)
+ return const_get(name) if const_defined?(name) == false && const_load!(name)
+ super(name)
+ end
+
+ # Load the controller class or a parent module.
+ def const_load!(name)
+ name = name.to_s if name.kind_of? Symbol
+
+ if File.directory? filesystem_path(name.underscore)
+ # Is it a submodule? If so, create a new LoadingModule *before* loading it.
+ # This ensures that subitems will be loadable
+ new_module = LoadingModule.new(@filesystem_root, self.path + [name.underscore])
+ const_set(name, new_module)
+ Object.const_set(name, new_module) if @path.empty?
+ end
+
+ source_file = filesystem_path("#{(name == 'ApplicationController' ? 'Application' : name).underscore}.rb")
+ self.load_file(source_file) if File.file?(source_file)
+ self.const_defined?(name.camelize)
+ end
+
+ # Is this name present or loadable?
+ # This method is used by Routes to find valid controllers.
+ def const_available?(name)
+ name = name.to_s unless name.kind_of? String
+ File.directory?(filesystem_path(name.underscore)) || File.file?(filesystem_path("#{name.underscore}.rb"))
+ end
+
+ def clear
+ constants.each do |name|
+ Object.send(:remove_const, name) if Object.const_defined?(name) && @path.empty?
+ self.send(:remove_const, name)
+ end
+ end
+
+ def load_file(file_path)
+ Controllers.module_eval(IO.read(file_path), file_path, 1) # Hard coded Controller line here!!!
+ end
+ end
end
Object.send(:define_method, :require_or_load) { |file_name| Dependencies.require_or_load(file_name) } unless Object.respond_to?(:require_or_load)
@@ -52,6 +114,9 @@ class Object #:nodoc:
# Use const_missing to autoload associations so we don't have to
# require_association when using single-table inheritance.
def const_missing(class_id)
+ if Object.const_defined?(:Controllers) and Object::Controllers.const_available?(class_id)
+ return Object::Controllers.const_get(class_id)
+ end
begin
require_or_load(class_id.to_s.demodulize.underscore)
if Object.const_defined?(class_id) then return Object.const_get(class_id) else raise LoadError end
diff --git a/activesupport/lib/inflector.rb b/activesupport/lib/inflector.rb
index 065fad3762..a9b2f87be4 100644
--- a/activesupport/lib/inflector.rb
+++ b/activesupport/lib/inflector.rb
@@ -20,11 +20,11 @@ module Inflector
end
def camelize(lower_case_and_underscored_word)
- lower_case_and_underscored_word.to_s.gsub(/(^|_)(.)/){$2.upcase}
+ lower_case_and_underscored_word.to_s.gsub(/\/(.?)/) { "::" + $1.upcase }.gsub(/(^|_)(.)/) { $2.upcase }
end
def underscore(camel_cased_word)
- camel_cased_word.to_s.gsub(/([A-Z]+)([A-Z])/,'\1_\2').gsub(/([a-z])([A-Z])/,'\1_\2').downcase
+ camel_cased_word.to_s.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z])/,'\1_\2').gsub(/([a-z])([A-Z])/,'\1_\2').downcase
end
def humanize(lower_case_and_underscored_word)
@@ -47,7 +47,13 @@ module Inflector
Inflector.underscore(Inflector.demodulize(class_name)) +
(separate_class_name_and_id_with_underscore ? "_id" : "id")
end
-
+
+ def constantize(camel_cased_word)
+ camel_cased_word.split("::").inject(Object) do |final_type, part|
+ final_type = final_type.const_get(part)
+ end
+ end
+
private
def plural_rules #:doc:
[
diff --git a/activesupport/test/inflector_test.rb b/activesupport/test/inflector_test.rb
index 4523430ebe..cdab0f9ed0 100644
--- a/activesupport/test/inflector_test.rb
+++ b/activesupport/test/inflector_test.rb
@@ -1,6 +1,13 @@
require 'test/unit'
require File.dirname(__FILE__) + '/../lib/inflector'
+module A
+ module B
+ class C
+ end
+ end
+end
+
class InflectorTest < Test::Unit::TestCase
SingularToPlural = {
"search" => "searches",
@@ -50,6 +57,12 @@ class InflectorTest < Test::Unit::TestCase
"SpecialGuest" => "special_guest",
"ApplicationController" => "application_controller"
}
+
+ CamelWithModuleToUnderscoreWithSlash = {
+ "Admin::Product" => "admin/product",
+ "Users::Commission::Department" => "users/commission/department",
+ "UsersSection::CommissionDepartment" => "users_section/commission_department",
+ }
ClassNameToForeignKeyWithUnderscore = {
"Person" => "person_id",
@@ -100,6 +113,18 @@ class InflectorTest < Test::Unit::TestCase
assert_equal "html_tidy_generator", Inflector.underscore("HTMLTidyGenerator")
end
+ def test_camelize_with_module
+ CamelWithModuleToUnderscoreWithSlash.each do |camel, underscore|
+ assert_equal(camel, Inflector.camelize(underscore))
+ end
+ end
+
+ def test_underscore_with_slashes
+ CamelWithModuleToUnderscoreWithSlash.each do |camel, underscore|
+ assert_equal(underscore, Inflector.underscore(camel))
+ end
+ end
+
def test_demodulize
assert_equal "Account", Inflector.demodulize("MyApplication::Billing::Account")
end
@@ -131,4 +156,10 @@ class InflectorTest < Test::Unit::TestCase
assert_equal(human, Inflector.humanize(underscore))
end
end
+
+ def test_constantize
+ assert_equal A::B::C, Inflector.constantize("A::B::C")
+ assert_equal InflectorTest, Inflector.constantize("InflectorTest")
+ assert_raises(NameError) { Inflector.constantize("UnknownClass") }
+ end
end \ No newline at end of file
diff --git a/activesupport/test/loading_module/admin/access_controller.rb b/activesupport/test/loading_module/admin/access_controller.rb
new file mode 100644
index 0000000000..ddcbda8132
--- /dev/null
+++ b/activesupport/test/loading_module/admin/access_controller.rb
@@ -0,0 +1,2 @@
+class Admin::AccessController
+end
diff --git a/activesupport/test/loading_module/admin/user_controller.rb b/activesupport/test/loading_module/admin/user_controller.rb
new file mode 100644
index 0000000000..f265f1597a
--- /dev/null
+++ b/activesupport/test/loading_module/admin/user_controller.rb
@@ -0,0 +1,2 @@
+class Admin::UserController
+end
diff --git a/activesupport/test/loading_module/content_controller.rb b/activesupport/test/loading_module/content_controller.rb
new file mode 100644
index 0000000000..f0870161e5
--- /dev/null
+++ b/activesupport/test/loading_module/content_controller.rb
@@ -0,0 +1,2 @@
+class ContentController
+end
diff --git a/activesupport/test/loading_module/resource_controller.rb b/activesupport/test/loading_module/resource_controller.rb
new file mode 100644
index 0000000000..d948f366bf
--- /dev/null
+++ b/activesupport/test/loading_module/resource_controller.rb
@@ -0,0 +1,2 @@
+class ResourceController
+end
diff --git a/activesupport/test/loading_module_tests.rb b/activesupport/test/loading_module_tests.rb
new file mode 100644
index 0000000000..c1d8c7de62
--- /dev/null
+++ b/activesupport/test/loading_module_tests.rb
@@ -0,0 +1,63 @@
+require 'test/unit'
+require '../lib/core_ext.rb'
+require '../lib/dependencies.rb'
+
+STAGING_DIRECTORY = 'loading_module'
+
+class LoadingModuleTests < Test::Unit::TestCase
+ def setup
+ @loading_module = Dependencies::LoadingModule.new(STAGING_DIRECTORY)
+ Object.const_set(:Controllers, @loading_module)
+ end
+ def teardown
+ @loading_module.clear
+ Object.send :remove_const, :Controllers
+ end
+
+ def test_setup
+ assert_kind_of Dependencies::LoadingModule, @loading_module
+ end
+
+ def test_const_available
+ assert @loading_module.const_available?(:Admin)
+ assert @loading_module.const_available?(:ResourceController)
+ assert @loading_module.const_available?(:ContentController)
+ assert @loading_module.const_available?("ContentController")
+
+ assert_equal false, @loading_module.const_available?(:AdminController)
+ assert_equal false, @loading_module.const_available?(:RandomName)
+ end
+
+ def test_const_load_module
+ assert @loading_module.const_load!(:Admin)
+ assert_kind_of Module, @loading_module::Admin
+ assert_kind_of Dependencies::LoadingModule, @loading_module::Admin
+ end
+
+ def test_const_load_controller
+ assert @loading_module.const_load!(:ContentController)
+ assert_kind_of Class, @loading_module::ContentController
+ end
+
+ def test_const_load_nested_controller
+ assert @loading_module.const_load!(:Admin)
+ assert @loading_module::Admin.const_available?(:UserController)
+ assert @loading_module::Admin.const_load!(:UserController)
+ assert_kind_of Class, @loading_module::Admin::UserController
+ end
+
+ def test_pretty_access
+ assert_kind_of Module, @loading_module::Admin
+ assert_kind_of Dependencies::LoadingModule, @loading_module::Admin
+
+ assert_kind_of Class, @loading_module::Admin::UserController
+ assert_kind_of Class, @loading_module::Admin::AccessController
+ assert_kind_of Class, @loading_module::ResourceController
+ assert_kind_of Class, @loading_module::ContentController
+ end
+
+ def test_missing_name
+ assert_raises(NameError) {@loading_module::PersonController}
+ assert_raises(NameError) {@loading_module::Admin::FishController}
+ end
+end \ No newline at end of file
diff --git a/railties/bin/destroy b/railties/bin/destroy
index 6c1848ce1e..ba6dc7703f 100644
--- a/railties/bin/destroy
+++ b/railties/bin/destroy
@@ -1,8 +1,5 @@
#!/usr/local/bin/ruby
require File.dirname(__FILE__) + '/../config/environment'
require 'rails_generator'
-require 'rails_generator/simple_logger'
require 'rails_generator/scripts/destroy'
-
-Rails::Generator::Base.logger = Rails::Generator::SimpleLogger.new(STDOUT)
Rails::Generator::Scripts::Destroy.new.run(ARGV)
diff --git a/railties/bin/generate b/railties/bin/generate
index 8bce002510..dde69e61a1 100755
--- a/railties/bin/generate
+++ b/railties/bin/generate
@@ -1,8 +1,5 @@
#!/usr/local/bin/ruby
require File.dirname(__FILE__) + '/../config/environment'
require 'rails_generator'
-require 'rails_generator/simple_logger'
require 'rails_generator/scripts/generate'
-
-Rails::Generator::Base.logger = Rails::Generator::SimpleLogger.new(STDOUT)
Rails::Generator::Scripts::Generate.new.run(ARGV)
diff --git a/railties/bin/rails b/railties/bin/rails
index da9b2af041..3d23b99609 100755
--- a/railties/bin/rails
+++ b/railties/bin/rails
@@ -1,7 +1,4 @@
require File.dirname(__FILE__) + '/../lib/rails_generator'
-require 'rails_generator/simple_logger'
require 'rails_generator/scripts/generate'
-
-Rails::Generator::Base.logger = Rails::Generator::SimpleLogger.new(STDOUT)
Rails::Generator::Base.use_application_sources!
Rails::Generator::Scripts::Generate.new.run(ARGV, :generator => 'app')
diff --git a/railties/bin/update b/railties/bin/update
index 64cc49cf02..430d325b07 100644
--- a/railties/bin/update
+++ b/railties/bin/update
@@ -1,8 +1,5 @@
#!/usr/local/bin/ruby
require File.dirname(__FILE__) + '/../config/environment'
require 'rails_generator'
-require 'rails_generator/simple_logger'
require 'rails_generator/scripts/update'
-
-Rails::Generator::Base.logger = Rails::Generator::SimpleLogger.new(STDOUT)
Rails::Generator::Scripts::Update.new.run(ARGV)
diff --git a/railties/configs/apache.conf b/railties/configs/apache.conf
index 5548292f8d..1aa874c866 100755
--- a/railties/configs/apache.conf
+++ b/railties/configs/apache.conf
@@ -1,61 +1,6 @@
-# General Apache options
-AddHandler fastcgi-script .fcgi
-AddHandler cgi-script .cgi
-Options +FollowSymLinks +ExecCGI
-
-# Make sure that mod_ruby.c has been added and loaded as a module with Apache
RewriteEngine On
+RewriteCond %{REQUEST_FILENAME} !-f
+RewriteRule ^(.*)$ /dispatch.fcgi?$1 [QSA,L]
-# Change extension from .cgi to .fcgi to switch to FCGI and to .rb to switch to mod_ruby
-RewriteBase /dispatch.cgi
-
-# Enable this rewrite rule to point to the controller/action that should serve root.
-# RewriteRule ^$ /controller/action [R]
-
-# <caching>
-# no query string?
-RewriteCond %{QUERY_STRING} ^$
-
-# no POST method?
-RewriteCond %{REQUEST_METHOD} !^POST$ [NC]
-
-# Request filename is a directory?
-RewriteCond %{REQUEST_FILENAME} -d
-
-# Request filename + '/index' is a file?
-RewriteCond %{REQUEST_FILENAME}/index -f
-
-# Rewrite to request filename + '/index' and finish
-RewriteRule ^(.*)/?$ $1/index [QSA,L]
-
-# no query string?
-RewriteCond %{QUERY_STRING} ^$
-
-# no POST method?
-RewriteCond %{REQUEST_METHOD} !^POST$ [NC]
-
-# Request filename is a file?
-RewriteCond %{REQUEST_FILENAME} -f
-
-# Finish rewriting
-RewriteRule .* - [L]
-
-# Set default type of cached files to text/html
-DefaultType text/html
-# </caching>
-
-# Add missing slash
-RewriteRule ^([-_a-zA-Z0-9]+)$ /$1/ [R]
-
-# Default rewriting rules.
-RewriteRule ^([-_a-zA-Z0-9]+)/([-_a-zA-Z0-9]+)/([0-9]+)$ ?controller=$1&action=$2&id=$3 [QSA,L]
-RewriteRule ^([-_a-zA-Z0-9]+)/([-_a-zA-Z0-9]+)$ ?controller=$1&action=$2 [QSA,L]
-RewriteRule ^([-_a-zA-Z0-9]+)/$ ?controller=$1&action=index [QSA,L]
-
-RewriteRule ^([-_a-zA-Z0-9]+)/([-_a-zA-Z0-9]+)/([-_a-zA-Z0-9]+)/([0-9]+)$ ?module=$1&controller=$2&action=$3&id=$4 [QSA,L]
-RewriteRule ^([-_a-zA-Z0-9]+)/([-_a-zA-Z0-9]+)/([-_a-zA-Z0-9]+)$ ?module=$1&controller=$2&action=$3 [QSA,L]
-RewriteRule ^([-_a-zA-Z0-9]+)/([-_a-zA-Z0-9]+)/$ ?module=$1&controller=$2&action=index [QSA,L]
-
-# You can also point these error messages to a controller/action
ErrorDocument 500 /500.html
ErrorDocument 404 /404.html \ No newline at end of file
diff --git a/railties/environments/shared.rb b/railties/environments/shared.rb
index 8e36ae6670..f8a8e8cb6f 100644
--- a/railties/environments/shared.rb
+++ b/railties/environments/shared.rb
@@ -39,6 +39,8 @@ require_dependency "environments/#{RAILS_ENV}"
ActiveRecord::Base.configurations = YAML::load(File.open("#{RAILS_ROOT}/config/database.yml"))
ActiveRecord::Base.establish_connection
+Controllers = Dependencies::LoadingModule.new(File.expand_path(File.join(RAILS_ROOT, 'app', 'controllers')))
+
# Configure defaults if the included environment did not.
begin
diff --git a/railties/environments/shared_for_gem.rb b/railties/environments/shared_for_gem.rb
index a277641a99..948b5e47eb 100644
--- a/railties/environments/shared_for_gem.rb
+++ b/railties/environments/shared_for_gem.rb
@@ -36,6 +36,8 @@ require_dependency "environments/#{RAILS_ENV}"
ActiveRecord::Base.configurations = YAML::load(File.open("#{RAILS_ROOT}/config/database.yml"))
ActiveRecord::Base.establish_connection
+Controllers = Dependencies::LoadingModule.new(File.expand_path(File.join(RAILS_ROOT, 'app', 'controllers')))
+
# Configure defaults if the included environment did not.
begin
diff --git a/railties/generators/model/USAGE b/railties/generators/model/USAGE
deleted file mode 100644
index e69de29bb2..0000000000
--- a/railties/generators/model/USAGE
+++ /dev/null
diff --git a/railties/lib/dispatcher.rb b/railties/lib/dispatcher.rb
index 566b031295..74de93713c 100644
--- a/railties/lib/dispatcher.rb
+++ b/railties/lib/dispatcher.rb
@@ -24,56 +24,34 @@
require 'breakpoint'
class Dispatcher
- class <<self
+ class << self
def dispatch(cgi = CGI.new, session_options = ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS)
begin
- Breakpoint.activate_drb("druby://localhost:#{BREAKPOINT_SERVER_PORT}", nil, !defined?(FastCGI)) if defined?(BREAKPOINT_SERVER_PORT)
-
- request = ActionController::CgiRequest.new(cgi, session_options)
- response = ActionController::CgiResponse.new(cgi)
-
- controller_name, module_name = controller_name(request.parameters), module_name(request.parameters)
-
- require_or_load("application")
- require_or_load(controller_path(controller_name, module_name))
-
- controller_class(controller_name).process(request, response).out
+ prepare_application
+ request, response = ActionController::CgiRequest.new(cgi, session_options), ActionController::CgiResponse.new(cgi)
+ ActionController::Routing::Routes.recognize!(request).process(request, response).out
rescue Object => exception
ActionController::Base.process_with_exception(request, response, exception).out
ensure
- reset_application if Dependencies.load?
- Breakpoint.deactivate_drb if defined?(BREAKPOINT_SERVER_PORT)
+ reset_application
end
end
private
- def reset_application
- Dependencies.clear
- Dependencies.remove_subclasses_for(ActiveRecord::Base, ActiveRecord::Observer, ActionController::Base)
+ def prepare_application
+ ActionController::Routing::Routes.reload if Dependencies.load?
+ Breakpoint.activate_drb("druby://localhost:#{BREAKPOINT_SERVER_PORT}", nil, !defined?(FastCGI)) if defined?(BREAKPOINT_SERVER_PORT)
+ Controllers.const_load!("application") unless Controllers.const_defined?(:ApplicationController)
end
- def controller_path(controller_name, module_name = nil)
- if module_name
- "#{module_name}/#{controller_name.underscore}_controller"
- else
- "#{controller_name.underscore}_controller"
+ def reset_application
+ if Dependencies.load?
+ Controllers.clear
+ Dependencies.clear
+ Dependencies.remove_subclasses_for(ActiveRecord::Base, ActiveRecord::Observer, ActionController::Base)
end
- end
-
- def controller_class(controller_name)
- Object.const_get(controller_class_name(controller_name))
- end
-
- def controller_class_name(controller_name)
- "#{controller_name.camelize}Controller"
- end
-
- def controller_name(parameters)
- parameters["controller"].downcase.gsub(/[^_a-zA-Z0-9]/, "").untaint
- end
- def module_name(parameters)
- parameters["module"].downcase.gsub(/[^_a-zA-Z0-9]/, "").untaint if parameters["module"]
+ Breakpoint.deactivate_drb if defined?(BREAKPOINT_SERVER_PORT)
end
end
end \ No newline at end of file
diff --git a/railties/lib/rails_generator.rb b/railties/lib/rails_generator.rb
index 0875a22dee..c46989819d 100644
--- a/railties/lib/rails_generator.rb
+++ b/railties/lib/rails_generator.rb
@@ -23,7 +23,7 @@
$:.unshift(File.dirname(__FILE__))
-require 'support/core_ext'
+require 'rails_generator/support/core_ext'
require 'rails_generator/base'
require 'rails_generator/lookup'
@@ -31,3 +31,7 @@ require 'rails_generator/commands'
Rails::Generator::Base.send(:include, Rails::Generator::Lookup)
Rails::Generator::Base.send(:include, Rails::Generator::Commands)
+
+# Set up a default logger for convenience.
+require 'rails_generator/simple_logger'
+Rails::Generator::Base.logger = Rails::Generator::SimpleLogger.new(STDOUT)
diff --git a/railties/lib/rails_generator/base.rb b/railties/lib/rails_generator/base.rb
index 065ce63966..92a54e2453 100644
--- a/railties/lib/rails_generator/base.rb
+++ b/railties/lib/rails_generator/base.rb
@@ -1,5 +1,5 @@
-require File.dirname(__FILE__) + '/../support/class_attribute_accessors'
-require File.dirname(__FILE__) + '/../support/inflector'
+require File.dirname(__FILE__) + '/support/class_attribute_accessors'
+require File.dirname(__FILE__) + '/support/inflector'
require File.dirname(__FILE__) + '/options'
require File.dirname(__FILE__) + '/manifest'
require File.dirname(__FILE__) + '/spec'
@@ -69,8 +69,8 @@ module Rails
@source_root = options[:source] || File.join(spec.path, 'templates')
if options[:destination]
@destination_root = options[:destination]
- elsif Object.const_defined?(:RAILS_ROOT)
- @destination_root = Object.const_get(:RAILS_ROOT)
+ elsif defined? ::RAILS_ROOT
+ @destination_root = ::RAILS_ROOT
end
# Silence the logger if requested.
@@ -173,11 +173,20 @@ module Rails
def assign_names!(name)
@name = name
base_name, @class_path, @class_nesting = extract_modules(@name)
- @class_name, @singular_name, @plural_name = inflect_names(base_name)
+ @class_name_without_nesting, @singular_name, @plural_name = inflect_names(base_name)
+ if @class_nesting.empty?
+ @class_name = @class_name_without_nesting
+ else
+ @class_name = "#{@class_nesting}::#{@class_name_without_nesting}"
+ end
end
+ # Extract modules from filesystem-style or ruby-style path:
+ # good/fun/stuff
+ # Good::Fun::Stuff
+ # produce the same results.
def extract_modules(name)
- modules = name.split('/')
+ modules = name.include?('/') ? name.split('/') : name.split('::')
name = modules.pop
path = modules.map { |m| m.underscore }
nesting = modules.map { |m| m.camelize }.join('::')
diff --git a/railties/lib/rails_generator/generators/applications/app/app_generator.rb b/railties/lib/rails_generator/generators/applications/app/app_generator.rb
index 0beb11b237..4a04757ddd 100644
--- a/railties/lib/rails_generator/generators/applications/app/app_generator.rb
+++ b/railties/lib/rails_generator/generators/applications/app/app_generator.rb
@@ -1,15 +1,16 @@
+require 'rbconfig'
+
class AppGenerator < Rails::Generator::Base
DEFAULT_SHEBANG = File.join(Config::CONFIG['bindir'],
Config::CONFIG['ruby_install_name'])
default_options :gem => true, :shebang => DEFAULT_SHEBANG
- mandatory_options :source => "#{File.dirname(__FILE__)}/../.."
+ mandatory_options :source => "#{File.dirname(__FILE__)}/../../../../.."
def initialize(runtime_args, runtime_options = {})
super
usage if args.empty?
@destination_root = args.shift
- puts "eek! #{destination_root.inspect}"
end
def manifest
@@ -32,6 +33,7 @@ class AppGenerator < Rails::Generator::Base
# database.yml and .htaccess
m.template "configs/database.yml", "config/database.yml"
+ m.template "configs/routes.rb", "config/routes.rb"
m.template "configs/apache.conf", "public/.htaccess"
# Environments
diff --git a/railties/lib/rails_generator/generators/components/controller/controller_generator.rb b/railties/lib/rails_generator/generators/components/controller/controller_generator.rb
index 1f7e69d124..d537031fea 100644
--- a/railties/lib/rails_generator/generators/components/controller/controller_generator.rb
+++ b/railties/lib/rails_generator/generators/components/controller/controller_generator.rb
@@ -4,8 +4,11 @@ class ControllerGenerator < Rails::Generator::NamedBase
# Check for class naming collisions.
m.class_collisions "#{class_name}Controller", "#{class_name}ControllerTest", "#{class_name}Helper"
- # Views directory even if there are no actions.
+ # Controller, helper, views, and test directories.
+ m.directory File.join('app/controllers', class_path)
+ m.directory File.join('app/helpers', class_path)
m.directory File.join('app/views', class_path, file_name)
+ m.directory File.join('test/functional', class_path)
# Controller class, functional test, and helper class.
m.template 'controller.rb',
diff --git a/railties/lib/rails_generator/generators/components/controller/templates/functional_test.rb b/railties/lib/rails_generator/generators/components/controller/templates/functional_test.rb
index c975cb3ce3..76e2b33ba5 100644
--- a/railties/lib/rails_generator/generators/components/controller/templates/functional_test.rb
+++ b/railties/lib/rails_generator/generators/components/controller/templates/functional_test.rb
@@ -7,7 +7,8 @@ class <%= class_name %>Controller; def rescue_action(e) raise e end; end
class <%= class_name %>ControllerTest < Test::Unit::TestCase
def setup
@controller = <%= class_name %>Controller.new
- @request, @response = ActionController::TestRequest.new, ActionController::TestResponse.new
+ @request = ActionController::TestRequest.new
+ @response = ActionController::TestResponse.new
end
# Replace this with your real tests.
diff --git a/railties/lib/rails_generator/generators/components/mailer/mailer_generator.rb b/railties/lib/rails_generator/generators/components/mailer/mailer_generator.rb
index 81d4599f7f..d8ddb43644 100644
--- a/railties/lib/rails_generator/generators/components/mailer/mailer_generator.rb
+++ b/railties/lib/rails_generator/generators/components/mailer/mailer_generator.rb
@@ -4,21 +4,28 @@ class MailerGenerator < Rails::Generator::NamedBase
# Check for class naming collisions.
m.class_collisions class_name, "#{class_name}Test"
- # Mailer class and unit test.
- m.template "mailer.rb", "app/models/#{file_name}.rb"
- m.template "unit_test.rb", "test/unit/#{file_name}_test.rb"
+ # Mailer, view, test, and fixture directories.
+ m.directory File.join('app/models', class_path)
+ m.directory File.join('app/views', class_path, file_name)
+ m.directory File.join('test/unit', class_path)
+ m.directory File.join('test/fixtures', class_path, table_name)
- # Views and fixtures directories.
- m.directory "app/views/#{file_name}"
- m.directory "test/fixtures/#{table_name}"
+ # Mailer class and unit test.
+ m.template "mailer.rb", File.join('app/models',
+ class_path,
+ "#{file_name}.rb")
+ m.template "unit_test.rb", File.join('test/unit',
+ class_path,
+ "#{file_name}_test.rb")
# View template and fixture for each action.
actions.each do |action|
m.template "view.rhtml",
- "app/views/#{file_name}/#{action}.rhtml",
+ File.join('app/views', class_path, file_name, "#{action}.rhtml"),
:assigns => { :action => action }
m.template "fixture.rhtml",
"test/fixtures/#{table_name}/#{action}",
+ File.join('test/fixtures', class_path, table_name, action),
:assigns => { :action => action }
end
end
diff --git a/railties/lib/rails_generator/generators/components/model/model_generator.rb b/railties/lib/rails_generator/generators/components/model/model_generator.rb
index 32577d08a3..c3407ca283 100644
--- a/railties/lib/rails_generator/generators/components/model/model_generator.rb
+++ b/railties/lib/rails_generator/generators/components/model/model_generator.rb
@@ -4,6 +4,11 @@ class ModelGenerator < Rails::Generator::NamedBase
# Check for class naming collisions.
m.class_collisions class_name, "#{class_name}Test"
+ # Model, test, and fixture directories.
+ m.directory File.join('app/models', class_path)
+ m.directory File.join('test/unit', class_path)
+ m.directory File.join('test/fixtures', class_path)
+
# Model class, unit test, and fixtures.
m.template 'model.rb', File.join('app/models', class_path, "#{file_name}.rb")
m.template 'unit_test.rb', File.join('test/unit', class_path, "#{file_name}_test.rb")
diff --git a/railties/lib/rails_generator/generators/components/model/templates/fixtures.yml b/railties/lib/rails_generator/generators/components/model/templates/fixtures.yml
index fc3185dc46..6285727968 100644
--- a/railties/lib/rails_generator/generators/components/model/templates/fixtures.yml
+++ b/railties/lib/rails_generator/generators/components/model/templates/fixtures.yml
@@ -1,10 +1,8 @@
# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
# Set the $base_id variable in the setup method of your tests.
# It's used to ensure that ids don't clash in some databases.
-<%% $base_id ||= 100000 %>
-
first_<%= singular_name %>:
- id: <%%= $base_id %>
+ id: 1
another_<%= singular_name %>:
- id: <%%= $base_id + 1 %>
+ id: 2
diff --git a/railties/lib/rails_generator/generators/components/model/templates/unit_test.rb b/railties/lib/rails_generator/generators/components/model/templates/unit_test.rb
index db0fbf5d33..e8714b589a 100644
--- a/railties/lib/rails_generator/generators/components/model/templates/unit_test.rb
+++ b/railties/lib/rails_generator/generators/components/model/templates/unit_test.rb
@@ -4,11 +4,11 @@ class <%= class_name %>Test < Test::Unit::TestCase
fixtures :<%= table_name %>
def setup
- $base_id = 1000001
+ @<%= singular_name %> = <%= class_name %>.find(1)
end
# Replace this with your real tests.
def test_truth
- assert true
+ assert_kind_of <%= class_name %>, @<%= singular_name %>
end
end
diff --git a/railties/lib/rails_generator/generators/components/scaffold/scaffold_generator.rb b/railties/lib/rails_generator/generators/components/scaffold/scaffold_generator.rb
index 4445995b46..abf9d79ffe 100644
--- a/railties/lib/rails_generator/generators/components/scaffold/scaffold_generator.rb
+++ b/railties/lib/rails_generator/generators/components/scaffold/scaffold_generator.rb
@@ -41,7 +41,12 @@ class ScaffoldGenerator < Rails::Generator::NamedBase
super
@controller_name = args.shift || @name.pluralize
base_name, @controller_class_path, @controller_class_nesting = extract_modules(@controller_name)
- @controller_class_name, @controller_singular_name, @controller_plural_name = inflect_names(base_name)
+ @controller_class_name_without_nesting, @controller_singular_name, @controller_plural_name = inflect_names(base_name)
+ if @controller_class_nesting.empty?
+ @controller_class_name = @controller_class_name_without_nesting
+ else
+ @controller_class_name = "#{@controller_class_nesting}::#{@controller_class_name_without_nesting}"
+ end
end
def manifest
@@ -52,8 +57,12 @@ class ScaffoldGenerator < Rails::Generator::NamedBase
# Check for class naming collisions.
m.class_collisions "#{controller_class_name}Controller", "#{controller_class_name}ControllerTest", "#{controller_class_name}Helper"
- # Views directory.
+ # Controller, helper, views, and test directories.
+ m.directory File.join('app/controllers', controller_class_path)
+ m.directory File.join('app/helpers', controller_class_path)
m.directory File.join('app/views', controller_class_path, controller_file_name)
+ m.directory File.join('test/functional', controller_class_path)
+
# Controller class, functional test, helper, and views.
m.template 'controller.rb',
@@ -79,7 +88,8 @@ class ScaffoldGenerator < Rails::Generator::NamedBase
scaffold_views.each do |action|
m.template "view_#{action}.rhtml",
File.join('app/views',
- controller_class_path, controller_file_name,
+ controller_class_path,
+ controller_file_name,
"#{action}.rhtml"),
:assigns => { :action => action }
end
@@ -103,7 +113,8 @@ class ScaffoldGenerator < Rails::Generator::NamedBase
unscaffolded_actions.each do |action|
m.template "controller:view.rhtml",
File.join('app/views',
- controller_class_path, controller_file_name,
+ controller_class_path,
+ controller_file_name,
"#{action}.rhtml"),
:assigns => { :action => action }
end
@@ -153,9 +164,13 @@ class ScaffoldGenerator < Rails::Generator::NamedBase
end
def model_instance
- unless Object.const_defined?(class_name)
- Object.const_set(class_name, Class.new(ActiveRecord::Base))
+ base = class_nesting.split('::').inject(Object) do |base, nested|
+ break base.const_get(nested) if base.const_defined?(nested)
+ base.const_set(nested, Module.new)
+ end
+ unless base.const_defined?(@class_name_without_nesting)
+ base.const_set(@class_name_without_nesting, Class.new(ActiveRecord::Base))
end
- Object.const_get(class_name).new
+ class_name.constantize.new
end
end
diff --git a/railties/lib/rails_generator/generators/components/scaffold/templates/functional_test.rb b/railties/lib/rails_generator/generators/components/scaffold/templates/functional_test.rb
index ea9c8e4e94..32185fb715 100644
--- a/railties/lib/rails_generator/generators/components/scaffold/templates/functional_test.rb
+++ b/railties/lib/rails_generator/generators/components/scaffold/templates/functional_test.rb
@@ -8,9 +8,9 @@ class <%= controller_class_name %>ControllerTest < Test::Unit::TestCase
fixtures :<%= table_name %>
def setup
- $base_id = 1000001
@controller = <%= controller_class_name %>Controller.new
- @request, @response = ActionController::TestRequest.new, ActionController::TestResponse.new
+ @request = ActionController::TestRequest.new
+ @response = ActionController::TestResponse.new
end
<% for action in unscaffolded_actions -%>
@@ -34,7 +34,7 @@ class <%= controller_class_name %>ControllerTest < Test::Unit::TestCase
end
def test_show<%= suffix %>
- process :show<%= suffix %>, 'id' => $base_id
+ process :show<%= suffix %>, 'id' => 1
assert_rendered_file 'show'
assert_template_has '<%= singular_name %>'
assert_valid_record '<%= singular_name %>'
@@ -56,25 +56,25 @@ class <%= controller_class_name %>ControllerTest < Test::Unit::TestCase
end
def test_edit<%= suffix %>
- process :edit<%= suffix %>, 'id' => $base_id
+ process :edit<%= suffix %>, 'id' => 1
assert_rendered_file 'edit<%= suffix %>'
assert_template_has '<%= singular_name %>'
assert_valid_record '<%= singular_name %>'
end
def test_update<%= suffix %>
- process :update<%= suffix %>, '<%= singular_name %>' => { 'id' => $base_id }
- assert_redirected_to :action => 'show<%= suffix %>', :id => $base_id
+ process :update<%= suffix %>, '<%= singular_name %>' => { 'id' => 1 }
+ assert_redirected_to :action => 'show<%= suffix %>', :id => 1
end
def test_destroy<%= suffix %>
- assert_not_nil <%= class_name %>.find($base_id)
+ assert_not_nil <%= class_name %>.find(1)
- process :destroy, 'id' => $base_id
+ process :destroy, 'id' => 1
assert_redirected_to :action => 'list<%= suffix %>'
assert_raise(ActiveRecord::RecordNotFound) {
- <%= singular_name %> = <%= class_name %>.find($base_id)
+ <%= singular_name %> = <%= class_name %>.find(1)
}
end
end
diff --git a/railties/lib/rails_generator/generators/components/scaffold/templates/view_list.rhtml b/railties/lib/rails_generator/generators/components/scaffold/templates/view_list.rhtml
index 068fd67472..e0d56d1122 100644
--- a/railties/lib/rails_generator/generators/components/scaffold/templates/view_list.rhtml
+++ b/railties/lib/rails_generator/generators/components/scaffold/templates/view_list.rhtml
@@ -10,7 +10,7 @@
<%% for <%= singular_name %> in @<%= plural_name %> %>
<tr>
<%% for column in <%= class_name %>.content_columns %>
- <td><%%=h <%= singular_name %>[column.name] %></td>
+ <td><%%=h <%= singular_name %>.send(column.name) %></td>
<%% end %>
<td><%%= link_to 'Show', :action => 'show<%= suffix %>', :id => <%= singular_name %>.id %></td>
<td><%%= link_to 'Edit', :action => 'edit<%= suffix %>', :id => <%= singular_name %>.id %></td>
diff --git a/railties/lib/rails_generator/lookup.rb b/railties/lib/rails_generator/lookup.rb
index ba47fd79be..00b78ce645 100644
--- a/railties/lib/rails_generator/lookup.rb
+++ b/railties/lib/rails_generator/lookup.rb
@@ -4,24 +4,20 @@ class Object
class << self
# Lookup missing generators using const_missing. This allows any
# generator to reference another without having to know its location:
- # RubyGems, ~/.rails/generators, and RAILS_ROOT/script/generators all
- # cooperate to get the job done. The greatest use of const_missing
- # autoloading is to easily subclass existing generators. Example:
- # class HorsebackGenerator < PostbackGenerator
- # We don't know whether the postback generator is built in, installed
- # as a gem, or in the user's home directory, and we shouldn't have to.
- unless respond_to?(:pre_generator_const_missing)
- alias_method :pre_generator_const_missing, :const_missing
-
- def const_missing(class_id)
- if md = /(.+)Generator$/.match(class_id.to_s)
- name = md.captures.first.demodulize.underscore
- Rails::Generator::Base.lookup(name).klass
- else
- pre_generator_const_missing(class_id)
- end
+ # RubyGems, ~/.rails/generators, and RAILS_ROOT/script/generators.
+ def lookup_missing_generator(class_id)
+ if md = /(.+)Generator$/.match(class_id.to_s)
+ name = md.captures.first.demodulize.underscore
+ Rails::Generator::Base.lookup(name).klass
+ else
+ const_missing_before_generators(class_id)
end
end
+
+ unless respond_to?(:const_missing_before_generators)
+ alias_method :const_missing_before_generators, :const_missing
+ alias_method :const_missing, :lookup_missing_generator
+ end
end
end
@@ -102,7 +98,7 @@ module Rails
# 4. Builtins. Model, controller, mailer, scaffold.
def use_component_sources!
reset_sources
- sources << PathSource.new(:app, "#{Object.const_get(:RAILS_ROOT)}/script/generators") if Object.const_defined?(:RAILS_ROOT)
+ sources << PathSource.new(:app, "#{::RAILS_ROOT}/script/generators") if defined? ::RAILS_ROOT
sources << PathSource.new(:user, "#{Dir.user_home}/.rails/generators")
sources << GemSource.new if Object.const_defined?(:Gem)
sources << PathSource.new(:builtin, "#{File.dirname(__FILE__)}/generators/components")
diff --git a/railties/lib/rails_generator/options.rb b/railties/lib/rails_generator/options.rb
index afe2d31625..54785413ef 100644
--- a/railties/lib/rails_generator/options.rb
+++ b/railties/lib/rails_generator/options.rb
@@ -1,8 +1,12 @@
require 'optparse'
-require File.dirname(__FILE__) + '/../support/class_inheritable_attributes'
+require File.dirname(__FILE__) + '/support/class_inheritable_attributes'
module Rails
module Generator
+ # Implement add_options! to add your options to the parser:
+ # def add_options!(opt)
+ # opt.on('-v', '--verbose') { |value| options[:verbose] = value }
+ # end
module Options
def self.append_features(base)
super
@@ -85,13 +89,14 @@ module Rails
@option_parser = OptionParser.new do |opt|
opt.banner = banner
- add_options!(opt)
+ add_options!(opt) if respond_to?(:add_options!)
add_general_options!(opt)
opt.parse!(args)
end
+ return args
+ ensure
self.options = full_options(runtime_options)
- args
end
# Raise a usage error. Override usage_message to provide a blurb
@@ -109,14 +114,6 @@ module Rails
"Usage: #{$0} [options]"
end
- # Override with a method that adds options to the parser.
- # Added options should use the options hash. For example,
- # def add_options!(opt)
- # opt.on('-v', '--verbose') { |value| options[:verbose] = value }
- # end
- def add_options!(opt)
- end
-
# Adds general options like -h and --quiet. Usually don't override.
def add_general_options!(opt)
opt.separator ''
diff --git a/railties/lib/rails_generator/scripts.rb b/railties/lib/rails_generator/scripts.rb
index 007980dcb5..f0b6b6f1ff 100644
--- a/railties/lib/rails_generator/scripts.rb
+++ b/railties/lib/rails_generator/scripts.rb
@@ -16,21 +16,23 @@ module Rails
# or first remaining argument, and invokes the requested command.
def run(args = [], runtime_options = {})
begin
- parse!(args, runtime_options)
-
- # Generator name is the only required option.
- unless options[:generator]
- usage if args.empty?
- options[:generator] ||= args.shift
- end
+ parse!(args.dup, runtime_options)
+ rescue OptionParser::InvalidOption => e
+ # Don't cry, script. Generators want what you think is invalid.
+ end
- # Look up generator instance and invoke command on it.
- Rails::Generator::Base.instance(options[:generator], args, options).command(options[:command]).invoke!
- rescue => e
- puts e
- puts " #{e.backtrace.join("\n ")}\n" if options[:backtrace]
- raise SystemExit
+ # Generator name is the only required option.
+ unless options[:generator]
+ usage if args.empty?
+ options[:generator] ||= args.shift
end
+
+ # Look up generator instance and invoke command on it.
+ Rails::Generator::Base.instance(options[:generator], args, options).command(options[:command]).invoke!
+ rescue => e
+ puts e
+ puts " #{e.backtrace.join("\n ")}\n" if options[:backtrace]
+ raise SystemExit
end
protected
diff --git a/railties/lib/rails_generator/scripts/destroy.rb b/railties/lib/rails_generator/scripts/destroy.rb
index fd8469fbc7..628ec4de32 100644
--- a/railties/lib/rails_generator/scripts/destroy.rb
+++ b/railties/lib/rails_generator/scripts/destroy.rb
@@ -3,9 +3,5 @@ require File.dirname(__FILE__) + '/../scripts'
module Rails::Generator::Scripts
class Destroy < Base
mandatory_options :command => :destroy
-
- protected
- def add_options!(opt)
- end
end
end
diff --git a/railties/lib/rails_generator/scripts/generate.rb b/railties/lib/rails_generator/scripts/generate.rb
index 329d6691df..1fe2f54ab3 100644
--- a/railties/lib/rails_generator/scripts/generate.rb
+++ b/railties/lib/rails_generator/scripts/generate.rb
@@ -3,9 +3,5 @@ require File.dirname(__FILE__) + '/../scripts'
module Rails::Generator::Scripts
class Generate < Base
mandatory_options :command => :create
-
- protected
- def add_options!(opt)
- end
end
end
diff --git a/railties/lib/rails_generator/scripts/update.rb b/railties/lib/rails_generator/scripts/update.rb
index ad1ae8004a..53a9faa366 100644
--- a/railties/lib/rails_generator/scripts/update.rb
+++ b/railties/lib/rails_generator/scripts/update.rb
@@ -5,9 +5,6 @@ module Rails::Generator::Scripts
mandatory_options :command => :update
protected
- def add_options!(opt)
- end
-
def banner
"Usage: #{$0} [options] scaffold"
end
diff --git a/railties/test/rails_generator_test.rb b/railties/test/rails_generator_test.rb
index 8470bed943..5934bb3e7b 100644
--- a/railties/test/rails_generator_test.rb
+++ b/railties/test/rails_generator_test.rb
@@ -1,22 +1,29 @@
-$LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib"
-RAILS_ROOT = File.dirname(__FILE__)
-
require 'test/unit'
-require 'rails_generator'
-require 'rails_generator/simple_logger'
-Rails::Generator::Base.logger = Rails::Generator::SimpleLogger.new
-
+# Optionally load RubyGems.
begin
require 'rubygems'
- require_gem 'actionpack'
rescue LoadError
end
+# Must set before requiring generator libs.
+RAILS_ROOT = File.dirname(__FILE__)
+
+# Preemptively load the rest of Rails so Gems don't hijack our requires.
+require File.dirname(__FILE__) + '/../../activerecord/lib/active_record'
+require File.dirname(__FILE__) + '/../../actionpack/lib/action_controller'
+require File.dirname(__FILE__) + '/../lib/rails_generator'
+
class RailsGeneratorTest < Test::Unit::TestCase
BUILTINS = %w(controller mailer model scaffold)
CAPITALIZED_BUILTINS = BUILTINS.map { |b| b.capitalize }
+ def test_sources
+ expected = [:app, :user, :RubyGems, :builtin]
+ expected.delete(:gem) unless Object.const_defined?(:Gem)
+ assert_equal expected, Rails::Generator::Base.sources.map { |s| s.label }
+ end
+
def test_lookup_builtins
(BUILTINS + CAPITALIZED_BUILTINS).each do |name|
assert_nothing_raised do
@@ -71,7 +78,7 @@ class RailsGeneratorTest < Test::Unit::TestCase
assert_equal 'admin/foo', g.name
assert_equal %w(admin), g.class_path
assert_equal 'Admin', g.class_nesting
- assert_equal 'Foo', g.class_name
+ assert_equal 'Admin::Foo', g.class_name
assert_equal 'foo', g.singular_name
assert_equal 'foos', g.plural_name
assert_equal g.singular_name, g.file_name