From c1304098cca8a9247a9ad1461a1a343354650843 Mon Sep 17 00:00:00 2001 From: Carlhuda Date: Wed, 2 Dec 2009 20:01:01 -0800 Subject: [PATCH] Reorganize autoloads: * A new module (ActiveSupport::Autoload) is provide that extends autoloading with new behavior. * All autoloads in modules that have extended ActiveSupport::Autoload will be eagerly required in threadsafe environments * Autoloads can optionally leave off the path if the path is the same as full_constant_name.underscore * It is possible to specify that a group of autoloads live under an additional path. For instance, all of ActionDispatch's middlewares are ActionDispatch::MiddlewareName, but they live under "action_dispatch/middlewares/middleware_name" * It is possible to specify that a group of autoloads are all found at the same path. For instance, a number of exceptions might all be declared there. * One consequence of this is that testing-related constants are not autoloaded. To get the testing helpers for a given component, require "component_name/test_case". For instance, "action_controller/test_case". * test_help.rb, which is automatically required by a Rails application's test helper, requires the test_case.rb for all active components, so this change will not be disruptive in existing or new applications. --- actionmailer/lib/action_mailer.rb | 32 +- actionmailer/lib/action_mailer/base.rb | 2 +- .../lib/action_mailer/delivery_method/file.rb | 2 +- actionmailer/lib/action_mailer/mail_helper.rb | 30 +- actionpack/lib/abstract_controller.rb | 25 +- .../rendering_controller.rb | 2 +- actionpack/lib/action_controller.rb | 116 +-- actionpack/lib/action_controller/base.rb | 2 +- actionpack/lib/action_controller/caching.rb | 7 +- .../deprecated/integration_test.rb | 2 + .../action_controller/metal/compatibility.rb | 2 +- .../lib/action_controller/metal/helpers.rb | 2 +- .../metal/{rescuable.rb => rescue.rb} | 0 .../{testing => }/test_case.rb | 3 + .../action_controller/vendor/html-scanner.rb | 2 + actionpack/lib/action_dispatch.rb | 43 +- .../middleware/show_exceptions.rb | 4 +- actionpack/lib/action_dispatch/test_case.rb | 6 + actionpack/lib/action_view.rb | 26 +- actionpack/lib/action_view/base.rb | 2 +- actionpack/lib/action_view/paths.rb | 2 +- .../action_view/{template => }/template.rb | 15 +- actionpack/lib/action_view/template/error.rb | 170 ++-- .../lib/action_view/template/handler.rb | 55 +- .../lib/action_view/template/handlers.rb | 80 +- .../action_view/template/handlers/builder.rb | 4 +- .../lib/action_view/template/handlers/erb.rb | 4 +- .../lib/action_view/template/handlers/rjs.rb | 4 +- .../lib/action_view/template/resolver.rb | 6 +- actionpack/lib/action_view/template/text.rb | 54 +- actionpack/lib/action_view/test_case.rb | 2 +- actionpack/test/abstract/layouts_test.rb | 26 +- actionpack/test/abstract/render_test.rb | 2 +- actionpack/test/controller/helper_test.rb | 2 +- actionpack/test/controller/layout_test.rb | 2 +- actionpack/test/template/render_test.rb | 8 +- activemodel/lib/active_model.rb | 43 +- activemodel/test/cases/helper.rb | 1 + activemodel/test/cases/tests_database.rb | 1 + activerecord/lib/active_record.rb | 100 +-- activeresource/lib/active_resource.rb | 16 +- activeresource/test/abstract_unit.rb | 1 + activeresource/test/cases/base_test.rb | 6 +- activesupport/lib/active_support/autoload.rb | 55 +- .../active_support/dependencies/autoload.rb | 37 + .../lib/active_support/testing/performance.rb | 742 +++++++++--------- activesupport/test/autoload.rb | 80 ++ .../test/fixtures/autoload/another_class.rb | 2 + .../test/fixtures/autoload/some_class.rb | 2 + railties/lib/rails/console_app.rb | 1 + railties/lib/rails/test_help.rb | 6 + railties/test/rails_info_controller_test.rb | 1 + 52 files changed, 1018 insertions(+), 822 deletions(-) rename actionpack/lib/action_controller/metal/{rescuable.rb => rescue.rb} (100%) rename actionpack/lib/action_controller/{testing => }/test_case.rb (99%) create mode 100644 actionpack/lib/action_dispatch/test_case.rb rename actionpack/lib/action_view/{template => }/template.rb (92%) create mode 100644 activesupport/lib/active_support/dependencies/autoload.rb create mode 100644 activesupport/test/autoload.rb create mode 100644 activesupport/test/fixtures/autoload/another_class.rb create mode 100644 activesupport/test/fixtures/autoload/some_class.rb diff --git a/actionmailer/lib/action_mailer.rb b/actionmailer/lib/action_mailer.rb index 23f04a11bad..12e781b6c39 100644 --- a/actionmailer/lib/action_mailer.rb +++ b/actionmailer/lib/action_mailer.rb @@ -25,32 +25,34 @@ actionpack_path = "#{File.dirname(__FILE__)}/../../actionpack/lib" $:.unshift(actionpack_path) if File.directory?(actionpack_path) require 'action_controller' require 'action_view' +require 'active_support/autoload' module ActionMailer - def self.load_all! - [Base, Part, ::Text::Format, ::Net::SMTP] - end + extend ::ActiveSupport::Autoload - autoload :AdvAttrAccessor, 'action_mailer/adv_attr_accessor' - autoload :DeprecatedBody, 'action_mailer/deprecated_body' - autoload :Base, 'action_mailer/base' - autoload :DeliveryMethod, 'action_mailer/delivery_method' - autoload :Part, 'action_mailer/part' - autoload :PartContainer, 'action_mailer/part_container' - autoload :Quoting, 'action_mailer/quoting' - autoload :TestCase, 'action_mailer/test_case' - autoload :TestHelper, 'action_mailer/test_helper' - autoload :Utils, 'action_mailer/utils' + autoload :AdvAttrAccessor + autoload :DeprecatedBody + autoload :Base + autoload :DeliveryMethod + autoload :MailHelper + autoload :Part + autoload :PartContainer + autoload :Quoting + autoload :TestHelper + autoload :Utils end module Text + extend ActiveSupport::Autoload + autoload :Format, 'action_mailer/vendor/text_format' end module Net - autoload :SMTP, 'net/smtp' + extend ActiveSupport::Autoload + + autoload :SMTP end -autoload :MailHelper, 'action_mailer/mail_helper' require 'action_mailer/vendor/tmail' diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb index 7b952c462f7..b5239ac0cd9 100644 --- a/actionmailer/lib/action_mailer/base.rb +++ b/actionmailer/lib/action_mailer/base.rb @@ -258,7 +258,7 @@ module ActionMailer #:nodoc: include AbstractController::Layouts include AbstractController::Helpers - helper MailHelper + helper ActionMailer::MailHelper if Object.const_defined?(:ActionController) include ActionController::UrlWriter diff --git a/actionmailer/lib/action_mailer/delivery_method/file.rb b/actionmailer/lib/action_mailer/delivery_method/file.rb index 587ae37ffaa..6c8cdf44509 100644 --- a/actionmailer/lib/action_mailer/delivery_method/file.rb +++ b/actionmailer/lib/action_mailer/delivery_method/file.rb @@ -6,7 +6,7 @@ module ActionMailer # A delivery method implementation which writes all mails to a file. class File < Method self.settings = { - :location => defined?(Rails) ? "#{Rails.root}/tmp/mails" : "#{Dir.tmpdir}/mails" + :location => defined?(Rails.root) ? "#{Rails.root}/tmp/mails" : "#{Dir.tmpdir}/mails" } def perform_delivery(mail) diff --git a/actionmailer/lib/action_mailer/mail_helper.rb b/actionmailer/lib/action_mailer/mail_helper.rb index 351b966abe7..9aa178cdef1 100644 --- a/actionmailer/lib/action_mailer/mail_helper.rb +++ b/actionmailer/lib/action_mailer/mail_helper.rb @@ -1,17 +1,19 @@ -module MailHelper - # Uses Text::Format to take the text and format it, indented two spaces for - # each line, and wrapped at 72 columns. - def block_format(text) - formatted = text.split(/\n\r\n/).collect { |paragraph| - Text::Format.new( - :columns => 72, :first_indent => 2, :body_indent => 2, :text => paragraph - ).format - }.join("\n") +module ActionMailer + module MailHelper + # Uses Text::Format to take the text and format it, indented two spaces for + # each line, and wrapped at 72 columns. + def block_format(text) + formatted = text.split(/\n\r\n/).collect { |paragraph| + Text::Format.new( + :columns => 72, :first_indent => 2, :body_indent => 2, :text => paragraph + ).format + }.join("\n") - # Make list points stand on their own line - formatted.gsub!(/[ ]*([*]+) ([^*]*)/) { |s| " #{$1} #{$2.strip}\n" } - formatted.gsub!(/[ ]*([#]+) ([^#]*)/) { |s| " #{$1} #{$2.strip}\n" } + # Make list points stand on their own line + formatted.gsub!(/[ ]*([*]+) ([^*]*)/) { |s| " #{$1} #{$2.strip}\n" } + formatted.gsub!(/[ ]*([#]+) ([^#]*)/) { |s| " #{$1} #{$2.strip}\n" } - formatted + formatted + end end -end +end \ No newline at end of file diff --git a/actionpack/lib/abstract_controller.rb b/actionpack/lib/abstract_controller.rb index 1a6c4278c99..688a2fe31cf 100644 --- a/actionpack/lib/abstract_controller.rb +++ b/actionpack/lib/abstract_controller.rb @@ -2,15 +2,20 @@ require "active_support/core_ext/module/attr_internal" require "active_support/core_ext/module/delegation" module AbstractController - autoload :Base, "abstract_controller/base" - autoload :Callbacks, "abstract_controller/callbacks" - autoload :Helpers, "abstract_controller/helpers" - autoload :Layouts, "abstract_controller/layouts" - autoload :LocalizedCache, "abstract_controller/localized_cache" - autoload :Logger, "abstract_controller/logger" - autoload :RenderingController, "abstract_controller/rendering_controller" + extend ActiveSupport::Autoload + + autoload :Base + autoload :Callbacks + autoload :Helpers + autoload :Layouts + autoload :LocalizedCache + autoload :Logger + autoload :RenderingController + # === Exceptions - autoload :ActionNotFound, "abstract_controller/exceptions" - autoload :DoubleRenderError, "abstract_controller/exceptions" - autoload :Error, "abstract_controller/exceptions" + autoload_at "abstract_controller/exceptions" do + autoload :ActionNotFound + autoload :DoubleRenderError + autoload :Error + end end diff --git a/actionpack/lib/abstract_controller/rendering_controller.rb b/actionpack/lib/abstract_controller/rendering_controller.rb index 7054b9cf269..777e515d601 100644 --- a/actionpack/lib/abstract_controller/rendering_controller.rb +++ b/actionpack/lib/abstract_controller/rendering_controller.rb @@ -115,7 +115,7 @@ module AbstractController # _partial:: Whether or not the file to look up is a partial def _determine_template(options) if options.key?(:text) - options[:_template] = ActionView::TextTemplate.new(options[:text], format_for_text) + options[:_template] = ActionView::Template::Text.new(options[:text], format_for_text) elsif options.key?(:inline) handler = ActionView::Template.handler_class_for_extension(options[:type] || "erb") template = ActionView::Template.new(options[:inline], "inline #{options[:inline].inspect}", handler, {}) diff --git a/actionpack/lib/action_controller.rb b/actionpack/lib/action_controller.rb index 03a40e4fce6..f830223058c 100644 --- a/actionpack/lib/action_controller.rb +++ b/actionpack/lib/action_controller.rb @@ -1,66 +1,72 @@ +require "active_support" + module ActionController - autoload :Base, "action_controller/base" - autoload :Benchmarking, "action_controller/metal/benchmarking" - autoload :ConditionalGet, "action_controller/metal/conditional_get" - autoload :Configuration, "action_controller/metal/configuration" - autoload :Head, "action_controller/metal/head" - autoload :Helpers, "action_controller/metal/helpers" - autoload :HideActions, "action_controller/metal/hide_actions" - autoload :Layouts, "action_controller/metal/layouts" - autoload :Metal, "action_controller/metal" - autoload :Middleware, "action_controller/middleware" - autoload :RackConvenience, "action_controller/metal/rack_convenience" - autoload :Rails2Compatibility, "action_controller/metal/compatibility" - autoload :Redirector, "action_controller/metal/redirector" - autoload :RenderingController, "action_controller/metal/rendering_controller" - autoload :RenderOptions, "action_controller/metal/render_options" - autoload :Rescue, "action_controller/metal/rescuable" - autoload :Responder, "action_controller/metal/responder" - autoload :Session, "action_controller/metal/session" - autoload :Testing, "action_controller/metal/testing" - autoload :UrlFor, "action_controller/metal/url_for" + extend ActiveSupport::Autoload - autoload :Caching, 'action_controller/caching' - autoload :Dispatcher, 'action_controller/dispatch/dispatcher' - autoload :Integration, 'action_controller/deprecated/integration_test' - autoload :IntegrationTest, 'action_controller/deprecated/integration_test' - autoload :MimeResponds, 'action_controller/metal/mime_responds' - autoload :PerformanceTest, 'action_controller/deprecated/performance_test' - autoload :PolymorphicRoutes, 'action_controller/polymorphic_routes' - autoload :RecordIdentifier, 'action_controller/record_identifier' - autoload :Routing, 'action_controller/deprecated' - autoload :SessionManagement, 'action_controller/metal/session_management' - autoload :TestCase, 'action_controller/testing/test_case' - autoload :TestProcess, 'action_controller/testing/process' - autoload :UrlRewriter, 'action_controller/url_rewriter' - autoload :UrlWriter, 'action_controller/url_rewriter' + autoload :Base + autoload :Caching + autoload :PolymorphicRoutes + autoload :RecordIdentifier + autoload :UrlRewriter + autoload :Translation + autoload :Metal + autoload :Middleware - autoload :Verification, 'action_controller/metal/verification' - autoload :Flash, 'action_controller/metal/flash' - autoload :RequestForgeryProtection, 'action_controller/metal/request_forgery_protection' - autoload :Streaming, 'action_controller/metal/streaming' - autoload :HttpAuthentication, 'action_controller/metal/http_authentication' - autoload :FilterParameterLogging, 'action_controller/metal/filter_parameter_logging' - autoload :Translation, 'action_controller/translation' - autoload :Cookies, 'action_controller/metal/cookies' + autoload_under "metal" do + autoload :Benchmarking + autoload :ConditionalGet + autoload :Configuration + autoload :Head + autoload :Helpers + autoload :HideActions + autoload :Layouts + autoload :MimeResponds + autoload :RackConvenience + autoload :Compatibility + autoload :Redirector + autoload :RenderingController + autoload :RenderOptions + autoload :Rescue + autoload :Responder + autoload :Session + autoload :SessionManagement + autoload :UrlFor + autoload :Verification + autoload :Flash + autoload :RequestForgeryProtection + autoload :Streaming + autoload :HttpAuthentication + autoload :FilterParameterLogging + autoload :Cookies + end - autoload :ActionControllerError, 'action_controller/metal/exceptions' - autoload :RenderError, 'action_controller/metal/exceptions' - autoload :RoutingError, 'action_controller/metal/exceptions' - autoload :MethodNotAllowed, 'action_controller/metal/exceptions' - autoload :NotImplemented, 'action_controller/metal/exceptions' - autoload :UnknownController, 'action_controller/metal/exceptions' - autoload :MissingFile, 'action_controller/metal/exceptions' - autoload :RenderError, 'action_controller/metal/exceptions' - autoload :SessionOverflowError, 'action_controller/metal/exceptions' - autoload :UnknownHttpMethod, 'action_controller/metal/exceptions' + autoload :Dispatcher, 'action_controller/dispatch/dispatcher' + autoload :PerformanceTest, 'action_controller/deprecated/performance_test' + autoload :Routing, 'action_controller/deprecated' + autoload :Integration, 'action_controller/deprecated/integration_test' + autoload :IntegrationTest, 'action_controller/deprecated/integration_test' + + autoload :UrlWriter, 'action_controller/url_rewriter' + + autoload_at "action_controller/metal/exceptions" do + autoload :ActionControllerError + autoload :RenderError + autoload :RoutingError + autoload :MethodNotAllowed + autoload :NotImplemented + autoload :UnknownController + autoload :MissingFile + autoload :RenderError + autoload :SessionOverflowError + autoload :UnknownHttpMethod + end end -autoload :HTML, 'action_controller/vendor/html-scanner' -autoload :AbstractController, 'abstract_controller' - +# All of these simply register additional autoloads +require 'abstract_controller' require 'action_dispatch' require 'action_view' +require 'action_controller/vendor/html-scanner' # Common ActiveSupport usage in ActionController require "active_support/concern" diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb index 4c026fe5f7b..ed3984c9d47 100644 --- a/actionpack/lib/action_controller/base.rb +++ b/actionpack/lib/action_controller/base.rb @@ -24,7 +24,7 @@ module ActionController include ActionController::MimeResponds # Rails 2.x compatibility - include ActionController::Rails2Compatibility + include ActionController::Compatibility include ActionController::Cookies include ActionController::Session diff --git a/actionpack/lib/action_controller/caching.rb b/actionpack/lib/action_controller/caching.rb index 3caf7590320..ad357ccedab 100644 --- a/actionpack/lib/action_controller/caching.rb +++ b/actionpack/lib/action_controller/caching.rb @@ -30,10 +30,11 @@ module ActionController #:nodoc: # config.action_controller.cache_store = MyOwnStore.new("parameter") module Caching extend ActiveSupport::Concern + extend ActiveSupport::Autoload - autoload :Actions, 'action_controller/caching/actions' - autoload :Fragments, 'action_controller/caching/fragments' - autoload :Pages, 'action_controller/caching/pages' + autoload :Actions + autoload :Fragments + autoload :Pages autoload :Sweeper, 'action_controller/caching/sweeping' autoload :Sweeping, 'action_controller/caching/sweeping' diff --git a/actionpack/lib/action_controller/deprecated/integration_test.rb b/actionpack/lib/action_controller/deprecated/integration_test.rb index 86336b6bc46..05c8c0f1569 100644 --- a/actionpack/lib/action_controller/deprecated/integration_test.rb +++ b/actionpack/lib/action_controller/deprecated/integration_test.rb @@ -1,2 +1,4 @@ +require "action_dispatch/testing/integration" + ActionController::Integration = ActionDispatch::Integration ActionController::IntegrationTest = ActionDispatch::IntegrationTest diff --git a/actionpack/lib/action_controller/metal/compatibility.rb b/actionpack/lib/action_controller/metal/compatibility.rb index 0c264fcd09f..a90f798cd54 100644 --- a/actionpack/lib/action_controller/metal/compatibility.rb +++ b/actionpack/lib/action_controller/metal/compatibility.rb @@ -1,5 +1,5 @@ module ActionController - module Rails2Compatibility + module Compatibility extend ActiveSupport::Concern class ::ActionController::ActionControllerError < StandardError #:nodoc: diff --git a/actionpack/lib/action_controller/metal/helpers.rb b/actionpack/lib/action_controller/metal/helpers.rb index b4325e24ad0..d0402e5bad5 100644 --- a/actionpack/lib/action_controller/metal/helpers.rb +++ b/actionpack/lib/action_controller/metal/helpers.rb @@ -52,7 +52,7 @@ module ActionController included do # Set the default directory for helpers extlib_inheritable_accessor(:helpers_dir) do - defined?(Rails) ? "#{Rails.root}/app/helpers" : "app/helpers" + defined?(Rails.root) ? "#{Rails.root}/app/helpers" : "app/helpers" end end diff --git a/actionpack/lib/action_controller/metal/rescuable.rb b/actionpack/lib/action_controller/metal/rescue.rb similarity index 100% rename from actionpack/lib/action_controller/metal/rescuable.rb rename to actionpack/lib/action_controller/metal/rescue.rb diff --git a/actionpack/lib/action_controller/testing/test_case.rb b/actionpack/lib/action_controller/test_case.rb similarity index 99% rename from actionpack/lib/action_controller/testing/test_case.rb rename to actionpack/lib/action_controller/test_case.rb index 01a55fe9307..7533a222997 100644 --- a/actionpack/lib/action_controller/testing/test_case.rb +++ b/actionpack/lib/action_controller/test_case.rb @@ -1,5 +1,8 @@ require 'active_support/test_case' require 'rack/session/abstract/id' +require 'action_controller/metal/testing' +require 'action_controller/testing/process' +require 'action_dispatch/test_case' module ActionController class TestRequest < ActionDispatch::TestRequest #:nodoc: diff --git a/actionpack/lib/action_controller/vendor/html-scanner.rb b/actionpack/lib/action_controller/vendor/html-scanner.rb index f622d195ee8..2cb20ddd05a 100644 --- a/actionpack/lib/action_controller/vendor/html-scanner.rb +++ b/actionpack/lib/action_controller/vendor/html-scanner.rb @@ -1,6 +1,8 @@ $LOAD_PATH << "#{File.dirname(__FILE__)}/html-scanner" module HTML + extend ActiveSupport::Autoload + autoload :CDATA, 'html/node' autoload :Document, 'html/document' autoload :FullSanitizer, 'html/sanitizer' diff --git a/actionpack/lib/action_dispatch.rb b/actionpack/lib/action_dispatch.rb index 259814a3225..e21dbc59cc6 100644 --- a/actionpack/lib/action_dispatch.rb +++ b/actionpack/lib/action_dispatch.rb @@ -28,37 +28,38 @@ module Rack end module ActionDispatch - autoload :Request, 'action_dispatch/http/request' - autoload :Response, 'action_dispatch/http/response' - autoload :StatusCodes, 'action_dispatch/http/status_codes' - autoload :Utils, 'action_dispatch/http/utils' + extend ActiveSupport::Autoload + + autoload_under "http" do + autoload :Request + autoload :Response + autoload :StatusCodes + autoload :Utils + end + + autoload_under "middleware" do + autoload :Callbacks + autoload :ParamsParser + autoload :Rescue + autoload :ShowExceptions + autoload :Static + autoload :StringCoercion + end - autoload :Callbacks, 'action_dispatch/middleware/callbacks' autoload :MiddlewareStack, 'action_dispatch/middleware/stack' - autoload :ParamsParser, 'action_dispatch/middleware/params_parser' - autoload :Rescue, 'action_dispatch/middleware/rescue' - autoload :ShowExceptions, 'action_dispatch/middleware/show_exceptions' - autoload :Static, 'action_dispatch/middleware/static' - autoload :StringCoercion, 'action_dispatch/middleware/string_coercion' - - autoload :Routing, 'action_dispatch/routing' - - autoload :Assertions, 'action_dispatch/testing/assertions' - autoload :Integration, 'action_dispatch/testing/integration' - autoload :IntegrationTest, 'action_dispatch/testing/integration' - autoload :PerformanceTest, 'action_dispatch/testing/performance_test' - autoload :TestRequest, 'action_dispatch/testing/test_request' - autoload :TestResponse, 'action_dispatch/testing/test_response' + autoload :Routing autoload :HTML, 'action_controller/vendor/html-scanner' module Http - autoload :Headers, 'action_dispatch/http/headers' + extend ActiveSupport::Autoload + + autoload :Headers end module Session autoload :AbstractStore, 'action_dispatch/middleware/session/abstract_store' - autoload :CookieStore, 'action_dispatch/middleware/session/cookie_store' + autoload :CookieStore, 'action_dispatch/middleware/session/cookie_store' autoload :MemCacheStore, 'action_dispatch/middleware/session/mem_cache_store' end end diff --git a/actionpack/lib/action_dispatch/middleware/show_exceptions.rb b/actionpack/lib/action_dispatch/middleware/show_exceptions.rb index 036deec6d2c..67c70a04189 100644 --- a/actionpack/lib/action_dispatch/middleware/show_exceptions.rb +++ b/actionpack/lib/action_dispatch/middleware/show_exceptions.rb @@ -29,7 +29,7 @@ module ActionDispatch 'ActionView::MissingTemplate' => 'missing_template', 'ActionController::RoutingError' => 'routing_error', ActionController::UnknownAction.name => 'unknown_action', - 'ActionView::TemplateError' => 'template_error' + 'ActionView::Template::Error' => 'template_error' }) FAILSAFE_RESPONSE = [500, {'Content-Type' => 'text/html'}, @@ -119,7 +119,7 @@ module ActionDispatch return unless logger ActiveSupport::Deprecation.silence do - if ActionView::TemplateError === exception + if ActionView::Template::Error === exception logger.fatal(exception.to_s) else logger.fatal( diff --git a/actionpack/lib/action_dispatch/test_case.rb b/actionpack/lib/action_dispatch/test_case.rb new file mode 100644 index 00000000000..afd708f06f7 --- /dev/null +++ b/actionpack/lib/action_dispatch/test_case.rb @@ -0,0 +1,6 @@ +require "action_dispatch/testing/assertions" +require "action_dispatch/testing/integration" +require "action_dispatch/testing/performance_test" +require "action_dispatch/testing/test_request" +require "action_dispatch/testing/test_response" +require "action_dispatch/testing/integration" \ No newline at end of file diff --git a/actionpack/lib/action_view.rb b/actionpack/lib/action_view.rb index f6f7ec0c8c1..81ee19d9961 100644 --- a/actionpack/lib/action_view.rb +++ b/actionpack/lib/action_view.rb @@ -24,27 +24,25 @@ require File.join(File.dirname(__FILE__), "action_pack") module ActionView - def self.load_all! - [Context, Base, TemplateError] + extend ActiveSupport::Autoload + + autoload :Base + autoload :Context + autoload :Template + autoload :Helpers + autoload :SafeBuffer + + + autoload_under "render" do + autoload :Partials + autoload :Rendering end - autoload :Base, 'action_view/base' - autoload :Context, 'action_view/context' - autoload :Helpers, 'action_view/helpers' autoload :MissingTemplate, 'action_view/base' - autoload :Partials, 'action_view/render/partials' autoload :Resolver, 'action_view/template/resolver' autoload :PathResolver, 'action_view/template/resolver' autoload :PathSet, 'action_view/paths' - autoload :Rendering, 'action_view/render/rendering' - autoload :Template, 'action_view/template/template' - autoload :TemplateError, 'action_view/template/error' - autoload :TemplateHandler, 'action_view/template/handler' - autoload :TemplateHandlers, 'action_view/template/handlers' - autoload :TextTemplate, 'action_view/template/text' - autoload :Helpers, 'action_view/helpers' autoload :FileSystemResolverWithFallback, 'action_view/template/resolver' - autoload :SafeBuffer, 'action_view/safe_buffer' end require 'action_view/erb/util' diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb index c33695770f5..d69e5109fa3 100644 --- a/actionpack/lib/action_view/base.rb +++ b/actionpack/lib/action_view/base.rb @@ -196,7 +196,7 @@ module ActionView #:nodoc: end class << self - delegate :erb_trim_mode=, :to => 'ActionView::TemplateHandlers::ERB' + delegate :erb_trim_mode=, :to => 'ActionView::Template::Handlers::ERB' delegate :logger, :to => 'ActionController::Base', :allow_nil => true end diff --git a/actionpack/lib/action_view/paths.rb b/actionpack/lib/action_view/paths.rb index 23bde61f9c0..0059b79e5f2 100644 --- a/actionpack/lib/action_view/paths.rb +++ b/actionpack/lib/action_view/paths.rb @@ -4,7 +4,7 @@ module ActionView #:nodoc: # TODO: Clean this up if obj.is_a?(String) if cache.nil? - cache = !defined?(Rails) || Rails.application.config.cache_classes + cache = !defined?(Rails.application) || Rails.application.config.cache_classes end FileSystemResolverWithFallback.new(obj, :cache => cache) else diff --git a/actionpack/lib/action_view/template/template.rb b/actionpack/lib/action_view/template.rb similarity index 92% rename from actionpack/lib/action_view/template/template.rb rename to actionpack/lib/action_view/template.rb index d1970ca3c74..210ad508f52 100644 --- a/actionpack/lib/action_view/template/template.rb +++ b/actionpack/lib/action_view/template.rb @@ -6,7 +6,14 @@ require "action_view/template/resolver" module ActionView class Template - extend TemplateHandlers + extend ActiveSupport::Autoload + + autoload :Error + autoload :Handler + autoload :Handlers + autoload :Text + + extend Template::Handlers attr_reader :source, :identifier, :handler, :mime_type, :formats, :details def initialize(source, identifier, handler, details) @@ -32,11 +39,11 @@ module ActionView view.send(method_name, locals, &block) end rescue Exception => e - if e.is_a?(TemplateError) + if e.is_a?(Template::Error) e.sub_template_of(self) raise e else - raise TemplateError.new(self, view.assigns, e) + raise Template::Error.new(self, view.assigns, e) end end @@ -103,7 +110,7 @@ module ActionView logger.debug "Backtrace: #{e.backtrace.join("\n")}" end - raise ActionView::TemplateError.new(self, {}, e) + raise ActionView::Template::Error.new(self, {}, e) end end diff --git a/actionpack/lib/action_view/template/error.rb b/actionpack/lib/action_view/template/error.rb index aa21606f76b..a136d4333ba 100644 --- a/actionpack/lib/action_view/template/error.rb +++ b/actionpack/lib/action_view/template/error.rb @@ -1,101 +1,103 @@ require "active_support/core_ext/enumerable" module ActionView - # The TemplateError exception is raised when the compilation of the template fails. This exception then gathers a - # bunch of intimate details and uses it to report a very precise exception message. - class TemplateError < ActionViewError #:nodoc: - SOURCE_CODE_RADIUS = 3 + class Template + # The Template::Error exception is raised when the compilation of the template fails. This exception then gathers a + # bunch of intimate details and uses it to report a very precise exception message. + class Error < ActionViewError #:nodoc: + SOURCE_CODE_RADIUS = 3 - attr_reader :original_exception + attr_reader :original_exception - def initialize(template, assigns, original_exception) - @template, @assigns, @original_exception = template, assigns.dup, original_exception - @backtrace = compute_backtrace - end - - def file_name - @template.identifier - end - - def message - ActiveSupport::Deprecation.silence { original_exception.message } - end - - def clean_backtrace - if defined?(Rails) && Rails.respond_to?(:backtrace_cleaner) - Rails.backtrace_cleaner.clean(original_exception.backtrace) - else - original_exception.backtrace + def initialize(template, assigns, original_exception) + @template, @assigns, @original_exception = template, assigns.dup, original_exception + @backtrace = compute_backtrace end - end - def sub_template_message - if @sub_templates - "Trace of template inclusion: " + - @sub_templates.collect { |template| template.inspect }.join(", ") - else - "" + def file_name + @template.identifier end - end - def source_extract(indentation = 0) - return unless num = line_number - num = num.to_i - - source_code = @template.source.split("\n") - - start_on_line = [ num - SOURCE_CODE_RADIUS - 1, 0 ].max - end_on_line = [ num + SOURCE_CODE_RADIUS - 1, source_code.length].min - - indent = ' ' * indentation - line_counter = start_on_line - return unless source_code = source_code[start_on_line..end_on_line] - - source_code.sum do |line| - line_counter += 1 - "#{indent}#{line_counter}: #{line}\n" + def message + ActiveSupport::Deprecation.silence { original_exception.message } end - end - def sub_template_of(template_path) - @sub_templates ||= [] - @sub_templates << template_path - end + def clean_backtrace + if defined?(Rails) && Rails.respond_to?(:backtrace_cleaner) + Rails.backtrace_cleaner.clean(original_exception.backtrace) + else + original_exception.backtrace + end + end - def line_number - @line_number ||= - if file_name - regexp = /#{Regexp.escape File.basename(file_name)}:(\d+)/ + def sub_template_message + if @sub_templates + "Trace of template inclusion: " + + @sub_templates.collect { |template| template.inspect }.join(", ") + else + "" + end + end - $1 if message =~ regexp or clean_backtrace.find { |line| line =~ regexp } + def source_extract(indentation = 0) + return unless num = line_number + num = num.to_i + + source_code = @template.source.split("\n") + + start_on_line = [ num - SOURCE_CODE_RADIUS - 1, 0 ].max + end_on_line = [ num + SOURCE_CODE_RADIUS - 1, source_code.length].min + + indent = ' ' * indentation + line_counter = start_on_line + return unless source_code = source_code[start_on_line..end_on_line] + + source_code.sum do |line| + line_counter += 1 + "#{indent}#{line_counter}: #{line}\n" + end + end + + def sub_template_of(template_path) + @sub_templates ||= [] + @sub_templates << template_path + end + + def line_number + @line_number ||= + if file_name + regexp = /#{Regexp.escape File.basename(file_name)}:(\d+)/ + + $1 if message =~ regexp or clean_backtrace.find { |line| line =~ regexp } + end + end + + def to_s + "\n#{self.class} (#{message}) #{source_location}:\n" + + "#{source_extract}\n #{clean_backtrace.join("\n ")}\n\n" + end + + # don't do anything nontrivial here. Any raised exception from here becomes fatal + # (and can't be rescued). + def backtrace + @backtrace + end + + private + def compute_backtrace + [ + "#{source_location.capitalize}\n\n#{source_extract(4)}\n " + + clean_backtrace.join("\n ") + ] + end + + def source_location + if line_number + "on line ##{line_number} of " + else + 'in ' + end + file_name end end - - def to_s - "\n#{self.class} (#{message}) #{source_location}:\n" + - "#{source_extract}\n #{clean_backtrace.join("\n ")}\n\n" - end - - # don't do anything nontrivial here. Any raised exception from here becomes fatal - # (and can't be rescued). - def backtrace - @backtrace - end - - private - def compute_backtrace - [ - "#{source_location.capitalize}\n\n#{source_extract(4)}\n " + - clean_backtrace.join("\n ") - ] - end - - def source_location - if line_number - "on line ##{line_number} of " - else - 'in ' - end + file_name - end end end \ No newline at end of file diff --git a/actionpack/lib/action_view/template/handler.rb b/actionpack/lib/action_view/template/handler.rb index 4bf58b9fa8a..5a46a278933 100644 --- a/actionpack/lib/action_view/template/handler.rb +++ b/actionpack/lib/action_view/template/handler.rb @@ -3,34 +3,39 @@ require "action_dispatch/http/mime_type" # Legacy TemplateHandler stub module ActionView - module TemplateHandlers #:nodoc: - module Compilable - def self.included(base) - base.extend(ClassMethods) - end - - module ClassMethods - def call(template) - new.compile(template) + class Template + module Handlers #:nodoc: + module Compilable + def self.included(base) + base.extend(ClassMethods) end + + module ClassMethods + def call(template) + new.compile(template) + end + end + + def compile(template) + raise "Need to implement #{self.class.name}#compile(template)" + end + end + end + + class Template::Handler + extlib_inheritable_accessor :default_format + self.default_format = Mime::HTML + + def self.call(template) + raise "Need to implement #{self.class.name}#call(template)" end - def compile(template) - raise "Need to implement #{self.class.name}#compile(template)" - end - end - end - - class TemplateHandler - extlib_inheritable_accessor :default_format - self.default_format = Mime::HTML - - def self.call(template) - raise "Need to implement #{self.class.name}#call(template)" - end - - def render(template, local_assigns) - raise "Need to implement #{self.class.name}#render(template, local_assigns)" + def render(template, local_assigns) + raise "Need to implement #{self.class.name}#render(template, local_assigns)" + end end end + + TemplateHandlers = Template::Handlers + TemplateHandler = Template::Handler end diff --git a/actionpack/lib/action_view/template/handlers.rb b/actionpack/lib/action_view/template/handlers.rb index faf54b9fe50..35488c0391c 100644 --- a/actionpack/lib/action_view/template/handlers.rb +++ b/actionpack/lib/action_view/template/handlers.rb @@ -1,52 +1,54 @@ module ActionView #:nodoc: - module TemplateHandlers #:nodoc: - autoload :ERB, 'action_view/template/handlers/erb' - autoload :RJS, 'action_view/template/handlers/rjs' - autoload :Builder, 'action_view/template/handlers/builder' + class Template + module Handlers #:nodoc: + autoload :ERB, 'action_view/template/handlers/erb' + autoload :RJS, 'action_view/template/handlers/rjs' + autoload :Builder, 'action_view/template/handlers/builder' - def self.extended(base) - base.register_default_template_handler :erb, TemplateHandlers::ERB - base.register_template_handler :rjs, TemplateHandlers::RJS - base.register_template_handler :builder, TemplateHandlers::Builder + def self.extended(base) + base.register_default_template_handler :erb, ERB + base.register_template_handler :rjs, RJS + base.register_template_handler :builder, Builder - # TODO: Depreciate old template extensions - base.register_template_handler :rhtml, TemplateHandlers::ERB - base.register_template_handler :rxml, TemplateHandlers::Builder - end + # TODO: Depreciate old template extensions + base.register_template_handler :rhtml, ERB + base.register_template_handler :rxml, Builder + end - @@template_handlers = {} - @@default_template_handlers = nil + @@template_handlers = {} + @@default_template_handlers = nil - def self.extensions - @@template_handlers.keys - end + def self.extensions + @@template_handlers.keys + end - # Register a class that knows how to handle template files with the given - # extension. This can be used to implement new template types. - # The constructor for the class must take the ActiveView::Base instance - # as a parameter, and the class must implement a +render+ method that - # takes the contents of the template to render as well as the Hash of - # local assigns available to the template. The +render+ method ought to - # return the rendered template as a string. - def register_template_handler(extension, klass) - @@template_handlers[extension.to_sym] = klass - end + # Register a class that knows how to handle template files with the given + # extension. This can be used to implement new template types. + # The constructor for the class must take the ActiveView::Base instance + # as a parameter, and the class must implement a +render+ method that + # takes the contents of the template to render as well as the Hash of + # local assigns available to the template. The +render+ method ought to + # return the rendered template as a string. + def register_template_handler(extension, klass) + @@template_handlers[extension.to_sym] = klass + end - def template_handler_extensions - @@template_handlers.keys.map {|key| key.to_s }.sort - end + def template_handler_extensions + @@template_handlers.keys.map {|key| key.to_s }.sort + end - def registered_template_handler(extension) - extension && @@template_handlers[extension.to_sym] - end + def registered_template_handler(extension) + extension && @@template_handlers[extension.to_sym] + end - def register_default_template_handler(extension, klass) - register_template_handler(extension, klass) - @@default_template_handlers = klass - end + def register_default_template_handler(extension, klass) + register_template_handler(extension, klass) + @@default_template_handlers = klass + end - def handler_class_for_extension(extension) - (extension && registered_template_handler(extension.to_sym)) || @@default_template_handlers + def handler_class_for_extension(extension) + (extension && registered_template_handler(extension.to_sym)) || @@default_template_handlers + end end end end diff --git a/actionpack/lib/action_view/template/handlers/builder.rb b/actionpack/lib/action_view/template/handlers/builder.rb index 5f381f7bf09..a93cfca8aa8 100644 --- a/actionpack/lib/action_view/template/handlers/builder.rb +++ b/actionpack/lib/action_view/template/handlers/builder.rb @@ -1,6 +1,6 @@ module ActionView - module TemplateHandlers - class Builder < TemplateHandler + module Template::Handlers + class Builder < Template::Handler include Compilable self.default_format = Mime::XML diff --git a/actionpack/lib/action_view/template/handlers/erb.rb b/actionpack/lib/action_view/template/handlers/erb.rb index 88aeb4b053b..f8e6376589c 100644 --- a/actionpack/lib/action_view/template/handlers/erb.rb +++ b/actionpack/lib/action_view/template/handlers/erb.rb @@ -3,7 +3,7 @@ require 'active_support/core_ext/string/output_safety' require 'erubis' module ActionView - module TemplateHandlers + module Template::Handlers class Erubis < ::Erubis::Eruby def add_preamble(src) src << "@output_buffer = ActionView::SafeBuffer.new;" @@ -26,7 +26,7 @@ module ActionView end end - class ERB < TemplateHandler + class ERB < Template::Handler include Compilable ## diff --git a/actionpack/lib/action_view/template/handlers/rjs.rb b/actionpack/lib/action_view/template/handlers/rjs.rb index b1d15dc209c..63e7dc09027 100644 --- a/actionpack/lib/action_view/template/handlers/rjs.rb +++ b/actionpack/lib/action_view/template/handlers/rjs.rb @@ -1,6 +1,6 @@ module ActionView - module TemplateHandlers - class RJS < TemplateHandler + module Template::Handlers + class RJS < Template::Handler include Compilable self.default_format = Mime::JS diff --git a/actionpack/lib/action_view/template/resolver.rb b/actionpack/lib/action_view/template/resolver.rb index 7336114e1b8..a2f4ab2ef59 100644 --- a/actionpack/lib/action_view/template/resolver.rb +++ b/actionpack/lib/action_view/template/resolver.rb @@ -1,6 +1,6 @@ require "pathname" require "active_support/core_ext/class" -require "action_view/template/template" +require "action_view/template" module ActionView # Abstract superclass @@ -20,7 +20,7 @@ module ActionView register_detail(:locale) { [I18n.locale] } register_detail(:formats) { Mime::SET.symbols } register_detail(:handlers, :allow_nil => false) do - TemplateHandlers.extensions + Template::Handlers.extensions end def initialize(options = {}) @@ -65,7 +65,7 @@ module ActionView # as well as incorrectly putting part of the path in the template # name instead of the prefix. def normalize_name(name, prefix) - handlers = TemplateHandlers.extensions.join('|') + handlers = Template::Handlers.extensions.join('|') name = name.to_s.gsub(/\.(?:#{handlers})$/, '') parts = name.split('/') diff --git a/actionpack/lib/action_view/template/text.rb b/actionpack/lib/action_view/template/text.rb index f6e011a5abb..67e086d8bd8 100644 --- a/actionpack/lib/action_view/template/text.rb +++ b/actionpack/lib/action_view/template/text.rb @@ -1,38 +1,40 @@ module ActionView #:nodoc: - class TextTemplate < String #:nodoc: - HTML = Mime[:html] + class Template + class Text < String #:nodoc: + HTML = Mime[:html] - def initialize(string, content_type = HTML) - super(string.to_s) - @content_type = Mime[content_type] || content_type - end + def initialize(string, content_type = HTML) + super(string.to_s) + @content_type = Mime[content_type] || content_type + end - def details - {:formats => [@content_type.to_sym]} - end + def details + {:formats => [@content_type.to_sym]} + end - def identifier - self - end + def identifier + self + end - def inspect - 'text template' - end + def inspect + 'text template' + end - def render(*args) - to_s - end + def render(*args) + to_s + end - def mime_type - @content_type - end + def mime_type + @content_type + end - def formats - [mime_type] - end + def formats + [mime_type] + end - def partial? - false + def partial? + false + end end end end diff --git a/actionpack/lib/action_view/test_case.rb b/actionpack/lib/action_view/test_case.rb index 86bbad822db..ab5bc49cf9e 100644 --- a/actionpack/lib/action_view/test_case.rb +++ b/actionpack/lib/action_view/test_case.rb @@ -1,5 +1,5 @@ require 'active_support/test_case' -require 'action_controller/testing/test_case' +require 'action_controller/test_case' module ActionView class Base diff --git a/actionpack/test/abstract/layouts_test.rb b/actionpack/test/abstract/layouts_test.rb index ae2f1bf1f22..5028c19b80d 100644 --- a/actionpack/test/abstract/layouts_test.rb +++ b/actionpack/test/abstract/layouts_test.rb @@ -23,7 +23,7 @@ module AbstractControllerTests self.view_paths = [] def index - render :_template => ActionView::TextTemplate.new("Hello blank!") + render :_template => ActionView::Template::Text.new("Hello blank!") end end @@ -31,19 +31,19 @@ module AbstractControllerTests layout "hello" def index - render :_template => ActionView::TextTemplate.new("Hello string!") + render :_template => ActionView::Template::Text.new("Hello string!") end def overwrite_default - render :_template => ActionView::TextTemplate.new("Hello string!"), :layout => :default + render :_template => ActionView::Template::Text.new("Hello string!"), :layout => :default end def overwrite_false - render :_template => ActionView::TextTemplate.new("Hello string!"), :layout => false + render :_template => ActionView::Template::Text.new("Hello string!"), :layout => false end def overwrite_string - render :_template => ActionView::TextTemplate.new("Hello string!"), :layout => "omg" + render :_template => ActionView::Template::Text.new("Hello string!"), :layout => "omg" end def overwrite_skip @@ -72,7 +72,7 @@ module AbstractControllerTests layout :hello def index - render :_template => ActionView::TextTemplate.new("Hello symbol!") + render :_template => ActionView::Template::Text.new("Hello symbol!") end private def hello @@ -84,7 +84,7 @@ module AbstractControllerTests layout :no_hello def index - render :_template => ActionView::TextTemplate.new("Hello missing symbol!") + render :_template => ActionView::Template::Text.new("Hello missing symbol!") end private def no_hello @@ -96,7 +96,7 @@ module AbstractControllerTests layout :nilz def index - render :_template => ActionView::TextTemplate.new("Hello nilz!") + render :_template => ActionView::Template::Text.new("Hello nilz!") end def nilz() end @@ -106,7 +106,7 @@ module AbstractControllerTests layout :objekt def index - render :_template => ActionView::TextTemplate.new("Hello nilz!") + render :_template => ActionView::Template::Text.new("Hello nilz!") end def objekt @@ -118,7 +118,7 @@ module AbstractControllerTests layout :omg_no_method def index - render :_template => ActionView::TextTemplate.new("Hello boom!") + render :_template => ActionView::Template::Text.new("Hello boom!") end end @@ -126,7 +126,7 @@ module AbstractControllerTests layout "missing" def index - render :_template => ActionView::TextTemplate.new("Hello missing!") + render :_template => ActionView::Template::Text.new("Hello missing!") end end @@ -134,7 +134,7 @@ module AbstractControllerTests layout false def index - render :_template => ActionView::TextTemplate.new("Hello false!") + render :_template => ActionView::Template::Text.new("Hello false!") end end @@ -142,7 +142,7 @@ module AbstractControllerTests layout nil def index - render :_template => ActionView::TextTemplate.new("Hello nil!") + render :_template => ActionView::Template::Text.new("Hello nil!") end end diff --git a/actionpack/test/abstract/render_test.rb b/actionpack/test/abstract/render_test.rb index 45a4763fe40..331cb6f7693 100644 --- a/actionpack/test/abstract/render_test.rb +++ b/actionpack/test/abstract/render_test.rb @@ -38,7 +38,7 @@ module AbstractController end def object - render :_template => ActionView::TextTemplate.new("With Object") + render :_template => ActionView::Template::Text.new("With Object") end end diff --git a/actionpack/test/controller/helper_test.rb b/actionpack/test/controller/helper_test.rb index b9be1639041..9030e562bb5 100644 --- a/actionpack/test/controller/helper_test.rb +++ b/actionpack/test/controller/helper_test.rb @@ -191,7 +191,7 @@ class IsolatedHelpersTest < Test::Unit::TestCase end def test_helper_in_a - assert_raise(ActionView::TemplateError) { call_controller(A, "index") } + assert_raise(ActionView::Template::Error) { call_controller(A, "index") } end def test_helper_in_b diff --git a/actionpack/test/controller/layout_test.rb b/actionpack/test/controller/layout_test.rb index feb2f81cc1a..f6352531568 100644 --- a/actionpack/test/controller/layout_test.rb +++ b/actionpack/test/controller/layout_test.rb @@ -115,7 +115,7 @@ class RendersNoLayoutController < LayoutTest end class LayoutSetInResponseTest < ActionController::TestCase - include ActionView::TemplateHandlers + include ActionView::Template::Handlers def test_layout_set_when_using_default_layout @controller = DefaultLayoutController.new diff --git a/actionpack/test/template/render_test.rb b/actionpack/test/template/render_test.rb index 35c51ca7ead..fdf3db1cdb4 100644 --- a/actionpack/test/template/render_test.rb +++ b/actionpack/test/template/render_test.rb @@ -106,8 +106,8 @@ module RenderTestCases def test_render_partial_with_errors @view.render(:partial => "test/raise") - flunk "Render did not raise TemplateError" - rescue ActionView::TemplateError => e + flunk "Render did not raise Template::Error" + rescue ActionView::Template::Error => e assert_match "undefined local variable or method `doesnt_exist'", e.message assert_equal "", e.sub_template_message assert_equal "1", e.line_number @@ -116,8 +116,8 @@ module RenderTestCases def test_render_sub_template_with_errors @view.render(:file => "test/sub_template_raise") - flunk "Render did not raise TemplateError" - rescue ActionView::TemplateError => e + flunk "Render did not raise Template::Error" + rescue ActionView::Template::Error => e assert_match "undefined local variable or method `doesnt_exist'", e.message assert_equal "Trace of template inclusion: #{File.expand_path("#{FIXTURE_LOAD_PATH}/test/sub_template_raise.html.erb")}", e.sub_template_message assert_equal "1", e.line_number diff --git a/activemodel/lib/active_model.rb b/activemodel/lib/active_model.rb index 505e16c1954..8e14b6724fa 100644 --- a/activemodel/lib/active_model.rb +++ b/activemodel/lib/active_model.rb @@ -26,28 +26,31 @@ $:.unshift(activesupport_path) if File.directory?(activesupport_path) require 'active_support' module ActiveModel - autoload :AttributeMethods, 'active_model/attribute_methods' - autoload :Conversion, 'active_model/conversion' - autoload :DeprecatedErrorMethods, 'active_model/deprecated_error_methods' - autoload :Dirty, 'active_model/dirty' - autoload :Errors, 'active_model/errors' - autoload :Lint, 'active_model/lint' - autoload :Name, 'active_model/naming' - autoload :Naming, 'active_model/naming' - autoload :Observer, 'active_model/observing' - autoload :Observing, 'active_model/observing' - autoload :Serialization, 'active_model/serialization' - autoload :StateMachine, 'active_model/state_machine' - autoload :TestCase, 'active_model/test_case' - autoload :Translation, 'active_model/translation' - autoload :Validations, 'active_model/validations' - autoload :ValidationsRepairHelper, 'active_model/validations_repair_helper' - autoload :Validator, 'active_model/validator' - autoload :VERSION, 'active_model/version' + extend ActiveSupport::Autoload + + autoload :AttributeMethods + autoload :Conversion + autoload :DeprecatedErrorMethods + autoload :Dirty + autoload :Errors + autoload :Lint + autoload :Name, 'active_model/naming' + autoload :Naming + autoload :Observer, 'active_model/observing' + autoload :Observing + autoload :Serialization + autoload :StateMachine + autoload :Translation + autoload :Validations + autoload :ValidationsRepairHelper + autoload :Validator + autoload :VERSION module Serializers - autoload :JSON, 'active_model/serializers/json' - autoload :Xml, 'active_model/serializers/xml' + extend ActiveSupport::Autoload + + autoload :JSON + autoload :Xml end end diff --git a/activemodel/test/cases/helper.rb b/activemodel/test/cases/helper.rb index c1a3f6a4a78..024f2378bea 100644 --- a/activemodel/test/cases/helper.rb +++ b/activemodel/test/cases/helper.rb @@ -10,6 +10,7 @@ $:.unshift(lib) unless $:.include?('lib') || $:.include?(lib) require 'config' require 'active_model' +require 'active_model/test_case' # Show backtraces for deprecated behavior for quicker cleanup. ActiveSupport::Deprecation.debug = true diff --git a/activemodel/test/cases/tests_database.rb b/activemodel/test/cases/tests_database.rb index 8dd00ea1474..79668dd9418 100644 --- a/activemodel/test/cases/tests_database.rb +++ b/activemodel/test/cases/tests_database.rb @@ -2,6 +2,7 @@ require 'logger' $:.unshift(File.dirname(__FILE__) + '/../../../activerecord/lib') require 'active_record' +require 'active_record/test_case' require 'active_record/fixtures' module ActiveModel diff --git a/activerecord/lib/active_record.rb b/activerecord/lib/active_record.rb index 8195e788267..f935d155266 100644 --- a/activerecord/lib/active_record.rb +++ b/activerecord/lib/active_record.rb @@ -32,64 +32,66 @@ require 'active_model' require 'arel' module ActiveRecord - # TODO: Review explicit loads to see if they will automatically be handled by the initializer. - def self.load_all! - [Base, DynamicFinderMatch, ConnectionAdapters::AbstractAdapter] - end + extend ActiveSupport::Autoload - autoload :VERSION, 'active_record/version' + autoload :VERSION autoload :ActiveRecordError, 'active_record/base' autoload :ConnectionNotEstablished, 'active_record/base' - autoload :Aggregations, 'active_record/aggregations' - autoload :AssociationPreload, 'active_record/association_preload' - autoload :Associations, 'active_record/associations' - autoload :AttributeMethods, 'active_record/attribute_methods' - autoload :Attributes, 'active_record/attributes' - autoload :AutosaveAssociation, 'active_record/autosave_association' - autoload :Relation, 'active_record/relation' - autoload :Base, 'active_record/base' - autoload :Batches, 'active_record/batches' - autoload :Calculations, 'active_record/calculations' - autoload :Callbacks, 'active_record/callbacks' - autoload :DynamicFinderMatch, 'active_record/dynamic_finder_match' - autoload :DynamicScopeMatch, 'active_record/dynamic_scope_match' - autoload :Migration, 'active_record/migration' + autoload :Aggregations + autoload :AssociationPreload + autoload :Associations + autoload :AttributeMethods + autoload :Attributes + autoload :AutosaveAssociation + autoload :Relation + autoload :Base + autoload :Batches + autoload :Calculations + autoload :Callbacks + autoload :DynamicFinderMatch + autoload :DynamicScopeMatch + autoload :Migration autoload :Migrator, 'active_record/migration' - autoload :NamedScope, 'active_record/named_scope' - autoload :NestedAttributes, 'active_record/nested_attributes' - autoload :Observer, 'active_record/observer' - autoload :QueryCache, 'active_record/query_cache' - autoload :Reflection, 'active_record/reflection' - autoload :Schema, 'active_record/schema' - autoload :SchemaDumper, 'active_record/schema_dumper' - autoload :Serialization, 'active_record/serialization' - autoload :SessionStore, 'active_record/session_store' - autoload :StateMachine, 'active_record/state_machine' - autoload :TestCase, 'active_record/test_case' - autoload :Timestamp, 'active_record/timestamp' - autoload :Transactions, 'active_record/transactions' - autoload :Types, 'active_record/types' - autoload :Validations, 'active_record/validations' + autoload :NamedScope + autoload :NestedAttributes + autoload :Observer + autoload :QueryCache + autoload :Reflection + autoload :Schema + autoload :SchemaDumper + autoload :Serialization + autoload :SessionStore + autoload :StateMachine + autoload :Timestamp + autoload :Transactions + autoload :Types + autoload :Validations module AttributeMethods - autoload :BeforeTypeCast, 'active_record/attribute_methods/before_type_cast' - autoload :Dirty, 'active_record/attribute_methods/dirty' - autoload :PrimaryKey, 'active_record/attribute_methods/primary_key' - autoload :Query, 'active_record/attribute_methods/query' - autoload :Read, 'active_record/attribute_methods/read' - autoload :TimeZoneConversion, 'active_record/attribute_methods/time_zone_conversion' - autoload :Write, 'active_record/attribute_methods/write' + extend ActiveSupport::Autoload + + autoload :BeforeTypeCast + autoload :Dirty + autoload :PrimaryKey + autoload :Query + autoload :Read + autoload :TimeZoneConversion + autoload :Write end module Attributes - autoload :Aliasing, 'active_record/attributes/aliasing' - autoload :Store, 'active_record/attributes/store' - autoload :Typecasting, 'active_record/attributes/typecasting' + extend ActiveSupport::Autoload + + autoload :Aliasing + autoload :Store + autoload :Typecasting end module Type + extend ActiveSupport::Autoload + autoload :Number, 'active_record/types/number' autoload :Object, 'active_record/types/object' autoload :Serialize, 'active_record/types/serialize' @@ -98,12 +100,16 @@ module ActiveRecord end module Locking - autoload :Optimistic, 'active_record/locking/optimistic' - autoload :Pessimistic, 'active_record/locking/pessimistic' + extend ActiveSupport::Autoload + + autoload :Optimistic + autoload :Pessimistic end module ConnectionAdapters - autoload :AbstractAdapter, 'active_record/connection_adapters/abstract_adapter' + extend ActiveSupport::Autoload + + autoload :AbstractAdapter end end diff --git a/activeresource/lib/active_resource.rb b/activeresource/lib/active_resource.rb index fd4c199b483..9357dd852f0 100644 --- a/activeresource/lib/active_resource.rb +++ b/activeresource/lib/active_resource.rb @@ -30,11 +30,13 @@ $:.unshift(activemodel_path) if File.directory?(activemodel_path) require 'active_model' module ActiveResource - autoload :Base, 'active_resource/base' - autoload :Connection, 'active_resource/connection' - autoload :CustomMethods, 'active_resource/custom_methods' - autoload :Formats, 'active_resource/formats' - autoload :Observing, 'active_resource/observing' - autoload :Validations, 'active_resource/validations' - autoload :HttpMock, 'active_resource/http_mock' + extend ActiveSupport::Autoload + + autoload :Base + autoload :Connection + autoload :CustomMethods + autoload :Formats + autoload :Observing + autoload :Validations + autoload :HttpMock end diff --git a/activeresource/test/abstract_unit.rb b/activeresource/test/abstract_unit.rb index 10849be20c6..3d684ff3479 100644 --- a/activeresource/test/abstract_unit.rb +++ b/activeresource/test/abstract_unit.rb @@ -13,6 +13,7 @@ require 'test/unit' require 'active_support' require 'active_support/test_case' require 'active_resource' +require 'active_model/test_case' $:.unshift "#{File.dirname(__FILE__)}/../test" require 'setter_trap' diff --git a/activeresource/test/cases/base_test.rb b/activeresource/test/cases/base_test.rb index 1d3f7891ec6..91349b810a2 100644 --- a/activeresource/test/cases/base_test.rb +++ b/activeresource/test/cases/base_test.rb @@ -543,9 +543,9 @@ class BaseTest < Test::Unit::TestCase assert Person.collection_path(:gender => 'male', :student => true).include?('gender=male') assert Person.collection_path(:gender => 'male', :student => true).include?('student=true') - assert_equal '/people.xml?name%5B%5D=bob&name%5B%5D=your+uncle%2Bme&name%5B%5D=&name%5B%5D=false', Person.collection_path(:name => ['bob', 'your uncle+me', nil, false]) + assert_equal '/people.xml?name[]=bob&name[]=your+uncle%2Bme&name[]=&name[]=false', Person.collection_path(:name => ['bob', 'your uncle+me', nil, false]) - assert_equal '/people.xml?struct%5Ba%5D%5B%5D=2&struct%5Ba%5D%5B%5D=1&struct%5Bb%5D=fred', Person.collection_path(:struct => {:a => [2,1], 'b' => 'fred'}) + assert_equal '/people.xml?struct[a][]=2&struct[a][]=1&struct[b]=fred', Person.collection_path(:struct => {:a => [2,1], 'b' => 'fred'}) end def test_custom_element_path @@ -581,7 +581,7 @@ class BaseTest < Test::Unit::TestCase assert_equal '/people/1/addresses/1.xml?type=work', StreetAddress.element_path(1, :person_id => 1, :type => 'work') assert_equal '/people/1/addresses/1.xml?type=work', StreetAddress.element_path(1, 'person_id' => 1, :type => 'work') assert_equal '/people/1/addresses/1.xml?type=work', StreetAddress.element_path(1, :type => 'work', :person_id => 1) - assert_equal '/people/1/addresses/1.xml?type%5B%5D=work&type%5B%5D=play+time', StreetAddress.element_path(1, :person_id => 1, :type => ['work', 'play time']) + assert_equal '/people/1/addresses/1.xml?type[]=work&type[]=play+time', StreetAddress.element_path(1, :person_id => 1, :type => ['work', 'play time']) end def test_custom_element_path_with_prefix_and_parameters diff --git a/activesupport/lib/active_support/autoload.rb b/activesupport/lib/active_support/autoload.rb index 63f7338a685..e57cf24b258 100644 --- a/activesupport/lib/active_support/autoload.rb +++ b/activesupport/lib/active_support/autoload.rb @@ -1,28 +1,31 @@ +require "active_support/dependencies/autoload" + module ActiveSupport - autoload :BacktraceCleaner, 'active_support/backtrace_cleaner' - autoload :Base64, 'active_support/base64' - autoload :BasicObject, 'active_support/basic_object' - autoload :Benchmarkable, 'active_support/benchmarkable' - autoload :BufferedLogger, 'active_support/buffered_logger' - autoload :Cache, 'active_support/cache' - autoload :Callbacks, 'active_support/callbacks' - autoload :Concern, 'active_support/concern' - autoload :Configurable, 'active_support/configurable' - autoload :DependencyModule, 'active_support/dependency_module' - autoload :DeprecatedCallbacks, 'active_support/deprecated_callbacks' - autoload :Deprecation, 'active_support/deprecation' - autoload :Gzip, 'active_support/gzip' - autoload :Inflector, 'active_support/inflector' - autoload :Memoizable, 'active_support/memoizable' - autoload :MessageEncryptor, 'active_support/message_encryptor' - autoload :MessageVerifier, 'active_support/message_verifier' - autoload :Multibyte, 'active_support/multibyte' - autoload :OptionMerger, 'active_support/option_merger' - autoload :OrderedHash, 'active_support/ordered_hash' - autoload :OrderedOptions, 'active_support/ordered_options' - autoload :Notifications, 'active_support/notifications' - autoload :Rescuable, 'active_support/rescuable' - autoload :SecureRandom, 'active_support/secure_random' - autoload :StringInquirer, 'active_support/string_inquirer' - autoload :XmlMini, 'active_support/xml_mini' + extend ActiveSupport::Autoload + + autoload :BacktraceCleaner + autoload :Base64 + autoload :BasicObject + autoload :Benchmarkable + autoload :BufferedLogger + autoload :Cache + autoload :Callbacks + autoload :Concern + autoload :Configurable + autoload :DeprecatedCallbacks + autoload :Deprecation + autoload :Gzip + autoload :Inflector + autoload :Memoizable + autoload :MessageEncryptor + autoload :MessageVerifier + autoload :Multibyte + autoload :OptionMerger + autoload :OrderedHash + autoload :OrderedOptions + autoload :Notifications + autoload :Rescuable + autoload :SecureRandom + autoload :StringInquirer + autoload :XmlMini end diff --git a/activesupport/lib/active_support/dependencies/autoload.rb b/activesupport/lib/active_support/dependencies/autoload.rb new file mode 100644 index 00000000000..973875f895f --- /dev/null +++ b/activesupport/lib/active_support/dependencies/autoload.rb @@ -0,0 +1,37 @@ +require "active_support/inflector/methods" + +module ActiveSupport + module Autoload + + @@autoloads = {} + @@under_path = nil + @@at_path = nil + + def autoload(const_name, path = @@at_path) + full = [self.name, @@under_path, const_name.to_s, path].compact.join("::") + location = path || Inflector.underscore(full) + + @@autoloads[const_name] = location + super const_name, location + end + + def autoload_under(path) + @@under_path, old_path = path, @@under_path + yield + ensure + @@under_path = old_path + end + + def autoload_at(path) + @@at_path, old_path = path, @@at_path + yield + ensure + @@at_path = old_path + end + + def self.eager_autoload! + @@autoloads.values.each {|file| require file } + end + + end +end \ No newline at end of file diff --git a/activesupport/lib/active_support/testing/performance.rb b/activesupport/lib/active_support/testing/performance.rb index ab34f975f6b..66e32fa5d73 100644 --- a/activesupport/lib/active_support/testing/performance.rb +++ b/activesupport/lib/active_support/testing/performance.rb @@ -1,450 +1,454 @@ -require 'ruby-prof' +begin + require 'ruby-prof' -require 'fileutils' -require 'rails/version' + require 'fileutils' + require 'rails/version' + require 'active_support/core_ext/class/delegating_attributes' -module ActiveSupport - module Testing - module Performance - DEFAULTS = - if benchmark = ARGV.include?('--benchmark') # HAX for rake test - { :benchmark => true, - :runs => 4, - :metrics => [:wall_time, :memory, :objects, :gc_runs, :gc_time], - :output => 'tmp/performance' } - else - { :benchmark => false, - :runs => 1, - :min_percent => 0.01, - :metrics => [:process_time, :memory, :objects], - :formats => [:flat, :graph_html, :call_tree], - :output => 'tmp/performance' } - end.freeze + module ActiveSupport + module Testing + module Performance + DEFAULTS = + if benchmark = ARGV.include?('--benchmark') # HAX for rake test + { :benchmark => true, + :runs => 4, + :metrics => [:wall_time, :memory, :objects, :gc_runs, :gc_time], + :output => 'tmp/performance' } + else + { :benchmark => false, + :runs => 1, + :min_percent => 0.01, + :metrics => [:process_time, :memory, :objects], + :formats => [:flat, :graph_html, :call_tree], + :output => 'tmp/performance' } + end.freeze - def self.included(base) - base.superclass_delegating_accessor :profile_options - base.profile_options = DEFAULTS - end - - def full_test_name - "#{self.class.name}##{method_name}" - end - - def run(result) - return if method_name =~ /^default_test$/ - - yield(self.class::STARTED, name) - @_result = result - - run_warmup - if profile_options && metrics = profile_options[:metrics] - metrics.each do |metric_name| - if klass = Metrics[metric_name.to_sym] - run_profile(klass.new) - result.add_run - end - end + def self.included(base) + base.superclass_delegating_accessor :profile_options + base.profile_options = DEFAULTS end - yield(self.class::FINISHED, name) - end + def full_test_name + "#{self.class.name}##{method_name}" + end - def run_test(metric, mode) - run_callbacks :setup - setup - metric.send(mode) { __send__ @method_name } - rescue ::Test::Unit::AssertionFailedError => e - add_failure(e.message, e.backtrace) - rescue StandardError, ScriptError - add_error($!) - ensure - begin - teardown - run_callbacks :teardown, :enumerator => :reverse_each + def run(result) + return if method_name =~ /^default_test$/ + + yield(self.class::STARTED, name) + @_result = result + + run_warmup + if profile_options && metrics = profile_options[:metrics] + metrics.each do |metric_name| + if klass = Metrics[metric_name.to_sym] + run_profile(klass.new) + result.add_run + end + end + end + + yield(self.class::FINISHED, name) + end + + def run_test(metric, mode) + run_callbacks :setup + setup + metric.send(mode) { __send__ @method_name } rescue ::Test::Unit::AssertionFailedError => e add_failure(e.message, e.backtrace) rescue StandardError, ScriptError add_error($!) - end - end - - protected - def run_warmup - GC.start - - time = Metrics::Time.new - run_test(time, :benchmark) - puts "%s (%s warmup)" % [full_test_name, time.format(time.total)] - - GC.start - end - - def run_profile(metric) - klass = profile_options[:benchmark] ? Benchmarker : Profiler - performer = klass.new(self, metric) - - performer.run - puts performer.report - performer.record - end - - class Performer - delegate :run_test, :profile_options, :full_test_name, :to => :@harness - - def initialize(harness, metric) - @harness, @metric = harness, metric - end - - def report - rate = @total / profile_options[:runs] - '%20s: %s' % [@metric.name, @metric.format(rate)] - end - - protected - def output_filename - "#{profile_options[:output]}/#{full_test_name}_#{@metric.name}" - end - end - - class Benchmarker < Performer - def run - profile_options[:runs].to_i.times { run_test(@metric, :benchmark) } - @total = @metric.total - end - - def record - avg = @metric.total / profile_options[:runs].to_i - now = Time.now.utc.xmlschema - with_output_file do |file| - file.puts "#{avg},#{now},#{environment}" - end - end - - def environment - unless defined? @env - app = "#{$1}.#{$2}" if File.directory?('.git') && `git branch -v` =~ /^\* (\S+)\s+(\S+)/ - - rails = Rails::VERSION::STRING - if File.directory?('vendor/rails/.git') - Dir.chdir('vendor/rails') do - rails += ".#{$1}.#{$2}" if `git branch -v` =~ /^\* (\S+)\s+(\S+)/ - end - end - - ruby = defined?(RUBY_ENGINE) ? RUBY_ENGINE : 'ruby' - ruby += "-#{RUBY_VERSION}.#{RUBY_PATCHLEVEL}" - - @env = [app, rails, ruby, RUBY_PLATFORM] * ',' - end - - @env - end - - protected - HEADER = 'measurement,created_at,app,rails,ruby,platform' - - def with_output_file - fname = output_filename - - if new = !File.exist?(fname) - FileUtils.mkdir_p(File.dirname(fname)) - end - - File.open(fname, 'ab') do |file| - file.puts(HEADER) if new - yield file - end - end - - def output_filename - "#{super}.csv" - end - end - - class Profiler < Performer - def initialize(*args) - super - @supported = @metric.measure_mode rescue false - end - - def run - return unless @supported - - RubyProf.measure_mode = @metric.measure_mode - RubyProf.start - RubyProf.pause - profile_options[:runs].to_i.times { run_test(@metric, :profile) } - @data = RubyProf.stop - @total = @data.threads.values.sum(0) { |method_infos| method_infos.sort.last.total_time } - end - - def report - if @supported - super - else - '%20s: unsupported' % @metric.name - end - end - - def record - return unless @supported - - klasses = profile_options[:formats].map { |f| RubyProf.const_get("#{f.to_s.camelize}Printer") }.compact - - klasses.each do |klass| - fname = output_filename(klass) - FileUtils.mkdir_p(File.dirname(fname)) - File.open(fname, 'wb') do |file| - klass.new(@data).print(file, profile_options.slice(:min_percent)) - end + ensure + begin + teardown + run_callbacks :teardown, :enumerator => :reverse_each + rescue ::Test::Unit::AssertionFailedError => e + add_failure(e.message, e.backtrace) + rescue StandardError, ScriptError + add_error($!) end end protected - def output_filename(printer_class) - suffix = - case printer_class.name.demodulize - when 'FlatPrinter'; 'flat.txt' - when 'GraphPrinter'; 'graph.txt' - when 'GraphHtmlPrinter'; 'graph.html' - when 'CallTreePrinter'; 'tree.txt' - else printer_class.name.sub(/Printer$/, '').underscore - end + def run_warmup + GC.start - "#{super()}_#{suffix}" - end - end + time = Metrics::Time.new + run_test(time, :benchmark) + puts "%s (%s warmup)" % [full_test_name, time.format(time.total)] - module Metrics - def self.[](name) - const_get(name.to_s.camelize) - rescue NameError - nil - end - - class Base - attr_reader :total - - def initialize - @total = 0 + GC.start end - def name - @name ||= self.class.name.demodulize.underscore + def run_profile(metric) + klass = profile_options[:benchmark] ? Benchmarker : Profiler + performer = klass.new(self, metric) + + performer.run + puts performer.report + performer.record end - def measure_mode - self.class::Mode + class Performer + delegate :run_test, :profile_options, :full_test_name, :to => :@harness + + def initialize(harness, metric) + @harness, @metric = harness, metric end - def measure - 0 - end - - def benchmark - with_gc_stats do - before = measure - yield - @total += (measure - before) - end - end - - def profile - RubyProf.resume - yield - ensure - RubyProf.pause + def report + rate = @total / profile_options[:runs] + '%20s: %s' % [@metric.name, @metric.format(rate)] end protected - if GC.respond_to?(:enable_stats) - def with_gc_stats - GC.enable_stats - yield - ensure - GC.disable_stats - end - elsif defined?(GC::Profiler) - def with_gc_stats - GC.start - GC.disable - GC::Profiler.enable - yield - ensure - GC::Profiler.disable - GC.enable - end - else - def with_gc_stats - yield - end + def output_filename + "#{profile_options[:output]}/#{full_test_name}_#{@metric.name}" end end - class Time < Base - def measure - ::Time.now.to_f + class Benchmarker < Performer + def run + profile_options[:runs].to_i.times { run_test(@metric, :benchmark) } + @total = @metric.total end - def format(measurement) - if measurement < 2 - '%d ms' % (measurement * 1000) - else - '%.2f sec' % measurement + def record + avg = @metric.total / profile_options[:runs].to_i + now = Time.now.utc.xmlschema + with_output_file do |file| + file.puts "#{avg},#{now},#{environment}" end end - end - class ProcessTime < Time - Mode = RubyProf::PROCESS_TIME + def environment + unless defined? @env + app = "#{$1}.#{$2}" if File.directory?('.git') && `git branch -v` =~ /^\* (\S+)\s+(\S+)/ - def measure - RubyProf.measure_process_time + rails = Rails::VERSION::STRING + if File.directory?('vendor/rails/.git') + Dir.chdir('vendor/rails') do + rails += ".#{$1}.#{$2}" if `git branch -v` =~ /^\* (\S+)\s+(\S+)/ + end + end + + ruby = defined?(RUBY_ENGINE) ? RUBY_ENGINE : 'ruby' + ruby += "-#{RUBY_VERSION}.#{RUBY_PATCHLEVEL}" + + @env = [app, rails, ruby, RUBY_PLATFORM] * ',' + end + + @env end + + protected + HEADER = 'measurement,created_at,app,rails,ruby,platform' + + def with_output_file + fname = output_filename + + if new = !File.exist?(fname) + FileUtils.mkdir_p(File.dirname(fname)) + end + + File.open(fname, 'ab') do |file| + file.puts(HEADER) if new + yield file + end + end + + def output_filename + "#{super}.csv" + end end - class WallTime < Time - Mode = RubyProf::WALL_TIME - - def measure - RubyProf.measure_wall_time - end - end - - class CpuTime < Time - Mode = RubyProf::CPU_TIME if RubyProf.const_defined?(:CPU_TIME) - + class Profiler < Performer def initialize(*args) - # FIXME: yeah my CPU is 2.33 GHz - RubyProf.cpu_frequency = 2.33e9 super + @supported = @metric.measure_mode rescue false end - def measure - RubyProf.measure_cpu_time + def run + return unless @supported + + RubyProf.measure_mode = @metric.measure_mode + RubyProf.start + RubyProf.pause + profile_options[:runs].to_i.times { run_test(@metric, :profile) } + @data = RubyProf.stop + @total = @data.threads.values.sum(0) { |method_infos| method_infos.sort.last.total_time } end + + def report + if @supported + super + else + '%20s: unsupported' % @metric.name + end + end + + def record + return unless @supported + + klasses = profile_options[:formats].map { |f| RubyProf.const_get("#{f.to_s.camelize}Printer") }.compact + + klasses.each do |klass| + fname = output_filename(klass) + FileUtils.mkdir_p(File.dirname(fname)) + File.open(fname, 'wb') do |file| + klass.new(@data).print(file, profile_options.slice(:min_percent)) + end + end + end + + protected + def output_filename(printer_class) + suffix = + case printer_class.name.demodulize + when 'FlatPrinter'; 'flat.txt' + when 'GraphPrinter'; 'graph.txt' + when 'GraphHtmlPrinter'; 'graph.html' + when 'CallTreePrinter'; 'tree.txt' + else printer_class.name.sub(/Printer$/, '').underscore + end + + "#{super()}_#{suffix}" + end end - class Memory < Base - Mode = RubyProf::MEMORY if RubyProf.const_defined?(:MEMORY) + module Metrics + def self.[](name) + const_get(name.to_s.camelize) + rescue NameError + nil + end - # ruby-prof wrapper - if RubyProf.respond_to?(:measure_memory) - def measure - RubyProf.measure_memory / 1024.0 + class Base + attr_reader :total + + def initialize + @total = 0 end - # Ruby 1.8 + railsbench patch - elsif GC.respond_to?(:allocated_size) - def measure - GC.allocated_size / 1024.0 + def name + @name ||= self.class.name.demodulize.underscore end - # Ruby 1.8 + lloyd patch - elsif GC.respond_to?(:heap_info) - def measure - GC.heap_info['heap_current_memory'] / 1024.0 + def measure_mode + self.class::Mode end - # Ruby 1.9 with total_malloc_allocated_size patch - elsif GC.respond_to?(:malloc_total_allocated_size) def measure - GC.total_malloc_allocated_size / 1024.0 + 0 end - # Ruby 1.9 unpatched - elsif GC.respond_to?(:malloc_allocated_size) - def measure - GC.malloc_allocated_size / 1024.0 + def benchmark + with_gc_stats do + before = measure + yield + @total += (measure - before) + end end - # Ruby 1.9 + GC profiler patch - elsif defined?(GC::Profiler) + def profile + RubyProf.resume + yield + ensure + RubyProf.pause + end + + protected + if GC.respond_to?(:enable_stats) + def with_gc_stats + GC.enable_stats + yield + ensure + GC.disable_stats + end + elsif defined?(GC::Profiler) + def with_gc_stats + GC.start + GC.disable + GC::Profiler.enable + yield + ensure + GC::Profiler.disable + GC.enable + end + else + def with_gc_stats + yield + end + end + end + + class Time < Base def measure - GC.enable - GC.start - kb = GC::Profiler.data.last[:HEAP_USE_SIZE] / 1024.0 - GC.disable - kb + ::Time.now.to_f + end + + def format(measurement) + if measurement < 2 + '%d ms' % (measurement * 1000) + else + '%.2f sec' % measurement + end end end - def format(measurement) - '%.2f KB' % measurement - end - end + class ProcessTime < Time + Mode = RubyProf::PROCESS_TIME - class Objects < Base - Mode = RubyProf::ALLOCATIONS if RubyProf.const_defined?(:ALLOCATIONS) - - if RubyProf.respond_to?(:measure_allocations) def measure - RubyProf.measure_allocations - end - - # Ruby 1.8 + railsbench patch - elsif ObjectSpace.respond_to?(:allocated_objects) - def measure - ObjectSpace.allocated_objects - end - - # Ruby 1.9 + GC profiler patch - elsif defined?(GC::Profiler) - def measure - GC.enable - GC.start - last = GC::Profiler.data.last - count = last[:HEAP_LIVE_OBJECTS] + last[:HEAP_FREE_OBJECTS] - GC.disable - count + RubyProf.measure_process_time end end - def format(measurement) - measurement.to_i.to_s - end - end + class WallTime < Time + Mode = RubyProf::WALL_TIME - class GcRuns < Base - Mode = RubyProf::GC_RUNS if RubyProf.const_defined?(:GC_RUNS) - - if RubyProf.respond_to?(:measure_gc_runs) def measure - RubyProf.measure_gc_runs - end - elsif GC.respond_to?(:collections) - def measure - GC.collections - end - elsif GC.respond_to?(:heap_info) - def measure - GC.heap_info['num_gc_passes'] + RubyProf.measure_wall_time end end - def format(measurement) - measurement.to_i.to_s - end - end + class CpuTime < Time + Mode = RubyProf::CPU_TIME if RubyProf.const_defined?(:CPU_TIME) - class GcTime < Base - Mode = RubyProf::GC_TIME if RubyProf.const_defined?(:GC_TIME) - - if RubyProf.respond_to?(:measure_gc_time) - def measure - RubyProf.measure_gc_time + def initialize(*args) + # FIXME: yeah my CPU is 2.33 GHz + RubyProf.cpu_frequency = 2.33e9 + super end - elsif GC.respond_to?(:time) + def measure - GC.time + RubyProf.measure_cpu_time end end - def format(measurement) - '%d ms' % (measurement / 1000) + class Memory < Base + Mode = RubyProf::MEMORY if RubyProf.const_defined?(:MEMORY) + + # ruby-prof wrapper + if RubyProf.respond_to?(:measure_memory) + def measure + RubyProf.measure_memory / 1024.0 + end + + # Ruby 1.8 + railsbench patch + elsif GC.respond_to?(:allocated_size) + def measure + GC.allocated_size / 1024.0 + end + + # Ruby 1.8 + lloyd patch + elsif GC.respond_to?(:heap_info) + def measure + GC.heap_info['heap_current_memory'] / 1024.0 + end + + # Ruby 1.9 with total_malloc_allocated_size patch + elsif GC.respond_to?(:malloc_total_allocated_size) + def measure + GC.total_malloc_allocated_size / 1024.0 + end + + # Ruby 1.9 unpatched + elsif GC.respond_to?(:malloc_allocated_size) + def measure + GC.malloc_allocated_size / 1024.0 + end + + # Ruby 1.9 + GC profiler patch + elsif defined?(GC::Profiler) + def measure + GC.enable + GC.start + kb = GC::Profiler.data.last[:HEAP_USE_SIZE] / 1024.0 + GC.disable + kb + end + end + + def format(measurement) + '%.2f KB' % measurement + end + end + + class Objects < Base + Mode = RubyProf::ALLOCATIONS if RubyProf.const_defined?(:ALLOCATIONS) + + if RubyProf.respond_to?(:measure_allocations) + def measure + RubyProf.measure_allocations + end + + # Ruby 1.8 + railsbench patch + elsif ObjectSpace.respond_to?(:allocated_objects) + def measure + ObjectSpace.allocated_objects + end + + # Ruby 1.9 + GC profiler patch + elsif defined?(GC::Profiler) + def measure + GC.enable + GC.start + last = GC::Profiler.data.last + count = last[:HEAP_LIVE_OBJECTS] + last[:HEAP_FREE_OBJECTS] + GC.disable + count + end + end + + def format(measurement) + measurement.to_i.to_s + end + end + + class GcRuns < Base + Mode = RubyProf::GC_RUNS if RubyProf.const_defined?(:GC_RUNS) + + if RubyProf.respond_to?(:measure_gc_runs) + def measure + RubyProf.measure_gc_runs + end + elsif GC.respond_to?(:collections) + def measure + GC.collections + end + elsif GC.respond_to?(:heap_info) + def measure + GC.heap_info['num_gc_passes'] + end + end + + def format(measurement) + measurement.to_i.to_s + end + end + + class GcTime < Base + Mode = RubyProf::GC_TIME if RubyProf.const_defined?(:GC_TIME) + + if RubyProf.respond_to?(:measure_gc_time) + def measure + RubyProf.measure_gc_time + end + elsif GC.respond_to?(:time) + def measure + GC.time + end + end + + def format(measurement) + '%d ms' % (measurement / 1000) + end end end end end end -end +rescue LoadError +end \ No newline at end of file diff --git a/activesupport/test/autoload.rb b/activesupport/test/autoload.rb new file mode 100644 index 00000000000..5d8026a9ca1 --- /dev/null +++ b/activesupport/test/autoload.rb @@ -0,0 +1,80 @@ +require 'abstract_unit' + +class TestAutoloadModule < ActiveSupport::TestCase + include ActiveSupport::Testing::Isolation + + module ::Fixtures + extend ActiveSupport::Autoload + + module Autoload + extend ActiveSupport::Autoload + end + end + + test "the autoload module works like normal autoload" do + module ::Fixtures::Autoload + autoload :SomeClass, "fixtures/autoload/some_class" + end + + assert_nothing_raised { ::Fixtures::Autoload::SomeClass } + end + + test "when specifying an :eager constant it still works like normal autoload by default" do + module ::Fixtures::Autoload + autoload :SomeClass, "fixtures/autoload/some_class" + end + + assert !$LOADED_FEATURES.include?("fixtures/autoload/some_class.rb") + assert_nothing_raised { ::Fixtures::Autoload::SomeClass } + end + + test ":eager constants can be triggered via ActiveSupport::Autoload.eager_autoload!" do + module ::Fixtures::Autoload + autoload :SomeClass, "fixtures/autoload/some_class" + end + ActiveSupport::Autoload.eager_autoload! + assert $LOADED_FEATURES.include?("fixtures/autoload/some_class.rb") + assert_nothing_raised { ::Fixtures::Autoload::SomeClass } + end + + test "the location of autoloaded constants defaults to :name.underscore" do + module ::Fixtures::Autoload + autoload :SomeClass + end + + assert !$LOADED_FEATURES.include?("fixtures/autoload/some_class.rb") + assert_nothing_raised { ::Fixtures::Autoload::SomeClass } + end + + test "the location of :eager autoloaded constants defaults to :name.underscore" do + module ::Fixtures::Autoload + autoload :SomeClass + end + + ActiveSupport::Autoload.eager_autoload! + assert $LOADED_FEATURES.include?("fixtures/autoload/some_class.rb") + assert_nothing_raised { ::Fixtures::Autoload::SomeClass } + end + + test "a directory for a block of autoloads can be specified" do + module ::Fixtures + autoload_under "autoload" do + autoload :AnotherClass + end + end + + assert !$LOADED_FEATURES.include?("fixtures/autoload/another_class.rb") + assert_nothing_raised { ::Fixtures::AnotherClass } + end + + test "a path for a block of autoloads can be specified" do + module ::Fixtures + autoload_at "fixtures/autoload/another_class" do + autoload :AnotherClass + end + end + + assert !$LOADED_FEATURES.include?("fixtures/autoload/another_class.rb") + assert_nothing_raised { ::Fixtures::AnotherClass } + end +end \ No newline at end of file diff --git a/activesupport/test/fixtures/autoload/another_class.rb b/activesupport/test/fixtures/autoload/another_class.rb new file mode 100644 index 00000000000..a240b3de41d --- /dev/null +++ b/activesupport/test/fixtures/autoload/another_class.rb @@ -0,0 +1,2 @@ +class Fixtures::AnotherClass +end \ No newline at end of file diff --git a/activesupport/test/fixtures/autoload/some_class.rb b/activesupport/test/fixtures/autoload/some_class.rb new file mode 100644 index 00000000000..13b3c73ef5f --- /dev/null +++ b/activesupport/test/fixtures/autoload/some_class.rb @@ -0,0 +1,2 @@ +class Fixtures::Autoload::SomeClass +end \ No newline at end of file diff --git a/railties/lib/rails/console_app.rb b/railties/lib/rails/console_app.rb index 1ad62e50588..9a51d594d34 100644 --- a/railties/lib/rails/console_app.rb +++ b/railties/lib/rails/console_app.rb @@ -1,6 +1,7 @@ require 'active_support/all' require 'active_support/test_case' require 'action_controller' +require 'action_dispatch/test_case' # work around the at_exit hook in test/unit, which kills IRB Test::Unit.run = true if Test::Unit.respond_to?(:run=) diff --git a/railties/lib/rails/test_help.rb b/railties/lib/rails/test_help.rb index 9f6c42945ff..0bf5f5c625b 100644 --- a/railties/lib/rails/test_help.rb +++ b/railties/lib/rails/test_help.rb @@ -8,8 +8,14 @@ gem "rack-test", "~> 0.5.0" require 'test/unit' require 'active_support/core_ext/kernel/requires' + +# AP is always present +require 'action_controller/test_case' require 'action_view/test_case' +require 'action_dispatch/test_case' + require 'action_mailer/test_case' if defined?(ActionMailer) +require 'active_model/test_case' if defined?(ActiveModel) if defined?(ActiveRecord) require 'active_record/test_case' diff --git a/railties/test/rails_info_controller_test.rb b/railties/test/rails_info_controller_test.rb index 39f23fa0bed..558109ba1ba 100644 --- a/railties/test/rails_info_controller_test.rb +++ b/railties/test/rails_info_controller_test.rb @@ -1,5 +1,6 @@ require 'abstract_unit' require 'action_controller' +require 'action_controller/test_case' require 'rails/info' require 'rails/info_controller'