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
This commit is contained in:
Marcel Molina
2005-11-20 22:32:40 +00:00
parent 55a3979a09
commit baa2ab5ac3
3 changed files with 99 additions and 1 deletions

View File

@@ -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)

View File

@@ -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)

View File

@@ -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