mirror of https://github.com/rails/rails
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.
This commit is contained in:
parent
399909b11c
commit
c1304098cc
|
@ -25,32 +25,34 @@ actionpack_path = "#{File.dirname(__FILE__)}/../../actionpack/lib"
|
||||||
$:.unshift(actionpack_path) if File.directory?(actionpack_path)
|
$:.unshift(actionpack_path) if File.directory?(actionpack_path)
|
||||||
require 'action_controller'
|
require 'action_controller'
|
||||||
require 'action_view'
|
require 'action_view'
|
||||||
|
require 'active_support/autoload'
|
||||||
|
|
||||||
module ActionMailer
|
module ActionMailer
|
||||||
def self.load_all!
|
extend ::ActiveSupport::Autoload
|
||||||
[Base, Part, ::Text::Format, ::Net::SMTP]
|
|
||||||
end
|
|
||||||
|
|
||||||
autoload :AdvAttrAccessor, 'action_mailer/adv_attr_accessor'
|
autoload :AdvAttrAccessor
|
||||||
autoload :DeprecatedBody, 'action_mailer/deprecated_body'
|
autoload :DeprecatedBody
|
||||||
autoload :Base, 'action_mailer/base'
|
autoload :Base
|
||||||
autoload :DeliveryMethod, 'action_mailer/delivery_method'
|
autoload :DeliveryMethod
|
||||||
autoload :Part, 'action_mailer/part'
|
autoload :MailHelper
|
||||||
autoload :PartContainer, 'action_mailer/part_container'
|
autoload :Part
|
||||||
autoload :Quoting, 'action_mailer/quoting'
|
autoload :PartContainer
|
||||||
autoload :TestCase, 'action_mailer/test_case'
|
autoload :Quoting
|
||||||
autoload :TestHelper, 'action_mailer/test_helper'
|
autoload :TestHelper
|
||||||
autoload :Utils, 'action_mailer/utils'
|
autoload :Utils
|
||||||
end
|
end
|
||||||
|
|
||||||
module Text
|
module Text
|
||||||
|
extend ActiveSupport::Autoload
|
||||||
|
|
||||||
autoload :Format, 'action_mailer/vendor/text_format'
|
autoload :Format, 'action_mailer/vendor/text_format'
|
||||||
end
|
end
|
||||||
|
|
||||||
module Net
|
module Net
|
||||||
autoload :SMTP, 'net/smtp'
|
extend ActiveSupport::Autoload
|
||||||
|
|
||||||
|
autoload :SMTP
|
||||||
end
|
end
|
||||||
|
|
||||||
autoload :MailHelper, 'action_mailer/mail_helper'
|
|
||||||
|
|
||||||
require 'action_mailer/vendor/tmail'
|
require 'action_mailer/vendor/tmail'
|
||||||
|
|
|
@ -258,7 +258,7 @@ module ActionMailer #:nodoc:
|
||||||
include AbstractController::Layouts
|
include AbstractController::Layouts
|
||||||
|
|
||||||
include AbstractController::Helpers
|
include AbstractController::Helpers
|
||||||
helper MailHelper
|
helper ActionMailer::MailHelper
|
||||||
|
|
||||||
if Object.const_defined?(:ActionController)
|
if Object.const_defined?(:ActionController)
|
||||||
include ActionController::UrlWriter
|
include ActionController::UrlWriter
|
||||||
|
|
|
@ -6,7 +6,7 @@ module ActionMailer
|
||||||
# A delivery method implementation which writes all mails to a file.
|
# A delivery method implementation which writes all mails to a file.
|
||||||
class File < Method
|
class File < Method
|
||||||
self.settings = {
|
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)
|
def perform_delivery(mail)
|
||||||
|
|
|
@ -1,17 +1,19 @@
|
||||||
module MailHelper
|
module ActionMailer
|
||||||
# Uses Text::Format to take the text and format it, indented two spaces for
|
module MailHelper
|
||||||
# each line, and wrapped at 72 columns.
|
# Uses Text::Format to take the text and format it, indented two spaces for
|
||||||
def block_format(text)
|
# each line, and wrapped at 72 columns.
|
||||||
formatted = text.split(/\n\r\n/).collect { |paragraph|
|
def block_format(text)
|
||||||
Text::Format.new(
|
formatted = text.split(/\n\r\n/).collect { |paragraph|
|
||||||
:columns => 72, :first_indent => 2, :body_indent => 2, :text => paragraph
|
Text::Format.new(
|
||||||
).format
|
:columns => 72, :first_indent => 2, :body_indent => 2, :text => paragraph
|
||||||
}.join("\n")
|
).format
|
||||||
|
}.join("\n")
|
||||||
|
|
||||||
# Make list points stand on their own line
|
# Make list points stand on their own line
|
||||||
formatted.gsub!(/[ ]*([*]+) ([^*]*)/) { |s| " #{$1} #{$2.strip}\n" }
|
formatted.gsub!(/[ ]*([*]+) ([^*]*)/) { |s| " #{$1} #{$2.strip}\n" }
|
||||||
formatted.gsub!(/[ ]*([#]+) ([^#]*)/) { |s| " #{$1} #{$2.strip}\n" }
|
formatted.gsub!(/[ ]*([#]+) ([^#]*)/) { |s| " #{$1} #{$2.strip}\n" }
|
||||||
|
|
||||||
formatted
|
formatted
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
|
@ -2,15 +2,20 @@ require "active_support/core_ext/module/attr_internal"
|
||||||
require "active_support/core_ext/module/delegation"
|
require "active_support/core_ext/module/delegation"
|
||||||
|
|
||||||
module AbstractController
|
module AbstractController
|
||||||
autoload :Base, "abstract_controller/base"
|
extend ActiveSupport::Autoload
|
||||||
autoload :Callbacks, "abstract_controller/callbacks"
|
|
||||||
autoload :Helpers, "abstract_controller/helpers"
|
autoload :Base
|
||||||
autoload :Layouts, "abstract_controller/layouts"
|
autoload :Callbacks
|
||||||
autoload :LocalizedCache, "abstract_controller/localized_cache"
|
autoload :Helpers
|
||||||
autoload :Logger, "abstract_controller/logger"
|
autoload :Layouts
|
||||||
autoload :RenderingController, "abstract_controller/rendering_controller"
|
autoload :LocalizedCache
|
||||||
|
autoload :Logger
|
||||||
|
autoload :RenderingController
|
||||||
|
|
||||||
# === Exceptions
|
# === Exceptions
|
||||||
autoload :ActionNotFound, "abstract_controller/exceptions"
|
autoload_at "abstract_controller/exceptions" do
|
||||||
autoload :DoubleRenderError, "abstract_controller/exceptions"
|
autoload :ActionNotFound
|
||||||
autoload :Error, "abstract_controller/exceptions"
|
autoload :DoubleRenderError
|
||||||
|
autoload :Error
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -115,7 +115,7 @@ module AbstractController
|
||||||
# _partial<TrueClass, FalseClass>:: Whether or not the file to look up is a partial
|
# _partial<TrueClass, FalseClass>:: Whether or not the file to look up is a partial
|
||||||
def _determine_template(options)
|
def _determine_template(options)
|
||||||
if options.key?(:text)
|
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)
|
elsif options.key?(:inline)
|
||||||
handler = ActionView::Template.handler_class_for_extension(options[:type] || "erb")
|
handler = ActionView::Template.handler_class_for_extension(options[:type] || "erb")
|
||||||
template = ActionView::Template.new(options[:inline], "inline #{options[:inline].inspect}", handler, {})
|
template = ActionView::Template.new(options[:inline], "inline #{options[:inline].inspect}", handler, {})
|
||||||
|
|
|
@ -1,66 +1,72 @@
|
||||||
|
require "active_support"
|
||||||
|
|
||||||
module ActionController
|
module ActionController
|
||||||
autoload :Base, "action_controller/base"
|
extend ActiveSupport::Autoload
|
||||||
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"
|
|
||||||
|
|
||||||
autoload :Caching, 'action_controller/caching'
|
autoload :Base
|
||||||
autoload :Dispatcher, 'action_controller/dispatch/dispatcher'
|
autoload :Caching
|
||||||
autoload :Integration, 'action_controller/deprecated/integration_test'
|
autoload :PolymorphicRoutes
|
||||||
autoload :IntegrationTest, 'action_controller/deprecated/integration_test'
|
autoload :RecordIdentifier
|
||||||
autoload :MimeResponds, 'action_controller/metal/mime_responds'
|
autoload :UrlRewriter
|
||||||
autoload :PerformanceTest, 'action_controller/deprecated/performance_test'
|
autoload :Translation
|
||||||
autoload :PolymorphicRoutes, 'action_controller/polymorphic_routes'
|
autoload :Metal
|
||||||
autoload :RecordIdentifier, 'action_controller/record_identifier'
|
autoload :Middleware
|
||||||
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 :Verification, 'action_controller/metal/verification'
|
autoload_under "metal" do
|
||||||
autoload :Flash, 'action_controller/metal/flash'
|
autoload :Benchmarking
|
||||||
autoload :RequestForgeryProtection, 'action_controller/metal/request_forgery_protection'
|
autoload :ConditionalGet
|
||||||
autoload :Streaming, 'action_controller/metal/streaming'
|
autoload :Configuration
|
||||||
autoload :HttpAuthentication, 'action_controller/metal/http_authentication'
|
autoload :Head
|
||||||
autoload :FilterParameterLogging, 'action_controller/metal/filter_parameter_logging'
|
autoload :Helpers
|
||||||
autoload :Translation, 'action_controller/translation'
|
autoload :HideActions
|
||||||
autoload :Cookies, 'action_controller/metal/cookies'
|
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 :Dispatcher, 'action_controller/dispatch/dispatcher'
|
||||||
autoload :RenderError, 'action_controller/metal/exceptions'
|
autoload :PerformanceTest, 'action_controller/deprecated/performance_test'
|
||||||
autoload :RoutingError, 'action_controller/metal/exceptions'
|
autoload :Routing, 'action_controller/deprecated'
|
||||||
autoload :MethodNotAllowed, 'action_controller/metal/exceptions'
|
autoload :Integration, 'action_controller/deprecated/integration_test'
|
||||||
autoload :NotImplemented, 'action_controller/metal/exceptions'
|
autoload :IntegrationTest, 'action_controller/deprecated/integration_test'
|
||||||
autoload :UnknownController, 'action_controller/metal/exceptions'
|
|
||||||
autoload :MissingFile, 'action_controller/metal/exceptions'
|
autoload :UrlWriter, 'action_controller/url_rewriter'
|
||||||
autoload :RenderError, 'action_controller/metal/exceptions'
|
|
||||||
autoload :SessionOverflowError, 'action_controller/metal/exceptions'
|
autoload_at "action_controller/metal/exceptions" do
|
||||||
autoload :UnknownHttpMethod, 'action_controller/metal/exceptions'
|
autoload :ActionControllerError
|
||||||
|
autoload :RenderError
|
||||||
|
autoload :RoutingError
|
||||||
|
autoload :MethodNotAllowed
|
||||||
|
autoload :NotImplemented
|
||||||
|
autoload :UnknownController
|
||||||
|
autoload :MissingFile
|
||||||
|
autoload :RenderError
|
||||||
|
autoload :SessionOverflowError
|
||||||
|
autoload :UnknownHttpMethod
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
autoload :HTML, 'action_controller/vendor/html-scanner'
|
# All of these simply register additional autoloads
|
||||||
autoload :AbstractController, 'abstract_controller'
|
require 'abstract_controller'
|
||||||
|
|
||||||
require 'action_dispatch'
|
require 'action_dispatch'
|
||||||
require 'action_view'
|
require 'action_view'
|
||||||
|
require 'action_controller/vendor/html-scanner'
|
||||||
|
|
||||||
# Common ActiveSupport usage in ActionController
|
# Common ActiveSupport usage in ActionController
|
||||||
require "active_support/concern"
|
require "active_support/concern"
|
||||||
|
|
|
@ -24,7 +24,7 @@ module ActionController
|
||||||
include ActionController::MimeResponds
|
include ActionController::MimeResponds
|
||||||
|
|
||||||
# Rails 2.x compatibility
|
# Rails 2.x compatibility
|
||||||
include ActionController::Rails2Compatibility
|
include ActionController::Compatibility
|
||||||
|
|
||||||
include ActionController::Cookies
|
include ActionController::Cookies
|
||||||
include ActionController::Session
|
include ActionController::Session
|
||||||
|
|
|
@ -30,10 +30,11 @@ module ActionController #:nodoc:
|
||||||
# config.action_controller.cache_store = MyOwnStore.new("parameter")
|
# config.action_controller.cache_store = MyOwnStore.new("parameter")
|
||||||
module Caching
|
module Caching
|
||||||
extend ActiveSupport::Concern
|
extend ActiveSupport::Concern
|
||||||
|
extend ActiveSupport::Autoload
|
||||||
|
|
||||||
autoload :Actions, 'action_controller/caching/actions'
|
autoload :Actions
|
||||||
autoload :Fragments, 'action_controller/caching/fragments'
|
autoload :Fragments
|
||||||
autoload :Pages, 'action_controller/caching/pages'
|
autoload :Pages
|
||||||
autoload :Sweeper, 'action_controller/caching/sweeping'
|
autoload :Sweeper, 'action_controller/caching/sweeping'
|
||||||
autoload :Sweeping, 'action_controller/caching/sweeping'
|
autoload :Sweeping, 'action_controller/caching/sweeping'
|
||||||
|
|
||||||
|
|
|
@ -1,2 +1,4 @@
|
||||||
|
require "action_dispatch/testing/integration"
|
||||||
|
|
||||||
ActionController::Integration = ActionDispatch::Integration
|
ActionController::Integration = ActionDispatch::Integration
|
||||||
ActionController::IntegrationTest = ActionDispatch::IntegrationTest
|
ActionController::IntegrationTest = ActionDispatch::IntegrationTest
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
module ActionController
|
module ActionController
|
||||||
module Rails2Compatibility
|
module Compatibility
|
||||||
extend ActiveSupport::Concern
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
class ::ActionController::ActionControllerError < StandardError #:nodoc:
|
class ::ActionController::ActionControllerError < StandardError #:nodoc:
|
||||||
|
|
|
@ -52,7 +52,7 @@ module ActionController
|
||||||
included do
|
included do
|
||||||
# Set the default directory for helpers
|
# Set the default directory for helpers
|
||||||
extlib_inheritable_accessor(:helpers_dir) do
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
require 'active_support/test_case'
|
require 'active_support/test_case'
|
||||||
require 'rack/session/abstract/id'
|
require 'rack/session/abstract/id'
|
||||||
|
require 'action_controller/metal/testing'
|
||||||
|
require 'action_controller/testing/process'
|
||||||
|
require 'action_dispatch/test_case'
|
||||||
|
|
||||||
module ActionController
|
module ActionController
|
||||||
class TestRequest < ActionDispatch::TestRequest #:nodoc:
|
class TestRequest < ActionDispatch::TestRequest #:nodoc:
|
|
@ -1,6 +1,8 @@
|
||||||
$LOAD_PATH << "#{File.dirname(__FILE__)}/html-scanner"
|
$LOAD_PATH << "#{File.dirname(__FILE__)}/html-scanner"
|
||||||
|
|
||||||
module HTML
|
module HTML
|
||||||
|
extend ActiveSupport::Autoload
|
||||||
|
|
||||||
autoload :CDATA, 'html/node'
|
autoload :CDATA, 'html/node'
|
||||||
autoload :Document, 'html/document'
|
autoload :Document, 'html/document'
|
||||||
autoload :FullSanitizer, 'html/sanitizer'
|
autoload :FullSanitizer, 'html/sanitizer'
|
||||||
|
|
|
@ -28,37 +28,38 @@ module Rack
|
||||||
end
|
end
|
||||||
|
|
||||||
module ActionDispatch
|
module ActionDispatch
|
||||||
autoload :Request, 'action_dispatch/http/request'
|
extend ActiveSupport::Autoload
|
||||||
autoload :Response, 'action_dispatch/http/response'
|
|
||||||
autoload :StatusCodes, 'action_dispatch/http/status_codes'
|
autoload_under "http" do
|
||||||
autoload :Utils, 'action_dispatch/http/utils'
|
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 :MiddlewareStack, 'action_dispatch/middleware/stack'
|
||||||
autoload :ParamsParser, 'action_dispatch/middleware/params_parser'
|
autoload :Routing
|
||||||
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 :HTML, 'action_controller/vendor/html-scanner'
|
autoload :HTML, 'action_controller/vendor/html-scanner'
|
||||||
|
|
||||||
module Http
|
module Http
|
||||||
autoload :Headers, 'action_dispatch/http/headers'
|
extend ActiveSupport::Autoload
|
||||||
|
|
||||||
|
autoload :Headers
|
||||||
end
|
end
|
||||||
|
|
||||||
module Session
|
module Session
|
||||||
autoload :AbstractStore, 'action_dispatch/middleware/session/abstract_store'
|
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'
|
autoload :MemCacheStore, 'action_dispatch/middleware/session/mem_cache_store'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -29,7 +29,7 @@ module ActionDispatch
|
||||||
'ActionView::MissingTemplate' => 'missing_template',
|
'ActionView::MissingTemplate' => 'missing_template',
|
||||||
'ActionController::RoutingError' => 'routing_error',
|
'ActionController::RoutingError' => 'routing_error',
|
||||||
ActionController::UnknownAction.name => 'unknown_action',
|
ActionController::UnknownAction.name => 'unknown_action',
|
||||||
'ActionView::TemplateError' => 'template_error'
|
'ActionView::Template::Error' => 'template_error'
|
||||||
})
|
})
|
||||||
|
|
||||||
FAILSAFE_RESPONSE = [500, {'Content-Type' => 'text/html'},
|
FAILSAFE_RESPONSE = [500, {'Content-Type' => 'text/html'},
|
||||||
|
@ -119,7 +119,7 @@ module ActionDispatch
|
||||||
return unless logger
|
return unless logger
|
||||||
|
|
||||||
ActiveSupport::Deprecation.silence do
|
ActiveSupport::Deprecation.silence do
|
||||||
if ActionView::TemplateError === exception
|
if ActionView::Template::Error === exception
|
||||||
logger.fatal(exception.to_s)
|
logger.fatal(exception.to_s)
|
||||||
else
|
else
|
||||||
logger.fatal(
|
logger.fatal(
|
||||||
|
|
|
@ -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"
|
|
@ -24,27 +24,25 @@
|
||||||
require File.join(File.dirname(__FILE__), "action_pack")
|
require File.join(File.dirname(__FILE__), "action_pack")
|
||||||
|
|
||||||
module ActionView
|
module ActionView
|
||||||
def self.load_all!
|
extend ActiveSupport::Autoload
|
||||||
[Context, Base, TemplateError]
|
|
||||||
|
autoload :Base
|
||||||
|
autoload :Context
|
||||||
|
autoload :Template
|
||||||
|
autoload :Helpers
|
||||||
|
autoload :SafeBuffer
|
||||||
|
|
||||||
|
|
||||||
|
autoload_under "render" do
|
||||||
|
autoload :Partials
|
||||||
|
autoload :Rendering
|
||||||
end
|
end
|
||||||
|
|
||||||
autoload :Base, 'action_view/base'
|
|
||||||
autoload :Context, 'action_view/context'
|
|
||||||
autoload :Helpers, 'action_view/helpers'
|
|
||||||
autoload :MissingTemplate, 'action_view/base'
|
autoload :MissingTemplate, 'action_view/base'
|
||||||
autoload :Partials, 'action_view/render/partials'
|
|
||||||
autoload :Resolver, 'action_view/template/resolver'
|
autoload :Resolver, 'action_view/template/resolver'
|
||||||
autoload :PathResolver, 'action_view/template/resolver'
|
autoload :PathResolver, 'action_view/template/resolver'
|
||||||
autoload :PathSet, 'action_view/paths'
|
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 :FileSystemResolverWithFallback, 'action_view/template/resolver'
|
||||||
autoload :SafeBuffer, 'action_view/safe_buffer'
|
|
||||||
end
|
end
|
||||||
|
|
||||||
require 'action_view/erb/util'
|
require 'action_view/erb/util'
|
||||||
|
|
|
@ -196,7 +196,7 @@ module ActionView #:nodoc:
|
||||||
end
|
end
|
||||||
|
|
||||||
class << self
|
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
|
delegate :logger, :to => 'ActionController::Base', :allow_nil => true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ module ActionView #:nodoc:
|
||||||
# TODO: Clean this up
|
# TODO: Clean this up
|
||||||
if obj.is_a?(String)
|
if obj.is_a?(String)
|
||||||
if cache.nil?
|
if cache.nil?
|
||||||
cache = !defined?(Rails) || Rails.application.config.cache_classes
|
cache = !defined?(Rails.application) || Rails.application.config.cache_classes
|
||||||
end
|
end
|
||||||
FileSystemResolverWithFallback.new(obj, :cache => cache)
|
FileSystemResolverWithFallback.new(obj, :cache => cache)
|
||||||
else
|
else
|
||||||
|
|
|
@ -6,7 +6,14 @@ require "action_view/template/resolver"
|
||||||
|
|
||||||
module ActionView
|
module ActionView
|
||||||
class Template
|
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
|
attr_reader :source, :identifier, :handler, :mime_type, :formats, :details
|
||||||
|
|
||||||
def initialize(source, identifier, handler, details)
|
def initialize(source, identifier, handler, details)
|
||||||
|
@ -32,11 +39,11 @@ module ActionView
|
||||||
view.send(method_name, locals, &block)
|
view.send(method_name, locals, &block)
|
||||||
end
|
end
|
||||||
rescue Exception => e
|
rescue Exception => e
|
||||||
if e.is_a?(TemplateError)
|
if e.is_a?(Template::Error)
|
||||||
e.sub_template_of(self)
|
e.sub_template_of(self)
|
||||||
raise e
|
raise e
|
||||||
else
|
else
|
||||||
raise TemplateError.new(self, view.assigns, e)
|
raise Template::Error.new(self, view.assigns, e)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -103,7 +110,7 @@ module ActionView
|
||||||
logger.debug "Backtrace: #{e.backtrace.join("\n")}"
|
logger.debug "Backtrace: #{e.backtrace.join("\n")}"
|
||||||
end
|
end
|
||||||
|
|
||||||
raise ActionView::TemplateError.new(self, {}, e)
|
raise ActionView::Template::Error.new(self, {}, e)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,101 +1,103 @@
|
||||||
require "active_support/core_ext/enumerable"
|
require "active_support/core_ext/enumerable"
|
||||||
|
|
||||||
module ActionView
|
module ActionView
|
||||||
# The TemplateError exception is raised when the compilation of the template fails. This exception then gathers a
|
class Template
|
||||||
# bunch of intimate details and uses it to report a very precise exception message.
|
# The Template::Error exception is raised when the compilation of the template fails. This exception then gathers a
|
||||||
class TemplateError < ActionViewError #:nodoc:
|
# bunch of intimate details and uses it to report a very precise exception message.
|
||||||
SOURCE_CODE_RADIUS = 3
|
class Error < ActionViewError #:nodoc:
|
||||||
|
SOURCE_CODE_RADIUS = 3
|
||||||
|
|
||||||
attr_reader :original_exception
|
attr_reader :original_exception
|
||||||
|
|
||||||
def initialize(template, assigns, original_exception)
|
def initialize(template, assigns, original_exception)
|
||||||
@template, @assigns, @original_exception = template, assigns.dup, original_exception
|
@template, @assigns, @original_exception = template, assigns.dup, original_exception
|
||||||
@backtrace = compute_backtrace
|
@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
|
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
def sub_template_message
|
def file_name
|
||||||
if @sub_templates
|
@template.identifier
|
||||||
"Trace of template inclusion: " +
|
|
||||||
@sub_templates.collect { |template| template.inspect }.join(", ")
|
|
||||||
else
|
|
||||||
""
|
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
def source_extract(indentation = 0)
|
def message
|
||||||
return unless num = line_number
|
ActiveSupport::Deprecation.silence { original_exception.message }
|
||||||
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
|
||||||
end
|
|
||||||
|
|
||||||
def sub_template_of(template_path)
|
def clean_backtrace
|
||||||
@sub_templates ||= []
|
if defined?(Rails) && Rails.respond_to?(:backtrace_cleaner)
|
||||||
@sub_templates << template_path
|
Rails.backtrace_cleaner.clean(original_exception.backtrace)
|
||||||
end
|
else
|
||||||
|
original_exception.backtrace
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def line_number
|
def sub_template_message
|
||||||
@line_number ||=
|
if @sub_templates
|
||||||
if file_name
|
"Trace of template inclusion: " +
|
||||||
regexp = /#{Regexp.escape File.basename(file_name)}:(\d+)/
|
@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
|
||||||
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
|
||||||
end
|
end
|
|
@ -3,34 +3,39 @@ require "action_dispatch/http/mime_type"
|
||||||
|
|
||||||
# Legacy TemplateHandler stub
|
# Legacy TemplateHandler stub
|
||||||
module ActionView
|
module ActionView
|
||||||
module TemplateHandlers #:nodoc:
|
class Template
|
||||||
module Compilable
|
module Handlers #:nodoc:
|
||||||
def self.included(base)
|
module Compilable
|
||||||
base.extend(ClassMethods)
|
def self.included(base)
|
||||||
end
|
base.extend(ClassMethods)
|
||||||
|
|
||||||
module ClassMethods
|
|
||||||
def call(template)
|
|
||||||
new.compile(template)
|
|
||||||
end
|
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
|
end
|
||||||
|
|
||||||
def compile(template)
|
def render(template, local_assigns)
|
||||||
raise "Need to implement #{self.class.name}#compile(template)"
|
raise "Need to implement #{self.class.name}#render(template, local_assigns)"
|
||||||
end
|
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)"
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
TemplateHandlers = Template::Handlers
|
||||||
|
TemplateHandler = Template::Handler
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,52 +1,54 @@
|
||||||
module ActionView #:nodoc:
|
module ActionView #:nodoc:
|
||||||
module TemplateHandlers #:nodoc:
|
class Template
|
||||||
autoload :ERB, 'action_view/template/handlers/erb'
|
module Handlers #:nodoc:
|
||||||
autoload :RJS, 'action_view/template/handlers/rjs'
|
autoload :ERB, 'action_view/template/handlers/erb'
|
||||||
autoload :Builder, 'action_view/template/handlers/builder'
|
autoload :RJS, 'action_view/template/handlers/rjs'
|
||||||
|
autoload :Builder, 'action_view/template/handlers/builder'
|
||||||
|
|
||||||
def self.extended(base)
|
def self.extended(base)
|
||||||
base.register_default_template_handler :erb, TemplateHandlers::ERB
|
base.register_default_template_handler :erb, ERB
|
||||||
base.register_template_handler :rjs, TemplateHandlers::RJS
|
base.register_template_handler :rjs, RJS
|
||||||
base.register_template_handler :builder, TemplateHandlers::Builder
|
base.register_template_handler :builder, Builder
|
||||||
|
|
||||||
# TODO: Depreciate old template extensions
|
# TODO: Depreciate old template extensions
|
||||||
base.register_template_handler :rhtml, TemplateHandlers::ERB
|
base.register_template_handler :rhtml, ERB
|
||||||
base.register_template_handler :rxml, TemplateHandlers::Builder
|
base.register_template_handler :rxml, Builder
|
||||||
end
|
end
|
||||||
|
|
||||||
@@template_handlers = {}
|
@@template_handlers = {}
|
||||||
@@default_template_handlers = nil
|
@@default_template_handlers = nil
|
||||||
|
|
||||||
def self.extensions
|
def self.extensions
|
||||||
@@template_handlers.keys
|
@@template_handlers.keys
|
||||||
end
|
end
|
||||||
|
|
||||||
# Register a class that knows how to handle template files with the given
|
# Register a class that knows how to handle template files with the given
|
||||||
# extension. This can be used to implement new template types.
|
# extension. This can be used to implement new template types.
|
||||||
# The constructor for the class must take the ActiveView::Base instance
|
# The constructor for the class must take the ActiveView::Base instance
|
||||||
# as a parameter, and the class must implement a +render+ method that
|
# 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
|
# 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
|
# local assigns available to the template. The +render+ method ought to
|
||||||
# return the rendered template as a string.
|
# return the rendered template as a string.
|
||||||
def register_template_handler(extension, klass)
|
def register_template_handler(extension, klass)
|
||||||
@@template_handlers[extension.to_sym] = klass
|
@@template_handlers[extension.to_sym] = klass
|
||||||
end
|
end
|
||||||
|
|
||||||
def template_handler_extensions
|
def template_handler_extensions
|
||||||
@@template_handlers.keys.map {|key| key.to_s }.sort
|
@@template_handlers.keys.map {|key| key.to_s }.sort
|
||||||
end
|
end
|
||||||
|
|
||||||
def registered_template_handler(extension)
|
def registered_template_handler(extension)
|
||||||
extension && @@template_handlers[extension.to_sym]
|
extension && @@template_handlers[extension.to_sym]
|
||||||
end
|
end
|
||||||
|
|
||||||
def register_default_template_handler(extension, klass)
|
def register_default_template_handler(extension, klass)
|
||||||
register_template_handler(extension, klass)
|
register_template_handler(extension, klass)
|
||||||
@@default_template_handlers = klass
|
@@default_template_handlers = klass
|
||||||
end
|
end
|
||||||
|
|
||||||
def handler_class_for_extension(extension)
|
def handler_class_for_extension(extension)
|
||||||
(extension && registered_template_handler(extension.to_sym)) || @@default_template_handlers
|
(extension && registered_template_handler(extension.to_sym)) || @@default_template_handlers
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
module ActionView
|
module ActionView
|
||||||
module TemplateHandlers
|
module Template::Handlers
|
||||||
class Builder < TemplateHandler
|
class Builder < Template::Handler
|
||||||
include Compilable
|
include Compilable
|
||||||
|
|
||||||
self.default_format = Mime::XML
|
self.default_format = Mime::XML
|
||||||
|
|
|
@ -3,7 +3,7 @@ require 'active_support/core_ext/string/output_safety'
|
||||||
require 'erubis'
|
require 'erubis'
|
||||||
|
|
||||||
module ActionView
|
module ActionView
|
||||||
module TemplateHandlers
|
module Template::Handlers
|
||||||
class Erubis < ::Erubis::Eruby
|
class Erubis < ::Erubis::Eruby
|
||||||
def add_preamble(src)
|
def add_preamble(src)
|
||||||
src << "@output_buffer = ActionView::SafeBuffer.new;"
|
src << "@output_buffer = ActionView::SafeBuffer.new;"
|
||||||
|
@ -26,7 +26,7 @@ module ActionView
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class ERB < TemplateHandler
|
class ERB < Template::Handler
|
||||||
include Compilable
|
include Compilable
|
||||||
|
|
||||||
##
|
##
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
module ActionView
|
module ActionView
|
||||||
module TemplateHandlers
|
module Template::Handlers
|
||||||
class RJS < TemplateHandler
|
class RJS < Template::Handler
|
||||||
include Compilable
|
include Compilable
|
||||||
|
|
||||||
self.default_format = Mime::JS
|
self.default_format = Mime::JS
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
require "pathname"
|
require "pathname"
|
||||||
require "active_support/core_ext/class"
|
require "active_support/core_ext/class"
|
||||||
require "action_view/template/template"
|
require "action_view/template"
|
||||||
|
|
||||||
module ActionView
|
module ActionView
|
||||||
# Abstract superclass
|
# Abstract superclass
|
||||||
|
@ -20,7 +20,7 @@ module ActionView
|
||||||
register_detail(:locale) { [I18n.locale] }
|
register_detail(:locale) { [I18n.locale] }
|
||||||
register_detail(:formats) { Mime::SET.symbols }
|
register_detail(:formats) { Mime::SET.symbols }
|
||||||
register_detail(:handlers, :allow_nil => false) do
|
register_detail(:handlers, :allow_nil => false) do
|
||||||
TemplateHandlers.extensions
|
Template::Handlers.extensions
|
||||||
end
|
end
|
||||||
|
|
||||||
def initialize(options = {})
|
def initialize(options = {})
|
||||||
|
@ -65,7 +65,7 @@ module ActionView
|
||||||
# as well as incorrectly putting part of the path in the template
|
# as well as incorrectly putting part of the path in the template
|
||||||
# name instead of the prefix.
|
# name instead of the prefix.
|
||||||
def normalize_name(name, prefix)
|
def normalize_name(name, prefix)
|
||||||
handlers = TemplateHandlers.extensions.join('|')
|
handlers = Template::Handlers.extensions.join('|')
|
||||||
name = name.to_s.gsub(/\.(?:#{handlers})$/, '')
|
name = name.to_s.gsub(/\.(?:#{handlers})$/, '')
|
||||||
|
|
||||||
parts = name.split('/')
|
parts = name.split('/')
|
||||||
|
|
|
@ -1,38 +1,40 @@
|
||||||
module ActionView #:nodoc:
|
module ActionView #:nodoc:
|
||||||
class TextTemplate < String #:nodoc:
|
class Template
|
||||||
HTML = Mime[:html]
|
class Text < String #:nodoc:
|
||||||
|
HTML = Mime[:html]
|
||||||
|
|
||||||
def initialize(string, content_type = HTML)
|
def initialize(string, content_type = HTML)
|
||||||
super(string.to_s)
|
super(string.to_s)
|
||||||
@content_type = Mime[content_type] || content_type
|
@content_type = Mime[content_type] || content_type
|
||||||
end
|
end
|
||||||
|
|
||||||
def details
|
def details
|
||||||
{:formats => [@content_type.to_sym]}
|
{:formats => [@content_type.to_sym]}
|
||||||
end
|
end
|
||||||
|
|
||||||
def identifier
|
def identifier
|
||||||
self
|
self
|
||||||
end
|
end
|
||||||
|
|
||||||
def inspect
|
def inspect
|
||||||
'text template'
|
'text template'
|
||||||
end
|
end
|
||||||
|
|
||||||
def render(*args)
|
def render(*args)
|
||||||
to_s
|
to_s
|
||||||
end
|
end
|
||||||
|
|
||||||
def mime_type
|
def mime_type
|
||||||
@content_type
|
@content_type
|
||||||
end
|
end
|
||||||
|
|
||||||
def formats
|
def formats
|
||||||
[mime_type]
|
[mime_type]
|
||||||
end
|
end
|
||||||
|
|
||||||
def partial?
|
def partial?
|
||||||
false
|
false
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
require 'active_support/test_case'
|
require 'active_support/test_case'
|
||||||
require 'action_controller/testing/test_case'
|
require 'action_controller/test_case'
|
||||||
|
|
||||||
module ActionView
|
module ActionView
|
||||||
class Base
|
class Base
|
||||||
|
|
|
@ -23,7 +23,7 @@ module AbstractControllerTests
|
||||||
self.view_paths = []
|
self.view_paths = []
|
||||||
|
|
||||||
def index
|
def index
|
||||||
render :_template => ActionView::TextTemplate.new("Hello blank!")
|
render :_template => ActionView::Template::Text.new("Hello blank!")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -31,19 +31,19 @@ module AbstractControllerTests
|
||||||
layout "hello"
|
layout "hello"
|
||||||
|
|
||||||
def index
|
def index
|
||||||
render :_template => ActionView::TextTemplate.new("Hello string!")
|
render :_template => ActionView::Template::Text.new("Hello string!")
|
||||||
end
|
end
|
||||||
|
|
||||||
def overwrite_default
|
def overwrite_default
|
||||||
render :_template => ActionView::TextTemplate.new("Hello string!"), :layout => :default
|
render :_template => ActionView::Template::Text.new("Hello string!"), :layout => :default
|
||||||
end
|
end
|
||||||
|
|
||||||
def overwrite_false
|
def overwrite_false
|
||||||
render :_template => ActionView::TextTemplate.new("Hello string!"), :layout => false
|
render :_template => ActionView::Template::Text.new("Hello string!"), :layout => false
|
||||||
end
|
end
|
||||||
|
|
||||||
def overwrite_string
|
def overwrite_string
|
||||||
render :_template => ActionView::TextTemplate.new("Hello string!"), :layout => "omg"
|
render :_template => ActionView::Template::Text.new("Hello string!"), :layout => "omg"
|
||||||
end
|
end
|
||||||
|
|
||||||
def overwrite_skip
|
def overwrite_skip
|
||||||
|
@ -72,7 +72,7 @@ module AbstractControllerTests
|
||||||
layout :hello
|
layout :hello
|
||||||
|
|
||||||
def index
|
def index
|
||||||
render :_template => ActionView::TextTemplate.new("Hello symbol!")
|
render :_template => ActionView::Template::Text.new("Hello symbol!")
|
||||||
end
|
end
|
||||||
private
|
private
|
||||||
def hello
|
def hello
|
||||||
|
@ -84,7 +84,7 @@ module AbstractControllerTests
|
||||||
layout :no_hello
|
layout :no_hello
|
||||||
|
|
||||||
def index
|
def index
|
||||||
render :_template => ActionView::TextTemplate.new("Hello missing symbol!")
|
render :_template => ActionView::Template::Text.new("Hello missing symbol!")
|
||||||
end
|
end
|
||||||
private
|
private
|
||||||
def no_hello
|
def no_hello
|
||||||
|
@ -96,7 +96,7 @@ module AbstractControllerTests
|
||||||
layout :nilz
|
layout :nilz
|
||||||
|
|
||||||
def index
|
def index
|
||||||
render :_template => ActionView::TextTemplate.new("Hello nilz!")
|
render :_template => ActionView::Template::Text.new("Hello nilz!")
|
||||||
end
|
end
|
||||||
|
|
||||||
def nilz() end
|
def nilz() end
|
||||||
|
@ -106,7 +106,7 @@ module AbstractControllerTests
|
||||||
layout :objekt
|
layout :objekt
|
||||||
|
|
||||||
def index
|
def index
|
||||||
render :_template => ActionView::TextTemplate.new("Hello nilz!")
|
render :_template => ActionView::Template::Text.new("Hello nilz!")
|
||||||
end
|
end
|
||||||
|
|
||||||
def objekt
|
def objekt
|
||||||
|
@ -118,7 +118,7 @@ module AbstractControllerTests
|
||||||
layout :omg_no_method
|
layout :omg_no_method
|
||||||
|
|
||||||
def index
|
def index
|
||||||
render :_template => ActionView::TextTemplate.new("Hello boom!")
|
render :_template => ActionView::Template::Text.new("Hello boom!")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -126,7 +126,7 @@ module AbstractControllerTests
|
||||||
layout "missing"
|
layout "missing"
|
||||||
|
|
||||||
def index
|
def index
|
||||||
render :_template => ActionView::TextTemplate.new("Hello missing!")
|
render :_template => ActionView::Template::Text.new("Hello missing!")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -134,7 +134,7 @@ module AbstractControllerTests
|
||||||
layout false
|
layout false
|
||||||
|
|
||||||
def index
|
def index
|
||||||
render :_template => ActionView::TextTemplate.new("Hello false!")
|
render :_template => ActionView::Template::Text.new("Hello false!")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -142,7 +142,7 @@ module AbstractControllerTests
|
||||||
layout nil
|
layout nil
|
||||||
|
|
||||||
def index
|
def index
|
||||||
render :_template => ActionView::TextTemplate.new("Hello nil!")
|
render :_template => ActionView::Template::Text.new("Hello nil!")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@ module AbstractController
|
||||||
end
|
end
|
||||||
|
|
||||||
def object
|
def object
|
||||||
render :_template => ActionView::TextTemplate.new("With Object")
|
render :_template => ActionView::Template::Text.new("With Object")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -191,7 +191,7 @@ class IsolatedHelpersTest < Test::Unit::TestCase
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_helper_in_a
|
def test_helper_in_a
|
||||||
assert_raise(ActionView::TemplateError) { call_controller(A, "index") }
|
assert_raise(ActionView::Template::Error) { call_controller(A, "index") }
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_helper_in_b
|
def test_helper_in_b
|
||||||
|
|
|
@ -115,7 +115,7 @@ class RendersNoLayoutController < LayoutTest
|
||||||
end
|
end
|
||||||
|
|
||||||
class LayoutSetInResponseTest < ActionController::TestCase
|
class LayoutSetInResponseTest < ActionController::TestCase
|
||||||
include ActionView::TemplateHandlers
|
include ActionView::Template::Handlers
|
||||||
|
|
||||||
def test_layout_set_when_using_default_layout
|
def test_layout_set_when_using_default_layout
|
||||||
@controller = DefaultLayoutController.new
|
@controller = DefaultLayoutController.new
|
||||||
|
|
|
@ -106,8 +106,8 @@ module RenderTestCases
|
||||||
|
|
||||||
def test_render_partial_with_errors
|
def test_render_partial_with_errors
|
||||||
@view.render(:partial => "test/raise")
|
@view.render(:partial => "test/raise")
|
||||||
flunk "Render did not raise TemplateError"
|
flunk "Render did not raise Template::Error"
|
||||||
rescue ActionView::TemplateError => e
|
rescue ActionView::Template::Error => e
|
||||||
assert_match "undefined local variable or method `doesnt_exist'", e.message
|
assert_match "undefined local variable or method `doesnt_exist'", e.message
|
||||||
assert_equal "", e.sub_template_message
|
assert_equal "", e.sub_template_message
|
||||||
assert_equal "1", e.line_number
|
assert_equal "1", e.line_number
|
||||||
|
@ -116,8 +116,8 @@ module RenderTestCases
|
||||||
|
|
||||||
def test_render_sub_template_with_errors
|
def test_render_sub_template_with_errors
|
||||||
@view.render(:file => "test/sub_template_raise")
|
@view.render(:file => "test/sub_template_raise")
|
||||||
flunk "Render did not raise TemplateError"
|
flunk "Render did not raise Template::Error"
|
||||||
rescue ActionView::TemplateError => e
|
rescue ActionView::Template::Error => e
|
||||||
assert_match "undefined local variable or method `doesnt_exist'", e.message
|
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 "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
|
assert_equal "1", e.line_number
|
||||||
|
|
|
@ -26,28 +26,31 @@ $:.unshift(activesupport_path) if File.directory?(activesupport_path)
|
||||||
require 'active_support'
|
require 'active_support'
|
||||||
|
|
||||||
module ActiveModel
|
module ActiveModel
|
||||||
autoload :AttributeMethods, 'active_model/attribute_methods'
|
extend ActiveSupport::Autoload
|
||||||
autoload :Conversion, 'active_model/conversion'
|
|
||||||
autoload :DeprecatedErrorMethods, 'active_model/deprecated_error_methods'
|
autoload :AttributeMethods
|
||||||
autoload :Dirty, 'active_model/dirty'
|
autoload :Conversion
|
||||||
autoload :Errors, 'active_model/errors'
|
autoload :DeprecatedErrorMethods
|
||||||
autoload :Lint, 'active_model/lint'
|
autoload :Dirty
|
||||||
autoload :Name, 'active_model/naming'
|
autoload :Errors
|
||||||
autoload :Naming, 'active_model/naming'
|
autoload :Lint
|
||||||
autoload :Observer, 'active_model/observing'
|
autoload :Name, 'active_model/naming'
|
||||||
autoload :Observing, 'active_model/observing'
|
autoload :Naming
|
||||||
autoload :Serialization, 'active_model/serialization'
|
autoload :Observer, 'active_model/observing'
|
||||||
autoload :StateMachine, 'active_model/state_machine'
|
autoload :Observing
|
||||||
autoload :TestCase, 'active_model/test_case'
|
autoload :Serialization
|
||||||
autoload :Translation, 'active_model/translation'
|
autoload :StateMachine
|
||||||
autoload :Validations, 'active_model/validations'
|
autoload :Translation
|
||||||
autoload :ValidationsRepairHelper, 'active_model/validations_repair_helper'
|
autoload :Validations
|
||||||
autoload :Validator, 'active_model/validator'
|
autoload :ValidationsRepairHelper
|
||||||
autoload :VERSION, 'active_model/version'
|
autoload :Validator
|
||||||
|
autoload :VERSION
|
||||||
|
|
||||||
module Serializers
|
module Serializers
|
||||||
autoload :JSON, 'active_model/serializers/json'
|
extend ActiveSupport::Autoload
|
||||||
autoload :Xml, 'active_model/serializers/xml'
|
|
||||||
|
autoload :JSON
|
||||||
|
autoload :Xml
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ $:.unshift(lib) unless $:.include?('lib') || $:.include?(lib)
|
||||||
|
|
||||||
require 'config'
|
require 'config'
|
||||||
require 'active_model'
|
require 'active_model'
|
||||||
|
require 'active_model/test_case'
|
||||||
|
|
||||||
# Show backtraces for deprecated behavior for quicker cleanup.
|
# Show backtraces for deprecated behavior for quicker cleanup.
|
||||||
ActiveSupport::Deprecation.debug = true
|
ActiveSupport::Deprecation.debug = true
|
||||||
|
|
|
@ -2,6 +2,7 @@ require 'logger'
|
||||||
|
|
||||||
$:.unshift(File.dirname(__FILE__) + '/../../../activerecord/lib')
|
$:.unshift(File.dirname(__FILE__) + '/../../../activerecord/lib')
|
||||||
require 'active_record'
|
require 'active_record'
|
||||||
|
require 'active_record/test_case'
|
||||||
require 'active_record/fixtures'
|
require 'active_record/fixtures'
|
||||||
|
|
||||||
module ActiveModel
|
module ActiveModel
|
||||||
|
|
|
@ -32,64 +32,66 @@ require 'active_model'
|
||||||
require 'arel'
|
require 'arel'
|
||||||
|
|
||||||
module ActiveRecord
|
module ActiveRecord
|
||||||
# TODO: Review explicit loads to see if they will automatically be handled by the initializer.
|
extend ActiveSupport::Autoload
|
||||||
def self.load_all!
|
|
||||||
[Base, DynamicFinderMatch, ConnectionAdapters::AbstractAdapter]
|
|
||||||
end
|
|
||||||
|
|
||||||
autoload :VERSION, 'active_record/version'
|
autoload :VERSION
|
||||||
|
|
||||||
autoload :ActiveRecordError, 'active_record/base'
|
autoload :ActiveRecordError, 'active_record/base'
|
||||||
autoload :ConnectionNotEstablished, 'active_record/base'
|
autoload :ConnectionNotEstablished, 'active_record/base'
|
||||||
|
|
||||||
autoload :Aggregations, 'active_record/aggregations'
|
autoload :Aggregations
|
||||||
autoload :AssociationPreload, 'active_record/association_preload'
|
autoload :AssociationPreload
|
||||||
autoload :Associations, 'active_record/associations'
|
autoload :Associations
|
||||||
autoload :AttributeMethods, 'active_record/attribute_methods'
|
autoload :AttributeMethods
|
||||||
autoload :Attributes, 'active_record/attributes'
|
autoload :Attributes
|
||||||
autoload :AutosaveAssociation, 'active_record/autosave_association'
|
autoload :AutosaveAssociation
|
||||||
autoload :Relation, 'active_record/relation'
|
autoload :Relation
|
||||||
autoload :Base, 'active_record/base'
|
autoload :Base
|
||||||
autoload :Batches, 'active_record/batches'
|
autoload :Batches
|
||||||
autoload :Calculations, 'active_record/calculations'
|
autoload :Calculations
|
||||||
autoload :Callbacks, 'active_record/callbacks'
|
autoload :Callbacks
|
||||||
autoload :DynamicFinderMatch, 'active_record/dynamic_finder_match'
|
autoload :DynamicFinderMatch
|
||||||
autoload :DynamicScopeMatch, 'active_record/dynamic_scope_match'
|
autoload :DynamicScopeMatch
|
||||||
autoload :Migration, 'active_record/migration'
|
autoload :Migration
|
||||||
autoload :Migrator, 'active_record/migration'
|
autoload :Migrator, 'active_record/migration'
|
||||||
autoload :NamedScope, 'active_record/named_scope'
|
autoload :NamedScope
|
||||||
autoload :NestedAttributes, 'active_record/nested_attributes'
|
autoload :NestedAttributes
|
||||||
autoload :Observer, 'active_record/observer'
|
autoload :Observer
|
||||||
autoload :QueryCache, 'active_record/query_cache'
|
autoload :QueryCache
|
||||||
autoload :Reflection, 'active_record/reflection'
|
autoload :Reflection
|
||||||
autoload :Schema, 'active_record/schema'
|
autoload :Schema
|
||||||
autoload :SchemaDumper, 'active_record/schema_dumper'
|
autoload :SchemaDumper
|
||||||
autoload :Serialization, 'active_record/serialization'
|
autoload :Serialization
|
||||||
autoload :SessionStore, 'active_record/session_store'
|
autoload :SessionStore
|
||||||
autoload :StateMachine, 'active_record/state_machine'
|
autoload :StateMachine
|
||||||
autoload :TestCase, 'active_record/test_case'
|
autoload :Timestamp
|
||||||
autoload :Timestamp, 'active_record/timestamp'
|
autoload :Transactions
|
||||||
autoload :Transactions, 'active_record/transactions'
|
autoload :Types
|
||||||
autoload :Types, 'active_record/types'
|
autoload :Validations
|
||||||
autoload :Validations, 'active_record/validations'
|
|
||||||
|
|
||||||
module AttributeMethods
|
module AttributeMethods
|
||||||
autoload :BeforeTypeCast, 'active_record/attribute_methods/before_type_cast'
|
extend ActiveSupport::Autoload
|
||||||
autoload :Dirty, 'active_record/attribute_methods/dirty'
|
|
||||||
autoload :PrimaryKey, 'active_record/attribute_methods/primary_key'
|
autoload :BeforeTypeCast
|
||||||
autoload :Query, 'active_record/attribute_methods/query'
|
autoload :Dirty
|
||||||
autoload :Read, 'active_record/attribute_methods/read'
|
autoload :PrimaryKey
|
||||||
autoload :TimeZoneConversion, 'active_record/attribute_methods/time_zone_conversion'
|
autoload :Query
|
||||||
autoload :Write, 'active_record/attribute_methods/write'
|
autoload :Read
|
||||||
|
autoload :TimeZoneConversion
|
||||||
|
autoload :Write
|
||||||
end
|
end
|
||||||
|
|
||||||
module Attributes
|
module Attributes
|
||||||
autoload :Aliasing, 'active_record/attributes/aliasing'
|
extend ActiveSupport::Autoload
|
||||||
autoload :Store, 'active_record/attributes/store'
|
|
||||||
autoload :Typecasting, 'active_record/attributes/typecasting'
|
autoload :Aliasing
|
||||||
|
autoload :Store
|
||||||
|
autoload :Typecasting
|
||||||
end
|
end
|
||||||
|
|
||||||
module Type
|
module Type
|
||||||
|
extend ActiveSupport::Autoload
|
||||||
|
|
||||||
autoload :Number, 'active_record/types/number'
|
autoload :Number, 'active_record/types/number'
|
||||||
autoload :Object, 'active_record/types/object'
|
autoload :Object, 'active_record/types/object'
|
||||||
autoload :Serialize, 'active_record/types/serialize'
|
autoload :Serialize, 'active_record/types/serialize'
|
||||||
|
@ -98,12 +100,16 @@ module ActiveRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
module Locking
|
module Locking
|
||||||
autoload :Optimistic, 'active_record/locking/optimistic'
|
extend ActiveSupport::Autoload
|
||||||
autoload :Pessimistic, 'active_record/locking/pessimistic'
|
|
||||||
|
autoload :Optimistic
|
||||||
|
autoload :Pessimistic
|
||||||
end
|
end
|
||||||
|
|
||||||
module ConnectionAdapters
|
module ConnectionAdapters
|
||||||
autoload :AbstractAdapter, 'active_record/connection_adapters/abstract_adapter'
|
extend ActiveSupport::Autoload
|
||||||
|
|
||||||
|
autoload :AbstractAdapter
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -30,11 +30,13 @@ $:.unshift(activemodel_path) if File.directory?(activemodel_path)
|
||||||
require 'active_model'
|
require 'active_model'
|
||||||
|
|
||||||
module ActiveResource
|
module ActiveResource
|
||||||
autoload :Base, 'active_resource/base'
|
extend ActiveSupport::Autoload
|
||||||
autoload :Connection, 'active_resource/connection'
|
|
||||||
autoload :CustomMethods, 'active_resource/custom_methods'
|
autoload :Base
|
||||||
autoload :Formats, 'active_resource/formats'
|
autoload :Connection
|
||||||
autoload :Observing, 'active_resource/observing'
|
autoload :CustomMethods
|
||||||
autoload :Validations, 'active_resource/validations'
|
autoload :Formats
|
||||||
autoload :HttpMock, 'active_resource/http_mock'
|
autoload :Observing
|
||||||
|
autoload :Validations
|
||||||
|
autoload :HttpMock
|
||||||
end
|
end
|
||||||
|
|
|
@ -13,6 +13,7 @@ require 'test/unit'
|
||||||
require 'active_support'
|
require 'active_support'
|
||||||
require 'active_support/test_case'
|
require 'active_support/test_case'
|
||||||
require 'active_resource'
|
require 'active_resource'
|
||||||
|
require 'active_model/test_case'
|
||||||
|
|
||||||
$:.unshift "#{File.dirname(__FILE__)}/../test"
|
$:.unshift "#{File.dirname(__FILE__)}/../test"
|
||||||
require 'setter_trap'
|
require 'setter_trap'
|
||||||
|
|
|
@ -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?('gender=male')
|
||||||
assert Person.collection_path(:gender => 'male', :student => true).include?('student=true')
|
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
|
end
|
||||||
|
|
||||||
def test_custom_element_path
|
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, '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=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
|
end
|
||||||
|
|
||||||
def test_custom_element_path_with_prefix_and_parameters
|
def test_custom_element_path_with_prefix_and_parameters
|
||||||
|
|
|
@ -1,28 +1,31 @@
|
||||||
|
require "active_support/dependencies/autoload"
|
||||||
|
|
||||||
module ActiveSupport
|
module ActiveSupport
|
||||||
autoload :BacktraceCleaner, 'active_support/backtrace_cleaner'
|
extend ActiveSupport::Autoload
|
||||||
autoload :Base64, 'active_support/base64'
|
|
||||||
autoload :BasicObject, 'active_support/basic_object'
|
autoload :BacktraceCleaner
|
||||||
autoload :Benchmarkable, 'active_support/benchmarkable'
|
autoload :Base64
|
||||||
autoload :BufferedLogger, 'active_support/buffered_logger'
|
autoload :BasicObject
|
||||||
autoload :Cache, 'active_support/cache'
|
autoload :Benchmarkable
|
||||||
autoload :Callbacks, 'active_support/callbacks'
|
autoload :BufferedLogger
|
||||||
autoload :Concern, 'active_support/concern'
|
autoload :Cache
|
||||||
autoload :Configurable, 'active_support/configurable'
|
autoload :Callbacks
|
||||||
autoload :DependencyModule, 'active_support/dependency_module'
|
autoload :Concern
|
||||||
autoload :DeprecatedCallbacks, 'active_support/deprecated_callbacks'
|
autoload :Configurable
|
||||||
autoload :Deprecation, 'active_support/deprecation'
|
autoload :DeprecatedCallbacks
|
||||||
autoload :Gzip, 'active_support/gzip'
|
autoload :Deprecation
|
||||||
autoload :Inflector, 'active_support/inflector'
|
autoload :Gzip
|
||||||
autoload :Memoizable, 'active_support/memoizable'
|
autoload :Inflector
|
||||||
autoload :MessageEncryptor, 'active_support/message_encryptor'
|
autoload :Memoizable
|
||||||
autoload :MessageVerifier, 'active_support/message_verifier'
|
autoload :MessageEncryptor
|
||||||
autoload :Multibyte, 'active_support/multibyte'
|
autoload :MessageVerifier
|
||||||
autoload :OptionMerger, 'active_support/option_merger'
|
autoload :Multibyte
|
||||||
autoload :OrderedHash, 'active_support/ordered_hash'
|
autoload :OptionMerger
|
||||||
autoload :OrderedOptions, 'active_support/ordered_options'
|
autoload :OrderedHash
|
||||||
autoload :Notifications, 'active_support/notifications'
|
autoload :OrderedOptions
|
||||||
autoload :Rescuable, 'active_support/rescuable'
|
autoload :Notifications
|
||||||
autoload :SecureRandom, 'active_support/secure_random'
|
autoload :Rescuable
|
||||||
autoload :StringInquirer, 'active_support/string_inquirer'
|
autoload :SecureRandom
|
||||||
autoload :XmlMini, 'active_support/xml_mini'
|
autoload :StringInquirer
|
||||||
|
autoload :XmlMini
|
||||||
end
|
end
|
||||||
|
|
|
@ -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
|
|
@ -1,450 +1,454 @@
|
||||||
require 'ruby-prof'
|
begin
|
||||||
|
require 'ruby-prof'
|
||||||
|
|
||||||
require 'fileutils'
|
require 'fileutils'
|
||||||
require 'rails/version'
|
require 'rails/version'
|
||||||
|
require 'active_support/core_ext/class/delegating_attributes'
|
||||||
|
|
||||||
module ActiveSupport
|
module ActiveSupport
|
||||||
module Testing
|
module Testing
|
||||||
module Performance
|
module Performance
|
||||||
DEFAULTS =
|
DEFAULTS =
|
||||||
if benchmark = ARGV.include?('--benchmark') # HAX for rake test
|
if benchmark = ARGV.include?('--benchmark') # HAX for rake test
|
||||||
{ :benchmark => true,
|
{ :benchmark => true,
|
||||||
:runs => 4,
|
:runs => 4,
|
||||||
:metrics => [:wall_time, :memory, :objects, :gc_runs, :gc_time],
|
:metrics => [:wall_time, :memory, :objects, :gc_runs, :gc_time],
|
||||||
:output => 'tmp/performance' }
|
:output => 'tmp/performance' }
|
||||||
else
|
else
|
||||||
{ :benchmark => false,
|
{ :benchmark => false,
|
||||||
:runs => 1,
|
:runs => 1,
|
||||||
:min_percent => 0.01,
|
:min_percent => 0.01,
|
||||||
:metrics => [:process_time, :memory, :objects],
|
:metrics => [:process_time, :memory, :objects],
|
||||||
:formats => [:flat, :graph_html, :call_tree],
|
:formats => [:flat, :graph_html, :call_tree],
|
||||||
:output => 'tmp/performance' }
|
:output => 'tmp/performance' }
|
||||||
end.freeze
|
end.freeze
|
||||||
|
|
||||||
def self.included(base)
|
def self.included(base)
|
||||||
base.superclass_delegating_accessor :profile_options
|
base.superclass_delegating_accessor :profile_options
|
||||||
base.profile_options = DEFAULTS
|
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
|
|
||||||
end
|
end
|
||||||
|
|
||||||
yield(self.class::FINISHED, name)
|
def full_test_name
|
||||||
end
|
"#{self.class.name}##{method_name}"
|
||||||
|
end
|
||||||
|
|
||||||
def run_test(metric, mode)
|
def run(result)
|
||||||
run_callbacks :setup
|
return if method_name =~ /^default_test$/
|
||||||
setup
|
|
||||||
metric.send(mode) { __send__ @method_name }
|
yield(self.class::STARTED, name)
|
||||||
rescue ::Test::Unit::AssertionFailedError => e
|
@_result = result
|
||||||
add_failure(e.message, e.backtrace)
|
|
||||||
rescue StandardError, ScriptError
|
run_warmup
|
||||||
add_error($!)
|
if profile_options && metrics = profile_options[:metrics]
|
||||||
ensure
|
metrics.each do |metric_name|
|
||||||
begin
|
if klass = Metrics[metric_name.to_sym]
|
||||||
teardown
|
run_profile(klass.new)
|
||||||
run_callbacks :teardown, :enumerator => :reverse_each
|
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
|
rescue ::Test::Unit::AssertionFailedError => e
|
||||||
add_failure(e.message, e.backtrace)
|
add_failure(e.message, e.backtrace)
|
||||||
rescue StandardError, ScriptError
|
rescue StandardError, ScriptError
|
||||||
add_error($!)
|
add_error($!)
|
||||||
end
|
ensure
|
||||||
end
|
begin
|
||||||
|
teardown
|
||||||
protected
|
run_callbacks :teardown, :enumerator => :reverse_each
|
||||||
def run_warmup
|
rescue ::Test::Unit::AssertionFailedError => e
|
||||||
GC.start
|
add_failure(e.message, e.backtrace)
|
||||||
|
rescue StandardError, ScriptError
|
||||||
time = Metrics::Time.new
|
add_error($!)
|
||||||
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
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
def output_filename(printer_class)
|
def run_warmup
|
||||||
suffix =
|
GC.start
|
||||||
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}"
|
time = Metrics::Time.new
|
||||||
end
|
run_test(time, :benchmark)
|
||||||
end
|
puts "%s (%s warmup)" % [full_test_name, time.format(time.total)]
|
||||||
|
|
||||||
module Metrics
|
GC.start
|
||||||
def self.[](name)
|
|
||||||
const_get(name.to_s.camelize)
|
|
||||||
rescue NameError
|
|
||||||
nil
|
|
||||||
end
|
|
||||||
|
|
||||||
class Base
|
|
||||||
attr_reader :total
|
|
||||||
|
|
||||||
def initialize
|
|
||||||
@total = 0
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def name
|
def run_profile(metric)
|
||||||
@name ||= self.class.name.demodulize.underscore
|
klass = profile_options[:benchmark] ? Benchmarker : Profiler
|
||||||
|
performer = klass.new(self, metric)
|
||||||
|
|
||||||
|
performer.run
|
||||||
|
puts performer.report
|
||||||
|
performer.record
|
||||||
end
|
end
|
||||||
|
|
||||||
def measure_mode
|
class Performer
|
||||||
self.class::Mode
|
delegate :run_test, :profile_options, :full_test_name, :to => :@harness
|
||||||
|
|
||||||
|
def initialize(harness, metric)
|
||||||
|
@harness, @metric = harness, metric
|
||||||
end
|
end
|
||||||
|
|
||||||
def measure
|
def report
|
||||||
0
|
rate = @total / profile_options[:runs]
|
||||||
end
|
'%20s: %s' % [@metric.name, @metric.format(rate)]
|
||||||
|
|
||||||
def benchmark
|
|
||||||
with_gc_stats do
|
|
||||||
before = measure
|
|
||||||
yield
|
|
||||||
@total += (measure - before)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def profile
|
|
||||||
RubyProf.resume
|
|
||||||
yield
|
|
||||||
ensure
|
|
||||||
RubyProf.pause
|
|
||||||
end
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
if GC.respond_to?(:enable_stats)
|
def output_filename
|
||||||
def with_gc_stats
|
"#{profile_options[:output]}/#{full_test_name}_#{@metric.name}"
|
||||||
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
|
||||||
end
|
end
|
||||||
|
|
||||||
class Time < Base
|
class Benchmarker < Performer
|
||||||
def measure
|
def run
|
||||||
::Time.now.to_f
|
profile_options[:runs].to_i.times { run_test(@metric, :benchmark) }
|
||||||
|
@total = @metric.total
|
||||||
end
|
end
|
||||||
|
|
||||||
def format(measurement)
|
def record
|
||||||
if measurement < 2
|
avg = @metric.total / profile_options[:runs].to_i
|
||||||
'%d ms' % (measurement * 1000)
|
now = Time.now.utc.xmlschema
|
||||||
else
|
with_output_file do |file|
|
||||||
'%.2f sec' % measurement
|
file.puts "#{avg},#{now},#{environment}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
class ProcessTime < Time
|
def environment
|
||||||
Mode = RubyProf::PROCESS_TIME
|
unless defined? @env
|
||||||
|
app = "#{$1}.#{$2}" if File.directory?('.git') && `git branch -v` =~ /^\* (\S+)\s+(\S+)/
|
||||||
|
|
||||||
def measure
|
rails = Rails::VERSION::STRING
|
||||||
RubyProf.measure_process_time
|
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
|
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
|
end
|
||||||
|
|
||||||
class WallTime < Time
|
class Profiler < Performer
|
||||||
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)
|
|
||||||
|
|
||||||
def initialize(*args)
|
def initialize(*args)
|
||||||
# FIXME: yeah my CPU is 2.33 GHz
|
|
||||||
RubyProf.cpu_frequency = 2.33e9
|
|
||||||
super
|
super
|
||||||
|
@supported = @metric.measure_mode rescue false
|
||||||
end
|
end
|
||||||
|
|
||||||
def measure
|
def run
|
||||||
RubyProf.measure_cpu_time
|
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
|
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
|
end
|
||||||
|
|
||||||
class Memory < Base
|
module Metrics
|
||||||
Mode = RubyProf::MEMORY if RubyProf.const_defined?(:MEMORY)
|
def self.[](name)
|
||||||
|
const_get(name.to_s.camelize)
|
||||||
|
rescue NameError
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
|
||||||
# ruby-prof wrapper
|
class Base
|
||||||
if RubyProf.respond_to?(:measure_memory)
|
attr_reader :total
|
||||||
def measure
|
|
||||||
RubyProf.measure_memory / 1024.0
|
def initialize
|
||||||
|
@total = 0
|
||||||
end
|
end
|
||||||
|
|
||||||
# Ruby 1.8 + railsbench patch
|
def name
|
||||||
elsif GC.respond_to?(:allocated_size)
|
@name ||= self.class.name.demodulize.underscore
|
||||||
def measure
|
|
||||||
GC.allocated_size / 1024.0
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Ruby 1.8 + lloyd patch
|
def measure_mode
|
||||||
elsif GC.respond_to?(:heap_info)
|
self.class::Mode
|
||||||
def measure
|
|
||||||
GC.heap_info['heap_current_memory'] / 1024.0
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Ruby 1.9 with total_malloc_allocated_size patch
|
|
||||||
elsif GC.respond_to?(:malloc_total_allocated_size)
|
|
||||||
def measure
|
def measure
|
||||||
GC.total_malloc_allocated_size / 1024.0
|
0
|
||||||
end
|
end
|
||||||
|
|
||||||
# Ruby 1.9 unpatched
|
def benchmark
|
||||||
elsif GC.respond_to?(:malloc_allocated_size)
|
with_gc_stats do
|
||||||
def measure
|
before = measure
|
||||||
GC.malloc_allocated_size / 1024.0
|
yield
|
||||||
|
@total += (measure - before)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Ruby 1.9 + GC profiler patch
|
def profile
|
||||||
elsif defined?(GC::Profiler)
|
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
|
def measure
|
||||||
GC.enable
|
::Time.now.to_f
|
||||||
GC.start
|
end
|
||||||
kb = GC::Profiler.data.last[:HEAP_USE_SIZE] / 1024.0
|
|
||||||
GC.disable
|
def format(measurement)
|
||||||
kb
|
if measurement < 2
|
||||||
|
'%d ms' % (measurement * 1000)
|
||||||
|
else
|
||||||
|
'%.2f sec' % measurement
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def format(measurement)
|
class ProcessTime < Time
|
||||||
'%.2f KB' % measurement
|
Mode = RubyProf::PROCESS_TIME
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
class Objects < Base
|
|
||||||
Mode = RubyProf::ALLOCATIONS if RubyProf.const_defined?(:ALLOCATIONS)
|
|
||||||
|
|
||||||
if RubyProf.respond_to?(:measure_allocations)
|
|
||||||
def measure
|
def measure
|
||||||
RubyProf.measure_allocations
|
RubyProf.measure_process_time
|
||||||
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
|
||||||
end
|
end
|
||||||
|
|
||||||
def format(measurement)
|
class WallTime < Time
|
||||||
measurement.to_i.to_s
|
Mode = RubyProf::WALL_TIME
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
class GcRuns < Base
|
|
||||||
Mode = RubyProf::GC_RUNS if RubyProf.const_defined?(:GC_RUNS)
|
|
||||||
|
|
||||||
if RubyProf.respond_to?(:measure_gc_runs)
|
|
||||||
def measure
|
def measure
|
||||||
RubyProf.measure_gc_runs
|
RubyProf.measure_wall_time
|
||||||
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
|
||||||
end
|
end
|
||||||
|
|
||||||
def format(measurement)
|
class CpuTime < Time
|
||||||
measurement.to_i.to_s
|
Mode = RubyProf::CPU_TIME if RubyProf.const_defined?(:CPU_TIME)
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
class GcTime < Base
|
def initialize(*args)
|
||||||
Mode = RubyProf::GC_TIME if RubyProf.const_defined?(:GC_TIME)
|
# FIXME: yeah my CPU is 2.33 GHz
|
||||||
|
RubyProf.cpu_frequency = 2.33e9
|
||||||
if RubyProf.respond_to?(:measure_gc_time)
|
super
|
||||||
def measure
|
|
||||||
RubyProf.measure_gc_time
|
|
||||||
end
|
end
|
||||||
elsif GC.respond_to?(:time)
|
|
||||||
def measure
|
def measure
|
||||||
GC.time
|
RubyProf.measure_cpu_time
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def format(measurement)
|
class Memory < Base
|
||||||
'%d ms' % (measurement / 1000)
|
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
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
rescue LoadError
|
||||||
|
end
|
|
@ -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
|
|
@ -0,0 +1,2 @@
|
||||||
|
class Fixtures::AnotherClass
|
||||||
|
end
|
|
@ -0,0 +1,2 @@
|
||||||
|
class Fixtures::Autoload::SomeClass
|
||||||
|
end
|
|
@ -1,6 +1,7 @@
|
||||||
require 'active_support/all'
|
require 'active_support/all'
|
||||||
require 'active_support/test_case'
|
require 'active_support/test_case'
|
||||||
require 'action_controller'
|
require 'action_controller'
|
||||||
|
require 'action_dispatch/test_case'
|
||||||
|
|
||||||
# work around the at_exit hook in test/unit, which kills IRB
|
# work around the at_exit hook in test/unit, which kills IRB
|
||||||
Test::Unit.run = true if Test::Unit.respond_to?(:run=)
|
Test::Unit.run = true if Test::Unit.respond_to?(:run=)
|
||||||
|
|
|
@ -8,8 +8,14 @@ gem "rack-test", "~> 0.5.0"
|
||||||
|
|
||||||
require 'test/unit'
|
require 'test/unit'
|
||||||
require 'active_support/core_ext/kernel/requires'
|
require 'active_support/core_ext/kernel/requires'
|
||||||
|
|
||||||
|
# AP is always present
|
||||||
|
require 'action_controller/test_case'
|
||||||
require 'action_view/test_case'
|
require 'action_view/test_case'
|
||||||
|
require 'action_dispatch/test_case'
|
||||||
|
|
||||||
require 'action_mailer/test_case' if defined?(ActionMailer)
|
require 'action_mailer/test_case' if defined?(ActionMailer)
|
||||||
|
require 'active_model/test_case' if defined?(ActiveModel)
|
||||||
|
|
||||||
if defined?(ActiveRecord)
|
if defined?(ActiveRecord)
|
||||||
require 'active_record/test_case'
|
require 'active_record/test_case'
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
require 'abstract_unit'
|
require 'abstract_unit'
|
||||||
require 'action_controller'
|
require 'action_controller'
|
||||||
|
require 'action_controller/test_case'
|
||||||
|
|
||||||
require 'rails/info'
|
require 'rails/info'
|
||||||
require 'rails/info_controller'
|
require 'rails/info_controller'
|
||||||
|
|
Loading…
Reference in New Issue