Permalink
Browse files

Added reusable reloading support through the inclusion of the Relodab…

…le 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
  • Loading branch information...
1 parent 9404654 commit 01b1a8772928fbf31180341356981b95d0581413 @dhh dhh committed Jan 29, 2006
Showing with 298 additions and 74 deletions.
  1. +7 −0 actionmailer/lib/action_mailer/base.rb
  2. +7 −0 actionpack/lib/action_controller/base.rb
  3. +5 −4 actionpack/lib/action_controller/layout.rb
  4. +7 −0 actionpack/lib/action_controller/test_process.rb
  5. +1 −1 actionpack/test/template/text_helper_test.rb
  6. +1 −0 activerecord/lib/active_record/base.rb
  7. +7 −0 activerecord/lib/active_record/observer.rb
  8. +1 −1 activerecord/test/class_inheritable_attributes_test.rb
  9. +10 −0 activesupport/CHANGELOG
  10. +1 −2 activesupport/lib/active_support.rb
  11. +1 −1 activesupport/lib/active_support/clean_logger.rb
  12. +14 −2 activesupport/lib/active_support/core_ext/blank.rb
  13. +3 −0 activesupport/lib/active_support/core_ext/class.rb
  14. 0 ...support/lib/active_support/{class_attribute_accessors.rb → core_ext/class/attribute_accessors.rb}
  15. 0 ...t/lib/active_support/{class_inheritable_attributes.rb → core_ext/class/inheritable_attributes.rb}
  16. +21 −0 activesupport/lib/active_support/core_ext/class/removal.rb
  17. +0 −1 activesupport/lib/active_support/core_ext/exception.rb
  18. +2 −0 activesupport/lib/active_support/core_ext/module.rb
  19. 0 ...pport/lib/active_support/{module_attribute_accessors.rb → core_ext/module/attribute_accessors.rb}
  20. +15 −0 activesupport/lib/active_support/core_ext/module/inclusion.rb
  21. +2 −0 activesupport/lib/active_support/core_ext/object.rb
  22. +4 −43 activesupport/lib/active_support/core_ext/{object_and_class.rb → object/extending.rb}
  23. +16 −0 activesupport/lib/active_support/core_ext/object/misc.rb
  24. +52 −13 activesupport/lib/active_support/dependencies.rb
  25. +4 −0 activesupport/lib/active_support/reloadable.rb
  26. +2 −0 activesupport/test/autoloading_fixtures/a/b.rb
  27. +2 −0 activesupport/test/autoloading_fixtures/a/c/d.rb
  28. +2 −0 activesupport/test/autoloading_fixtures/e.rb
  29. +1 −1 activesupport/test/class_inheritable_attributes_test.rb
  30. +1 −1 activesupport/test/core_ext/blank_test.rb
  31. +37 −0 activesupport/test/core_ext/class_test.rb
  32. +51 −0 activesupport/test/core_ext/module_test.rb
  33. +2 −1 activesupport/test/core_ext/object_and_class_ext_test.rb
  34. +17 −0 activesupport/test/dependencies_test.rb
  35. +1 −1 activesupport/test/option_merger_test.rb
  36. +1 −2 railties/lib/dispatcher.rb
@@ -121,6 +121,13 @@ module ActionMailer
class Base
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:
cattr_accessor :template_root
@@ -224,6 +224,13 @@ def initialize(message = nil)
# FCGI.each_cgi{ |cgi| WeblogController.process_cgi(cgi) }
class Base
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.
# By default, it does.
@@ -1,16 +1,16 @@
module ActionController #:nodoc:
module Layout #:nodoc:
- def self.append_features(base)
- super
+ def self.included(base)
+ base.extend(ClassMethods)
base.class_eval do
alias_method :render_with_no_layout, :render
alias_method :render, :render_with_a_layout
class << self
alias_method :inherited_without_layout, :inherited
+ alias_method :inherited, :inherited_with_layout
end
end
- base.extend(ClassMethods)
end
# Layouts reverse the common pattern of including shared headers and footers in many templates to isolate changes in
@@ -172,8 +172,9 @@ def layout_conditions #:nodoc:
end
private
- def inherited(child)
+ def inherited_with_layout(child)
inherited_without_layout(child)
+ child.send :include, Reloadable
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?
end
@@ -333,6 +333,13 @@ def assigns(key = nil)
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
@response.session
end
@@ -3,7 +3,7 @@
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/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
include ActionView::Helpers::TextHelper
@@ -244,6 +244,7 @@ class Base
cattr_accessor :logger
def self.inherited(child) #:nodoc:
+ child.send :include, Reloadable
@@subclasses[self] ||= []
@@subclasses[self] << child
super
@@ -81,6 +81,13 @@ def observers=(*observers)
class Observer
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.
def self.observe(*models)
define_method(:observed_class) { models }
@@ -1,6 +1,6 @@
require 'test/unit'
require 'abstract_unit'
-require 'active_support/class_inheritable_attributes'
+require 'active_support/core_ext/class/inheritable_attributes'
class A
include ClassInheritableAttributes
@@ -1,5 +1,15 @@
*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 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__))
-require 'active_support/class_attribute_accessors'
-require 'active_support/class_inheritable_attributes'
require 'active_support/inflector'
require 'active_support/core_ext'
require 'active_support/clean_logger'
require 'active_support/dependencies'
+require 'active_support/reloadable'
require 'active_support/ordered_options'
require 'active_support/option_merger'
@@ -1,5 +1,5 @@
require 'logger'
-require File.dirname(__FILE__) + '/class_attribute_accessors'
+require File.dirname(__FILE__) + '/core_ext/class/attribute_accessors'
class Logger #:nodoc:
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:
def blank?
true
@@ -35,4 +47,4 @@ class Numeric #:nodoc:
def blank?
false
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
-
alias :clean_message :message
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 @@ def remove_subclasses_of(*superclasses)
Object.send(:remove_const, subclass.to_s) rescue nil
end
end
-
+
def subclasses_of(*superclasses)
subclasses = []
ObjectSpace.each_object(Class) do |k|
@@ -20,65 +20,26 @@ def extended_by
end
def copy_instance_variables_from(object, exclude = [])
- exclude += object.protected_instance_variables if
- object.respond_to? :protected_instance_variables
+ exclude += object.protected_instance_variables if object.respond_to? :protected_instance_variables
instance_variables = object.instance_variables - exclude.map { |name| name.to_s }
- instance_variables.each do |name|
- instance_variable_set name, object.instance_variable_get(name)
- end
+ instance_variables.each { |name| instance_variable_set(name, object.instance_variable_get(name)) }
end
def extend_with_included_modules_from(object)
object.extended_by.each { |mod| extend mod }
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
instance_variables.inject({}) do |values, name|
values[name[1..-1]] = instance_variable_get(name)
values
end
end
- def to_json
- ActiveSupport::JSON.encode(self)
- end
-
unless defined? instance_exec # 1.9
def instance_exec(*arguments, &block)
block.bind(self)[*arguments]
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
+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
Oops, something went wrong.

0 comments on commit 01b1a87

Please sign in to comment.