aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarcel Molina <marcel@vernix.org>2005-11-20 22:32:40 +0000
committerMarcel Molina <marcel@vernix.org>2005-11-20 22:32:40 +0000
commitbaa2ab5ac30404bce5b5fddaa0d37322280fb48e (patch)
treeabd7fef85ef4a167ec5941f6e614d5e57da11db1
parent55a3979a098d05158066ea3e53d0cdb66e88638c (diff)
downloadrails-baa2ab5ac30404bce5b5fddaa0d37322280fb48e.tar.gz
rails-baa2ab5ac30404bce5b5fddaa0d37322280fb48e.tar.bz2
rails-baa2ab5ac30404bce5b5fddaa0d37322280fb48e.zip
Add extended_by, extend_with_included_modules_from and copy_instance_variables_from to Object.
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@3113 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
-rw-r--r--activesupport/CHANGELOG5
-rw-r--r--activesupport/lib/active_support/core_ext/object_and_class.rb21
-rw-r--r--activesupport/test/core_ext/object_and_class_ext_test.rb74
3 files changed, 99 insertions, 1 deletions
diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG
index 5aa7d23de3..0de240ff91 100644
--- a/activesupport/CHANGELOG
+++ b/activesupport/CHANGELOG
@@ -1,5 +1,10 @@
*SVN*
+* Added the following methods [Marcel Molina Jr., Sam Stephenson]:
+ * Object#copy_instance_variables_from(object) to copy instance variables from one object to another
+ * Object#extended_by to get an instance's included/extended modules
+ * Object#extend_with_included_modules_from(object) to extend an instance with the modules from another instance
+
* Rename Version constant to VERSION. #2802 [Marcel Molina Jr.]
*1.2.3* (November 7th, 2005)
diff --git a/activesupport/lib/active_support/core_ext/object_and_class.rb b/activesupport/lib/active_support/core_ext/object_and_class.rb
index 1e080d35a4..7864c1a9dc 100644
--- a/activesupport/lib/active_support/core_ext/object_and_class.rb
+++ b/activesupport/lib/active_support/core_ext/object_and_class.rb
@@ -13,7 +13,26 @@ class Object #:nodoc:
end
subclasses
end
-
+
+ def extended_by
+ ancestors = class << self; ancestors end
+ ancestors.select { |mod| mod.class == Module } - [ Object, Kernel ]
+ end
+
+ def copy_instance_variables_from(object, exclude = [])
+ 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
+ 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)
diff --git a/activesupport/test/core_ext/object_and_class_ext_test.rb b/activesupport/test/core_ext/object_and_class_ext_test.rb
index 29e18d5ae1..4a554e7602 100644
--- a/activesupport/test/core_ext/object_and_class_ext_test.rb
+++ b/activesupport/test/core_ext/object_and_class_ext_test.rb
@@ -6,6 +6,18 @@ class ClassB < ClassA; end
class ClassC < ClassB; end
class ClassD < ClassA; end
+module Bar
+ def bar; end
+end
+
+module Baz
+ def baz; end
+end
+
+class Foo
+ include Bar
+end
+
class ClassExtTest < Test::Unit::TestCase
def test_methods
assert defined?(ClassB)
@@ -30,4 +42,66 @@ class ObjectTests < Test::Unit::TestCase
suppress(LoadError, ArgumentError) { raise LoadError }
suppress(LoadError, ArgumentError) { raise ArgumentError }
end
+
+ def test_extended_by
+ foo = Foo.new
+ assert_equal [Bar], foo.extended_by
+ foo.extend(Baz)
+ assert_equal %w(Bar Baz), foo.extended_by.map {|mod| mod.name}.sort
+ end
+
+ def test_extend_with_included_modules_from
+ foo, object = Foo.new, Object.new
+ assert !object.respond_to?(:bar)
+ assert !object.respond_to?(:baz)
+
+ object.extend_with_included_modules_from(foo)
+ assert object.respond_to?(:bar)
+ assert !object.respond_to?(:baz)
+
+ foo.extend(Baz)
+ object.extend_with_included_modules_from(foo)
+ assert object.respond_to?(:bar)
+ assert object.respond_to?(:baz)
+ end
+
end
+
+class ObjectInstanceVariableTest < Test::Unit::TestCase
+ def setup
+ @source, @dest = Object.new, Object.new
+ @source.instance_variable_set(:@bar, 'bar')
+ @source.instance_variable_set(:@baz, 'baz')
+ end
+
+ def test_copy_instance_variables_from_without_explicit_excludes
+ assert_equal [], @dest.instance_variables
+ @dest.copy_instance_variables_from(@source)
+
+ assert_equal %w(@bar @baz), @dest.instance_variables.sort
+ %w(@bar @baz).each do |name|
+ assert_equal @source.instance_variable_get(name).object_id,
+ @dest.instance_variable_get(name).object_id
+ end
+ end
+
+ def test_copy_instance_variables_from_with_explicit_excludes
+ @dest.copy_instance_variables_from(@source, ['@baz'])
+ assert_nil @dest.instance_variable_get('@baz')
+ assert_equal 'bar', @dest.instance_variable_get('@bar')
+ end
+
+ def test_copy_instance_variables_automatically_excludes_protected_instance_variables
+ @source.instance_variable_set(:@quux, 'quux')
+ class << @source
+ def protected_instance_variables
+ ['@bar', :@quux]
+ end
+ end
+
+ @dest.copy_instance_variables_from(@source)
+ assert_nil @dest.instance_variable_get('@bar')
+ assert_nil @dest.instance_variable_get('@quux')
+ assert_equal 'baz', @dest.instance_variable_get('@baz')
+ end
+end \ No newline at end of file