Added reusable reloading support through the inclusion of the Relodable module that all subclasses of ActiveRecord::Base, ActiveRecord::Observer, ActiveController::Base, and ActionMailer::Base automatically gets [DHH]. Added auto-loading support for classes in modules, so Conductor::Migration will look for conductor/migration.rb and Conductor::Database::Settings will look for conductor/database/settings.rb [Nicholas Seckar]. Refactored extensions to module, class, and object in active support [DHH]
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@3493 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
This commit is contained in:
parent
94046542e2
commit
01b1a87729
|
@ -121,6 +121,13 @@ module ActionMailer
|
||||||
class Base
|
class Base
|
||||||
include AdvAttrAccessor, PartContainer
|
include AdvAttrAccessor, PartContainer
|
||||||
|
|
||||||
|
# Action Mailer subclasses should be reloaded by the dispatcher in Rails
|
||||||
|
# when Dependencies.mechanism = :load.
|
||||||
|
def self.inherited(child) #:nodoc:
|
||||||
|
child.send :include, Reloadable
|
||||||
|
super
|
||||||
|
end
|
||||||
|
|
||||||
private_class_method :new #:nodoc:
|
private_class_method :new #:nodoc:
|
||||||
|
|
||||||
cattr_accessor :template_root
|
cattr_accessor :template_root
|
||||||
|
|
|
@ -224,6 +224,13 @@ module ActionController #:nodoc:
|
||||||
# FCGI.each_cgi{ |cgi| WeblogController.process_cgi(cgi) }
|
# FCGI.each_cgi{ |cgi| WeblogController.process_cgi(cgi) }
|
||||||
class Base
|
class Base
|
||||||
DEFAULT_RENDER_STATUS_CODE = "200 OK"
|
DEFAULT_RENDER_STATUS_CODE = "200 OK"
|
||||||
|
|
||||||
|
# Action Controller subclasses should be reloaded by the dispatcher in Rails
|
||||||
|
# when Dependencies.mechanism = :load.
|
||||||
|
def self.inherited(child) #:nodoc:
|
||||||
|
child.send :include, Reloadable
|
||||||
|
super
|
||||||
|
end
|
||||||
|
|
||||||
# Determines whether the view has access to controller internals @request, @response, @session, and @template.
|
# Determines whether the view has access to controller internals @request, @response, @session, and @template.
|
||||||
# By default, it does.
|
# By default, it does.
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
module ActionController #:nodoc:
|
module ActionController #:nodoc:
|
||||||
module Layout #:nodoc:
|
module Layout #:nodoc:
|
||||||
def self.append_features(base)
|
def self.included(base)
|
||||||
super
|
base.extend(ClassMethods)
|
||||||
base.class_eval do
|
base.class_eval do
|
||||||
alias_method :render_with_no_layout, :render
|
alias_method :render_with_no_layout, :render
|
||||||
alias_method :render, :render_with_a_layout
|
alias_method :render, :render_with_a_layout
|
||||||
|
|
||||||
class << self
|
class << self
|
||||||
alias_method :inherited_without_layout, :inherited
|
alias_method :inherited_without_layout, :inherited
|
||||||
|
alias_method :inherited, :inherited_with_layout
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
base.extend(ClassMethods)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Layouts reverse the common pattern of including shared headers and footers in many templates to isolate changes in
|
# Layouts reverse the common pattern of including shared headers and footers in many templates to isolate changes in
|
||||||
|
@ -172,8 +172,9 @@ module ActionController #:nodoc:
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
def inherited(child)
|
def inherited_with_layout(child)
|
||||||
inherited_without_layout(child)
|
inherited_without_layout(child)
|
||||||
|
child.send :include, Reloadable
|
||||||
layout_match = child.name.underscore.sub(/_controller$/, '')
|
layout_match = child.name.underscore.sub(/_controller$/, '')
|
||||||
child.layout(layout_match) unless layout_list.grep(%r{layouts/#{layout_match}\.[a-z][0-9a-z]*$}).empty?
|
child.layout(layout_match) unless layout_list.grep(%r{layouts/#{layout_match}\.[a-z][0-9a-z]*$}).empty?
|
||||||
end
|
end
|
||||||
|
|
|
@ -333,6 +333,13 @@ module ActionController #:nodoc:
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def build_request_uri(action, parameters)
|
||||||
|
options = @controller.send(:rewrite_options, parameters)
|
||||||
|
options.update(:only_path => true, :action => action)
|
||||||
|
url = ActionController::UrlRewriter.new(@request, parameters)
|
||||||
|
@request.set_REQUEST_URI(url.rewrite(options))
|
||||||
|
end
|
||||||
|
|
||||||
def session
|
def session
|
||||||
@response.session
|
@response.session
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,7 +3,7 @@ require "#{File.dirname(__FILE__)}/../testing_sandbox"
|
||||||
require File.dirname(__FILE__) + '/../../lib/action_view/helpers/text_helper'
|
require File.dirname(__FILE__) + '/../../lib/action_view/helpers/text_helper'
|
||||||
require File.dirname(__FILE__) + '/../../../activesupport/lib/active_support/core_ext/numeric' # for human_size
|
require File.dirname(__FILE__) + '/../../../activesupport/lib/active_support/core_ext/numeric' # for human_size
|
||||||
require File.dirname(__FILE__) + '/../../../activesupport/lib/active_support/core_ext/hash' # for stringify_keys
|
require File.dirname(__FILE__) + '/../../../activesupport/lib/active_support/core_ext/hash' # for stringify_keys
|
||||||
require File.dirname(__FILE__) + '/../../../activesupport/lib/active_support/core_ext/object_and_class.rb' # for blank?
|
require File.dirname(__FILE__) + '/../../../activesupport/lib/active_support/core_ext/object.rb' # for blank?
|
||||||
|
|
||||||
class TextHelperTest < Test::Unit::TestCase
|
class TextHelperTest < Test::Unit::TestCase
|
||||||
include ActionView::Helpers::TextHelper
|
include ActionView::Helpers::TextHelper
|
||||||
|
|
|
@ -244,6 +244,7 @@ module ActiveRecord #:nodoc:
|
||||||
cattr_accessor :logger
|
cattr_accessor :logger
|
||||||
|
|
||||||
def self.inherited(child) #:nodoc:
|
def self.inherited(child) #:nodoc:
|
||||||
|
child.send :include, Reloadable
|
||||||
@@subclasses[self] ||= []
|
@@subclasses[self] ||= []
|
||||||
@@subclasses[self] << child
|
@@subclasses[self] << child
|
||||||
super
|
super
|
||||||
|
|
|
@ -81,6 +81,13 @@ module ActiveRecord
|
||||||
class Observer
|
class Observer
|
||||||
include Singleton
|
include Singleton
|
||||||
|
|
||||||
|
# Observer subclasses should be reloaded by the dispatcher in Rails
|
||||||
|
# when Dependencies.mechanism = :load.
|
||||||
|
def self.inherited(child) #:nodoc:
|
||||||
|
child.send :include, Reloadable
|
||||||
|
super
|
||||||
|
end
|
||||||
|
|
||||||
# Attaches the observer to the supplied model classes.
|
# Attaches the observer to the supplied model classes.
|
||||||
def self.observe(*models)
|
def self.observe(*models)
|
||||||
define_method(:observed_class) { models }
|
define_method(:observed_class) { models }
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
require 'test/unit'
|
require 'test/unit'
|
||||||
require 'abstract_unit'
|
require 'abstract_unit'
|
||||||
require 'active_support/class_inheritable_attributes'
|
require 'active_support/core_ext/class/inheritable_attributes'
|
||||||
|
|
||||||
class A
|
class A
|
||||||
include ClassInheritableAttributes
|
include ClassInheritableAttributes
|
||||||
|
|
|
@ -1,5 +1,15 @@
|
||||||
*SVN*
|
*SVN*
|
||||||
|
|
||||||
|
* Added reusable reloading support through the inclusion of the Relodable module that all subclasses of ActiveRecord::Base, ActiveRecord::Observer, ActiveController::Base, and ActionMailer::Base automatically gets. This means that these classes will be reloaded by the dispatcher when Dependencies.mechanism = :load. You can make your own models reloadable easily:
|
||||||
|
|
||||||
|
class Setting
|
||||||
|
include Reloadable
|
||||||
|
end
|
||||||
|
|
||||||
|
Reloading a class is done by removing its constant which will cause it to be loaded again on the next reference. [DHH]
|
||||||
|
|
||||||
|
* Added auto-loading support for classes in modules, so Conductor::Migration will look for conductor/migration.rb and Conductor::Database::Settings will look for conductor/database/settings.rb [Nicholas Seckar]
|
||||||
|
|
||||||
* Add Object#instance_exec, like instance_eval but passes its arguments to the block. (Active Support will not override the Ruby 1.9 implementation of this method.) [Sam Stephenson]
|
* Add Object#instance_exec, like instance_eval but passes its arguments to the block. (Active Support will not override the Ruby 1.9 implementation of this method.) [Sam Stephenson]
|
||||||
|
|
||||||
* Add Proc#bind(object) for changing a proc or block's self by returning a Method bound to the given object. Based on why the lucky stiff's "cloaker" method. [Sam Stephenson]
|
* Add Proc#bind(object) for changing a proc or block's self by returning a Method bound to the given object. Based on why the lucky stiff's "cloaker" method. [Sam Stephenson]
|
||||||
|
|
|
@ -23,13 +23,12 @@
|
||||||
|
|
||||||
$:.unshift(File.dirname(__FILE__))
|
$:.unshift(File.dirname(__FILE__))
|
||||||
|
|
||||||
require 'active_support/class_attribute_accessors'
|
|
||||||
require 'active_support/class_inheritable_attributes'
|
|
||||||
require 'active_support/inflector'
|
require 'active_support/inflector'
|
||||||
|
|
||||||
require 'active_support/core_ext'
|
require 'active_support/core_ext'
|
||||||
require 'active_support/clean_logger'
|
require 'active_support/clean_logger'
|
||||||
require 'active_support/dependencies'
|
require 'active_support/dependencies'
|
||||||
|
require 'active_support/reloadable'
|
||||||
|
|
||||||
require 'active_support/ordered_options'
|
require 'active_support/ordered_options'
|
||||||
require 'active_support/option_merger'
|
require 'active_support/option_merger'
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
require 'logger'
|
require 'logger'
|
||||||
require File.dirname(__FILE__) + '/class_attribute_accessors'
|
require File.dirname(__FILE__) + '/core_ext/class/attribute_accessors'
|
||||||
|
|
||||||
class Logger #:nodoc:
|
class Logger #:nodoc:
|
||||||
cattr_accessor :silencer
|
cattr_accessor :silencer
|
||||||
|
|
|
@ -1,4 +1,16 @@
|
||||||
# The methods here are provided to speed up function blank? in class Object
|
class Object #:nodoc:
|
||||||
|
# "", " ", nil, [], and {} are blank
|
||||||
|
def blank?
|
||||||
|
if respond_to?(:empty?) && respond_to?(:strip)
|
||||||
|
empty? or strip.empty?
|
||||||
|
elsif respond_to?(:empty?)
|
||||||
|
empty?
|
||||||
|
else
|
||||||
|
!self
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
class NilClass #:nodoc:
|
class NilClass #:nodoc:
|
||||||
def blank?
|
def blank?
|
||||||
true
|
true
|
||||||
|
@ -35,4 +47,4 @@ class Numeric #:nodoc:
|
||||||
def blank?
|
def blank?
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
end
|
end
|
|
@ -0,0 +1,3 @@
|
||||||
|
require File.dirname(__FILE__) + '/class/attribute_accessors'
|
||||||
|
require File.dirname(__FILE__) + '/class/inheritable_attributes'
|
||||||
|
require File.dirname(__FILE__) + '/class/removal'
|
|
@ -0,0 +1,21 @@
|
||||||
|
class Class #:nodoc:
|
||||||
|
def remove_subclasses
|
||||||
|
Object.remove_subclasses_of(self)
|
||||||
|
end
|
||||||
|
|
||||||
|
def subclasses
|
||||||
|
Object.subclasses_of(self).map { |o| o.to_s }
|
||||||
|
end
|
||||||
|
|
||||||
|
def remove_class(klass)
|
||||||
|
if klass.to_s.include? "::"
|
||||||
|
modules = klass.to_s.split("::")
|
||||||
|
final_klass = modules.pop
|
||||||
|
|
||||||
|
final_module = modules.inject(Object) { |final_type, part| final_type.const_get(part) }
|
||||||
|
final_module.send(:remove_const, final_klass) rescue nil
|
||||||
|
else
|
||||||
|
Object.send(:remove_const, klass.to_s) rescue nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,5 +1,4 @@
|
||||||
class Exception
|
class Exception
|
||||||
|
|
||||||
alias :clean_message :message
|
alias :clean_message :message
|
||||||
|
|
||||||
TraceSubstitutions = []
|
TraceSubstitutions = []
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
require File.dirname(__FILE__) + '/module/inclusion'
|
||||||
|
require File.dirname(__FILE__) + '/module/attribute_accessors'
|
|
@ -0,0 +1,15 @@
|
||||||
|
class Module
|
||||||
|
def remove_classes_including
|
||||||
|
included_in_classes.each { |klass| Class.remove_class(klass) }
|
||||||
|
end
|
||||||
|
|
||||||
|
def included_in_classes
|
||||||
|
classes = []
|
||||||
|
ObjectSpace.each_object(Class) { |k| classes << k if k.included_modules.include?(self) }
|
||||||
|
|
||||||
|
classes.reverse.inject([]) do |unique_classes, klass|
|
||||||
|
unique_classes << klass unless unique_classes.collect { |k| k.to_s }.include?(klass.to_s)
|
||||||
|
unique_classes
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,2 @@
|
||||||
|
require File.dirname(__FILE__) + '/object/extending'
|
||||||
|
require File.dirname(__FILE__) + '/object/misc'
|
|
@ -4,7 +4,7 @@ class Object #:nodoc:
|
||||||
Object.send(:remove_const, subclass.to_s) rescue nil
|
Object.send(:remove_const, subclass.to_s) rescue nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def subclasses_of(*superclasses)
|
def subclasses_of(*superclasses)
|
||||||
subclasses = []
|
subclasses = []
|
||||||
ObjectSpace.each_object(Class) do |k|
|
ObjectSpace.each_object(Class) do |k|
|
||||||
|
@ -20,41 +20,16 @@ class Object #:nodoc:
|
||||||
end
|
end
|
||||||
|
|
||||||
def copy_instance_variables_from(object, exclude = [])
|
def copy_instance_variables_from(object, exclude = [])
|
||||||
exclude += object.protected_instance_variables if
|
exclude += object.protected_instance_variables if object.respond_to? :protected_instance_variables
|
||||||
object.respond_to? :protected_instance_variables
|
|
||||||
|
|
||||||
instance_variables = object.instance_variables - exclude.map { |name| name.to_s }
|
instance_variables = object.instance_variables - exclude.map { |name| name.to_s }
|
||||||
instance_variables.each do |name|
|
instance_variables.each { |name| instance_variable_set(name, object.instance_variable_get(name)) }
|
||||||
instance_variable_set name, object.instance_variable_get(name)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def extend_with_included_modules_from(object)
|
def extend_with_included_modules_from(object)
|
||||||
object.extended_by.each { |mod| extend mod }
|
object.extended_by.each { |mod| extend mod }
|
||||||
end
|
end
|
||||||
|
|
||||||
# "", " ", nil, [], and {} are blank
|
|
||||||
def blank?
|
|
||||||
if respond_to?(:empty?) && respond_to?(:strip)
|
|
||||||
empty? or strip.empty?
|
|
||||||
elsif respond_to?(:empty?)
|
|
||||||
empty?
|
|
||||||
else
|
|
||||||
!self
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def suppress(*exception_classes)
|
|
||||||
begin yield
|
|
||||||
rescue Exception => e
|
|
||||||
raise unless exception_classes.any? {|cls| e.kind_of? cls}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def with_options(options)
|
|
||||||
yield ActiveSupport::OptionMerger.new(self, options)
|
|
||||||
end
|
|
||||||
|
|
||||||
def instance_values
|
def instance_values
|
||||||
instance_variables.inject({}) do |values, name|
|
instance_variables.inject({}) do |values, name|
|
||||||
values[name[1..-1]] = instance_variable_get(name)
|
values[name[1..-1]] = instance_variable_get(name)
|
||||||
|
@ -62,23 +37,9 @@ class Object #:nodoc:
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_json
|
|
||||||
ActiveSupport::JSON.encode(self)
|
|
||||||
end
|
|
||||||
|
|
||||||
unless defined? instance_exec # 1.9
|
unless defined? instance_exec # 1.9
|
||||||
def instance_exec(*arguments, &block)
|
def instance_exec(*arguments, &block)
|
||||||
block.bind(self)[*arguments]
|
block.bind(self)[*arguments]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class Class #:nodoc:
|
|
||||||
def remove_subclasses
|
|
||||||
Object.remove_subclasses_of(self)
|
|
||||||
end
|
|
||||||
|
|
||||||
def subclasses
|
|
||||||
Object.subclasses_of(self).map { |o| o.to_s }
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
class Object #:nodoc:
|
||||||
|
def with_options(options)
|
||||||
|
yield ActiveSupport::OptionMerger.new(self, options)
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_json
|
||||||
|
ActiveSupport::JSON.encode(self)
|
||||||
|
end
|
||||||
|
|
||||||
|
def suppress(*exception_classes)
|
||||||
|
begin yield
|
||||||
|
rescue Exception => e
|
||||||
|
raise unless exception_classes.any? { |cls| e.kind_of?(cls) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,5 +1,5 @@
|
||||||
require 'set'
|
require 'set'
|
||||||
require File.dirname(__FILE__) + '/module_attribute_accessors'
|
require File.dirname(__FILE__) + '/core_ext/module/attribute_accessors'
|
||||||
require File.dirname(__FILE__) + '/core_ext/load_error'
|
require File.dirname(__FILE__) + '/core_ext/load_error'
|
||||||
require File.dirname(__FILE__) + '/core_ext/kernel'
|
require File.dirname(__FILE__) + '/core_ext/kernel'
|
||||||
|
|
||||||
|
@ -69,10 +69,6 @@ module Dependencies #:nodoc:
|
||||||
history << file_name
|
history << file_name
|
||||||
end
|
end
|
||||||
|
|
||||||
def remove_subclasses_for(*classes)
|
|
||||||
Object.remove_subclasses_of(*classes)
|
|
||||||
end
|
|
||||||
|
|
||||||
# LoadingModules implement namespace-safe dynamic loading.
|
# LoadingModules implement namespace-safe dynamic loading.
|
||||||
# They support automatic loading via const_missing, allowing contained items to be automatically
|
# They support automatic loading via const_missing, allowing contained items to be automatically
|
||||||
# loaded when required. No extra syntax is required, as expressions such as Controller::Admin::UserController
|
# loaded when required. No extra syntax is required, as expressions such as Controller::Admin::UserController
|
||||||
|
@ -211,27 +207,70 @@ Object.send(:define_method, :require_association) { |file_name| Dependencies.ass
|
||||||
class Module #:nodoc:
|
class Module #:nodoc:
|
||||||
# Rename the original handler so we can chain it to the new one
|
# Rename the original handler so we can chain it to the new one
|
||||||
alias :rails_original_const_missing :const_missing
|
alias :rails_original_const_missing :const_missing
|
||||||
|
|
||||||
|
def parent
|
||||||
|
parent_name = name.split('::')[0..-2] * '::'
|
||||||
|
parent_name.empty? ? Object : parent_name.constantize
|
||||||
|
end
|
||||||
|
|
||||||
|
def as_load_path
|
||||||
|
if self == Object || self == Kernel
|
||||||
|
''
|
||||||
|
elsif is_a? Class
|
||||||
|
parent == self ? '' : parent.as_load_path
|
||||||
|
else
|
||||||
|
name.split('::').collect do |word|
|
||||||
|
word.underscore
|
||||||
|
end * '/'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# Use const_missing to autoload associations so we don't have to
|
# Use const_missing to autoload associations so we don't have to
|
||||||
# require_association when using single-table inheritance.
|
# require_association when using single-table inheritance.
|
||||||
def const_missing(class_id)
|
def const_missing(class_id)
|
||||||
if Object.const_defined?(:Controllers) and Object::Controllers.const_available?(class_id)
|
if Object.const_defined?(:Controllers) && Object::Controllers.const_available?(class_id)
|
||||||
return Object::Controllers.const_get(class_id)
|
return Object::Controllers.const_get(class_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
file_name = class_id.to_s.demodulize.underscore
|
file_name = class_id.to_s.demodulize.underscore
|
||||||
|
file_path = as_load_path.empty? ? file_name : "#{as_load_path}/#{file_name}"
|
||||||
begin
|
begin
|
||||||
require_dependency(file_name)
|
require_dependency(file_path)
|
||||||
raise NameError.new("uninitialized constant #{class_id}") unless Object.const_defined?(class_id)
|
brief_name = self == Object ? '' : "#{name}::"
|
||||||
return Object.const_get(class_id)
|
raise NameError.new("uninitialized constant #{brief_name}#{class_id}") unless const_defined?(class_id)
|
||||||
|
return const_get(class_id)
|
||||||
rescue MissingSourceFile => e
|
rescue MissingSourceFile => e
|
||||||
# Convert the exception to a NameError only if the file we are looking for is the missing one.
|
# Re-raise the error if it does not concern the file we were trying to load.
|
||||||
raise unless e.is_missing? file_name
|
raise unless e.is_missing? file_path
|
||||||
|
|
||||||
|
# Look for a directory in the load path that we ought to load.
|
||||||
|
if $LOAD_PATH.any? { |base| File.directory? "#{base}/#{file_path}" }
|
||||||
|
mod = Module.new
|
||||||
|
const_set class_id, mod # Create the new module
|
||||||
|
return mod
|
||||||
|
end
|
||||||
|
|
||||||
|
if parent && parent != self
|
||||||
|
suppress(NameError) do
|
||||||
|
return parent.send(:const_missing, class_id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
raise NameError.new("uninitialized constant #{class_id}").copy_blame!(e)
|
raise NameError.new("uninitialized constant #{class_id}").copy_blame!(e)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class Class
|
||||||
|
def const_missing(class_id)
|
||||||
|
if [Object, Kernel].include?(self) || parent == self
|
||||||
|
super
|
||||||
|
else
|
||||||
|
parent.send :const_missing, class_id
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
class Object #:nodoc:
|
class Object #:nodoc:
|
||||||
def load(file, *extras)
|
def load(file, *extras)
|
||||||
super(file, *extras)
|
super(file, *extras)
|
||||||
|
@ -267,4 +306,4 @@ class Exception #:nodoc:
|
||||||
@blamed_files = exc.blamed_files.clone
|
@blamed_files = exc.blamed_files.clone
|
||||||
self
|
self
|
||||||
end
|
end
|
||||||
end
|
end
|
|
@ -0,0 +1,4 @@
|
||||||
|
# Classes that include this module will automatically be reloaded
|
||||||
|
# by the Rails dispatcher when Dependencies.mechanism = :load.
|
||||||
|
module Reloadable
|
||||||
|
end
|
|
@ -0,0 +1,2 @@
|
||||||
|
class A::B
|
||||||
|
end
|
|
@ -0,0 +1,2 @@
|
||||||
|
class A::C::D
|
||||||
|
end
|
|
@ -0,0 +1,2 @@
|
||||||
|
class E
|
||||||
|
end
|
|
@ -1,5 +1,5 @@
|
||||||
require 'test/unit'
|
require 'test/unit'
|
||||||
require File.dirname(__FILE__) + '/../lib/active_support/class_inheritable_attributes'
|
require File.dirname(__FILE__) + '/../lib/active_support/core_ext/class/inheritable_attributes'
|
||||||
|
|
||||||
class ClassInheritableAttributesTest < Test::Unit::TestCase
|
class ClassInheritableAttributesTest < Test::Unit::TestCase
|
||||||
def setup
|
def setup
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
require 'test/unit'
|
require 'test/unit'
|
||||||
require File.dirname(__FILE__) + '/../../lib/active_support/core_ext/object_and_class'
|
require File.dirname(__FILE__) + '/../../lib/active_support/core_ext/object'
|
||||||
require File.dirname(__FILE__) + '/../../lib/active_support/core_ext/blank'
|
require File.dirname(__FILE__) + '/../../lib/active_support/core_ext/blank'
|
||||||
|
|
||||||
class BlankTest < Test::Unit::TestCase
|
class BlankTest < Test::Unit::TestCase
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
require 'test/unit'
|
||||||
|
require File.dirname(__FILE__) + '/../../lib/active_support/core_ext/class'
|
||||||
|
|
||||||
|
class A
|
||||||
|
end
|
||||||
|
|
||||||
|
module X
|
||||||
|
class B
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
module Y
|
||||||
|
module Z
|
||||||
|
class C
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class ClassTest < Test::Unit::TestCase
|
||||||
|
def test_removing_class_in_root_namespace
|
||||||
|
assert A.is_a?(Class)
|
||||||
|
Class.remove_class(A)
|
||||||
|
assert_raises(NameError) { A.is_a?(Class) }
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_removing_class_in_one_level_namespace
|
||||||
|
assert X::B.is_a?(Class)
|
||||||
|
Class.remove_class(X::B)
|
||||||
|
assert_raises(NameError) { X::B.is_a?(Class) }
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_removing_class_in_two_level_namespace
|
||||||
|
assert Y::Z::C.is_a?(Class)
|
||||||
|
Class.remove_class(Y::Z::C)
|
||||||
|
assert_raises(NameError) { Y::Z::C.is_a?(Class) }
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,51 @@
|
||||||
|
require 'test/unit'
|
||||||
|
require File.dirname(__FILE__) + '/../../lib/active_support/core_ext/class'
|
||||||
|
require File.dirname(__FILE__) + '/../../lib/active_support/core_ext/module'
|
||||||
|
|
||||||
|
module One
|
||||||
|
end
|
||||||
|
|
||||||
|
class Ab
|
||||||
|
include One
|
||||||
|
end
|
||||||
|
|
||||||
|
module Xy
|
||||||
|
class Bc
|
||||||
|
include One
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
module Yz
|
||||||
|
module Zy
|
||||||
|
class Cd
|
||||||
|
include One
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class De
|
||||||
|
end
|
||||||
|
|
||||||
|
class ModuleTest < Test::Unit::TestCase
|
||||||
|
def test_included_in_classes
|
||||||
|
assert One.included_in_classes.include?(Ab)
|
||||||
|
assert One.included_in_classes.include?(Xy::Bc)
|
||||||
|
assert One.included_in_classes.include?(Yz::Zy::Cd)
|
||||||
|
assert !One.included_in_classes.include?(De)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_remove_classes_including
|
||||||
|
assert Ab.is_a?(Class)
|
||||||
|
assert Xy::Bc.is_a?(Class)
|
||||||
|
assert Yz::Zy::Cd.is_a?(Class)
|
||||||
|
assert De.is_a?(Class)
|
||||||
|
|
||||||
|
One.remove_classes_including
|
||||||
|
|
||||||
|
assert_raises(NameError) { Ae.is_a?(Class) }
|
||||||
|
assert_raises(NameError) { Xy::Bc.is_a?(Class) }
|
||||||
|
assert_raises(NameError) { Yz::Zy::Cd.is_a?(Class) }
|
||||||
|
|
||||||
|
assert De.is_a?(Class)
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,5 +1,6 @@
|
||||||
require 'test/unit'
|
require 'test/unit'
|
||||||
require File.dirname(__FILE__) + '/../../lib/active_support/core_ext/object_and_class'
|
require File.dirname(__FILE__) + '/../../lib/active_support/core_ext/object'
|
||||||
|
require File.dirname(__FILE__) + '/../../lib/active_support/core_ext/class'
|
||||||
|
|
||||||
class ClassA; end
|
class ClassA; end
|
||||||
class ClassB < ClassA; end
|
class ClassB < ClassA; end
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
require 'test/unit'
|
require 'test/unit'
|
||||||
$LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib/active_support/'
|
$LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib/active_support/'
|
||||||
|
require 'core_ext/string'
|
||||||
require 'dependencies'
|
require 'dependencies'
|
||||||
|
|
||||||
class DependenciesTest < Test::Unit::TestCase
|
class DependenciesTest < Test::Unit::TestCase
|
||||||
|
@ -99,4 +100,20 @@ class DependenciesTest < Test::Unit::TestCase
|
||||||
$LOAD_PATH.shift
|
$LOAD_PATH.shift
|
||||||
Dependencies.mechanism = old_mechanism
|
Dependencies.mechanism = old_mechanism
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_as_load_path
|
||||||
|
assert_equal '', DependenciesTest.as_load_path
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_module_loading
|
||||||
|
$LOAD_PATH.unshift "#{File.dirname(__FILE__)}/autoloading_fixtures"
|
||||||
|
old_mechanism, Dependencies.mechanism = Dependencies.mechanism, :load
|
||||||
|
|
||||||
|
assert_kind_of Module, A
|
||||||
|
assert_kind_of Class, A::B
|
||||||
|
assert_kind_of Class, A::C::D
|
||||||
|
ensure
|
||||||
|
$LOAD_PATH.shift
|
||||||
|
Dependencies.mechanism = old_mechanism
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,7 +2,7 @@ require 'test/unit'
|
||||||
|
|
||||||
unless defined? ActiveSupport::OptionMerger
|
unless defined? ActiveSupport::OptionMerger
|
||||||
require File.dirname(__FILE__) + '/../lib/active_support/option_merger'
|
require File.dirname(__FILE__) + '/../lib/active_support/option_merger'
|
||||||
require File.dirname(__FILE__) + '/../lib/active_support/core_ext/object_and_class'
|
require File.dirname(__FILE__) + '/../lib/active_support/core_ext/object'
|
||||||
end
|
end
|
||||||
|
|
||||||
class OptionMergerTest < Test::Unit::TestCase
|
class OptionMergerTest < Test::Unit::TestCase
|
||||||
|
|
|
@ -53,8 +53,7 @@ class Dispatcher
|
||||||
Controllers.clear!
|
Controllers.clear!
|
||||||
Dependencies.clear
|
Dependencies.clear
|
||||||
ActiveRecord::Base.reset_subclasses
|
ActiveRecord::Base.reset_subclasses
|
||||||
Dependencies.remove_subclasses_for(ActiveRecord::Base, ActiveRecord::Observer, ActionController::Base)
|
Reloadable.remove_classes_including
|
||||||
Dependencies.remove_subclasses_for(ActionMailer::Base) if defined?(ActionMailer::Base)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
Loading…
Reference in New Issue