qualitysmith_extensions 0.0.34 → 0.0.49
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/qualitysmith_extensions/array/shell_escape.rb +2 -2
- data/lib/qualitysmith_extensions/kernel/remove_const.rb +178 -0
- data/lib/qualitysmith_extensions/kernel/remove_module.rb +127 -0
- data/lib/qualitysmith_extensions/module/ancestry_of_instance_method.rb +43 -0
- data/lib/qualitysmith_extensions/module/attribute_accessors.rb +3 -0
- data/lib/qualitysmith_extensions/module/basename.rb +76 -0
- data/lib/qualitysmith_extensions/module/class_methods.rb +87 -0
- data/lib/qualitysmith_extensions/module/create.rb +315 -0
- data/lib/qualitysmith_extensions/module/dirname.rb +4 -0
- data/lib/qualitysmith_extensions/module/guard_method.rb +0 -1
- data/lib/qualitysmith_extensions/module/join.rb +66 -0
- data/lib/qualitysmith_extensions/module/module_methods.rb +4 -0
- data/lib/qualitysmith_extensions/module/namespace.rb +111 -0
- data/lib/qualitysmith_extensions/module/parents.rb +61 -0
- data/lib/qualitysmith_extensions/module/remove_const.rb +117 -0
- data/lib/qualitysmith_extensions/module/split.rb +55 -0
- data/lib/qualitysmith_extensions/object/ancestry_of_method.rb +257 -0
- data/lib/qualitysmith_extensions/object/methods.rb +7 -2
- data/lib/qualitysmith_extensions/string/constantize.rb +4 -0
- data/lib/qualitysmith_extensions/string/shell_escape.rb +1 -1
- data/lib/qualitysmith_extensions/symbol/constantize.rb +69 -0
- data/lib/qualitysmith_extensions/template.rb +1 -0
- data/lib/qualitysmith_extensions/test/assert_anything.rb +93 -0
- metadata +19 -3
- data/lib/qualitysmith_extensions/class/class_methods.rb +0 -5
@@ -0,0 +1,111 @@
|
|
1
|
+
#--
|
2
|
+
# Author:: Tyler Rick
|
3
|
+
# Copyright:: Copyright (c) 2007 QualitySmith, Inc.
|
4
|
+
# License:: Ruby License
|
5
|
+
# Submit to Facets?:: Yes.
|
6
|
+
# Developer notes::
|
7
|
+
# Changes::
|
8
|
+
#++
|
9
|
+
|
10
|
+
|
11
|
+
require 'rubygems'
|
12
|
+
require 'qualitysmith_extensions/symbol/constantize'
|
13
|
+
require 'qualitysmith_extensions/module/split'
|
14
|
+
|
15
|
+
|
16
|
+
class Module
|
17
|
+
# Return the module which contains this one; if this is a root module, such as
|
18
|
+
# +::MyModule+, then Object is returned.
|
19
|
+
def namespace
|
20
|
+
namespace_name = name.split('::')[0..-2].join('::')
|
21
|
+
namespace_name.empty? ? Object : namespace_name.constantize
|
22
|
+
end
|
23
|
+
|
24
|
+
# Gets the "dirname" of a "module path" (the string/symbol representing the namespace modules that it is contained in),
|
25
|
+
# in the same sense that <tt>File.dirname</tt> returns the dirname of a _filesystem_ path.
|
26
|
+
#
|
27
|
+
# Same as +namespace_of+, only this just returns the _name_ of the namespace module (as a string), rather than returning the
|
28
|
+
# constant itself.
|
29
|
+
#
|
30
|
+
# See also <tt>Module.basename</tt>
|
31
|
+
def self.dirname(module_or_name)
|
32
|
+
case module_or_name
|
33
|
+
when Module
|
34
|
+
module_or_name.namespace.name
|
35
|
+
when Symbol
|
36
|
+
Module.split_name(module_or_name)[0..-2].join('::')
|
37
|
+
when String
|
38
|
+
Module.split_name(module_or_name)[0..-2].join('::')
|
39
|
+
end
|
40
|
+
end
|
41
|
+
class << self
|
42
|
+
alias_method :namespace_name_of, :dirname
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.namespace_of(module_or_name)
|
46
|
+
namespace_name_of(module_or_name).constantize
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
|
52
|
+
|
53
|
+
# _____ _
|
54
|
+
# |_ _|__ ___| |_
|
55
|
+
# | |/ _ \/ __| __|
|
56
|
+
# | | __/\__ \ |_
|
57
|
+
# |_|\___||___/\__|
|
58
|
+
#
|
59
|
+
=begin test
|
60
|
+
require 'test/unit'
|
61
|
+
|
62
|
+
module OuterModule; end
|
63
|
+
module OuterModule::MiddleModule; end
|
64
|
+
module OuterModule::MiddleModule::InnerModule; end
|
65
|
+
|
66
|
+
class NamespaceTest < Test::Unit::TestCase
|
67
|
+
module InnerModule; end
|
68
|
+
def test_1
|
69
|
+
assert_equal Object, OuterModule.namespace
|
70
|
+
end
|
71
|
+
def test_nesting
|
72
|
+
assert_equal OuterModule::MiddleModule,
|
73
|
+
OuterModule::MiddleModule::InnerModule.namespace
|
74
|
+
end
|
75
|
+
def test_nesting_2
|
76
|
+
assert_equal NamespaceTest, InnerModule.namespace
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
class NamespaceOfTest < Test::Unit::TestCase
|
81
|
+
module InnerModule; end
|
82
|
+
def test_1
|
83
|
+
assert_equal Object, Module.namespace_of(OuterModule)
|
84
|
+
end
|
85
|
+
def test_nesting
|
86
|
+
assert_equal OuterModule::MiddleModule,
|
87
|
+
Module.namespace_of(OuterModule::MiddleModule::InnerModule)
|
88
|
+
assert_equal OuterModule::MiddleModule,
|
89
|
+
Module.namespace_of(:'OuterModule::MiddleModule::InnerModule')
|
90
|
+
assert_equal OuterModule::MiddleModule,
|
91
|
+
Module.namespace_of('OuterModule::MiddleModule::InnerModule')
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
class NamespaceNameOfTest < Test::Unit::TestCase
|
96
|
+
module InnerModule; end
|
97
|
+
def test_1
|
98
|
+
assert_equal 'Object',
|
99
|
+
Module.namespace_name_of(OuterModule)
|
100
|
+
end
|
101
|
+
def test_nesting
|
102
|
+
assert_equal 'OuterModule::MiddleModule',
|
103
|
+
Module.namespace_name_of(OuterModule::MiddleModule::InnerModule)
|
104
|
+
assert_equal 'OuterModule::MiddleModule',
|
105
|
+
Module.namespace_name_of(:'OuterModule::MiddleModule::InnerModule')
|
106
|
+
assert_equal 'OuterModule::MiddleModule',
|
107
|
+
Module.namespace_name_of('OuterModule::MiddleModule::InnerModule')
|
108
|
+
end
|
109
|
+
end
|
110
|
+
=end
|
111
|
+
|
@@ -0,0 +1,61 @@
|
|
1
|
+
#--
|
2
|
+
# Author:: Tyler Rick
|
3
|
+
# Copyright:: Copyright (c) ActiveSupport authors
|
4
|
+
# License::
|
5
|
+
# Submit to Facets?:: Yes.
|
6
|
+
# Developer notes::
|
7
|
+
# * Tests incomplete...
|
8
|
+
# Changes::
|
9
|
+
# * Copied from ActiveSupport.
|
10
|
+
#++
|
11
|
+
|
12
|
+
|
13
|
+
require 'rubygems'
|
14
|
+
require 'facets/core/kernel/constant'
|
15
|
+
|
16
|
+
|
17
|
+
class Module
|
18
|
+
# Return all the parents of this module, ordered from nested outwards. The
|
19
|
+
# receiver is not contained within the result.
|
20
|
+
def parents
|
21
|
+
parents = []
|
22
|
+
parts = name.split('::')[0..-2]
|
23
|
+
until parts.empty?
|
24
|
+
#parents << (parts * '::').constantize
|
25
|
+
parents << constant(parts * '::')
|
26
|
+
parts.pop
|
27
|
+
end
|
28
|
+
parents << Object unless parents.include? Object
|
29
|
+
parents
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
|
35
|
+
|
36
|
+
# _____ _
|
37
|
+
# |_ _|__ ___| |_
|
38
|
+
# | |/ _ \/ __| __|
|
39
|
+
# | | __/\__ \ |_
|
40
|
+
# |_|\___||___/\__|
|
41
|
+
#
|
42
|
+
=begin test
|
43
|
+
require 'test/unit'
|
44
|
+
|
45
|
+
module OuterModule; end
|
46
|
+
module OuterModule::InnerModule; end
|
47
|
+
|
48
|
+
class TheTest < Test::Unit::TestCase
|
49
|
+
module InnerModule; end
|
50
|
+
def test_1
|
51
|
+
assert_equal [Object], OuterModule.parents
|
52
|
+
end
|
53
|
+
def test_nesting
|
54
|
+
assert_equal [OuterModule, Object], OuterModule::InnerModule.parents
|
55
|
+
end
|
56
|
+
def test_nesting_2
|
57
|
+
assert_equal [TheTest, Object], InnerModule.parents
|
58
|
+
end
|
59
|
+
end
|
60
|
+
=end
|
61
|
+
|
@@ -0,0 +1,117 @@
|
|
1
|
+
#--
|
2
|
+
# Author:: Tyler Rick
|
3
|
+
# Copyright:: Copyright (c) 2007 QualitySmith, Inc.
|
4
|
+
# License:: Ruby License
|
5
|
+
# Submit to Facets?:: Yes.
|
6
|
+
# Developer notes::
|
7
|
+
#++
|
8
|
+
|
9
|
+
require 'rubygems'
|
10
|
+
require 'qualitysmith_extensions/object/ignore_access'
|
11
|
+
require 'qualitysmith_extensions/module/split'
|
12
|
+
require 'facets/core/module/by_name'
|
13
|
+
require 'facets/core/module/modspace'
|
14
|
+
|
15
|
+
module Kernel
|
16
|
+
# This is similar to +Kernel#remove_const+, but it _only_ works for modules/classes.
|
17
|
+
#
|
18
|
+
# This is similar to the built-in <tt>Module#remove_module</tt>, but it lets you do it in a more object oriented manner,
|
19
|
+
# calling +remove!+ on the module/class/constant itself that you want to remove, rather than on its parent.
|
20
|
+
#
|
21
|
+
# Makes it possible to write simply:
|
22
|
+
# A::B::C.remove_const!
|
23
|
+
# rather than having to think about which module the constant is actually defined in and calling +remove_const+ on that module.
|
24
|
+
# This is how you would have to otherwise do it:
|
25
|
+
# A::B.send(:remove_const, :C)
|
26
|
+
#
|
27
|
+
def remove_const!
|
28
|
+
if split.size > 1
|
29
|
+
parent_module = modspace # For example, would be A::B for A::B::C
|
30
|
+
const_to_remove = split.last # For example, would be :C for A::B::C
|
31
|
+
parent_module.ignore_access.remove_const(const_to_remove)
|
32
|
+
else
|
33
|
+
Object.ignore_access.remove_const(name)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# _____ _
|
39
|
+
# |_ _|__ ___| |_
|
40
|
+
# | |/ _ \/ __| __|
|
41
|
+
# | | __/\__ \ |_
|
42
|
+
# |_|\___||___/\__|
|
43
|
+
#
|
44
|
+
=begin test
|
45
|
+
require 'test/unit'
|
46
|
+
require 'qualitysmith_extensions/kernel/remove_const' # Test for compatibility. Just in case the remove_const_before_was_added_to_Kernel alias might have thrown something off.
|
47
|
+
|
48
|
+
# How it would be done *without* this extension:
|
49
|
+
module TestRemoveABC_TheOldWay
|
50
|
+
module A
|
51
|
+
module B
|
52
|
+
class C
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
class TheTest < Test::Unit::TestCase
|
58
|
+
def test_1
|
59
|
+
assert_nothing_raised { A::B::C }
|
60
|
+
A::B.send(:remove_const, :C)
|
61
|
+
assert_raise(NameError) { A::B::C }
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# How it would be done *with* this extension:
|
67
|
+
module TestRemoveABC
|
68
|
+
module A
|
69
|
+
module B
|
70
|
+
class C
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
class TheTest < Test::Unit::TestCase
|
76
|
+
def test_1
|
77
|
+
assert_nothing_raised { A::B::C }
|
78
|
+
A::B::C.remove_const!
|
79
|
+
assert_raise(NameError) { A::B::C }
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
module TestRemoveAB
|
85
|
+
module A
|
86
|
+
module B
|
87
|
+
module C
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
class TheTest < Test::Unit::TestCase
|
93
|
+
def test_1
|
94
|
+
assert_nothing_raised { A::B }
|
95
|
+
A::B.remove_const!
|
96
|
+
assert_raise(NameError) { A::B }
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
module A
|
102
|
+
end
|
103
|
+
module TestRemoveA_FromObject
|
104
|
+
|
105
|
+
class TheTest < Test::Unit::TestCase
|
106
|
+
def test_1
|
107
|
+
assert_nothing_raised { A }
|
108
|
+
A.remove_const!
|
109
|
+
assert_raise(NameError) { A }
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
=end
|
115
|
+
|
116
|
+
|
117
|
+
|
@@ -0,0 +1,55 @@
|
|
1
|
+
#--
|
2
|
+
# Author:: Tyler Rick
|
3
|
+
# Copyright:: Copyright (c) 2007 QualitySmith, Inc.
|
4
|
+
# License:: Ruby License
|
5
|
+
# Submit to Facets?:: Yes!
|
6
|
+
# Developer notes::
|
7
|
+
#++
|
8
|
+
|
9
|
+
require 'rubygems'
|
10
|
+
require 'facets/core/symbol/to_proc'
|
11
|
+
|
12
|
+
class Module
|
13
|
+
# Very similar to Facets' +Module#nesting+, but, whereas +nesting+ will break <tt>A::B</tt> into an array of _constants_ represting nesting
|
14
|
+
# (<tt>[A, A::B]</tt>), this method will split it into an array of _symbols_: <tt>[:A, :B]</tt>.
|
15
|
+
#
|
16
|
+
# Note that the second element in this array, <tt>:B</tt>, is _not_ fully qualified, so you could not do a <tt>const_get</tt>
|
17
|
+
# on that symbol.
|
18
|
+
def split
|
19
|
+
name.split(/::/).map(&:to_sym)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Like Module#split, only this operates on a string/symbol. Useful for when you don't want to or can't actually instantiate
|
23
|
+
# the module represented by the symbol.
|
24
|
+
def self.split_name(name)
|
25
|
+
name.to_s.split(/::/).map(&:to_sym)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
# _____ _
|
31
|
+
# |_ _|__ ___| |_
|
32
|
+
# | |/ _ \/ __| __|
|
33
|
+
# | | __/\__ \ |_
|
34
|
+
# |_|\___||___/\__|
|
35
|
+
#
|
36
|
+
=begin test
|
37
|
+
require 'test/unit'
|
38
|
+
|
39
|
+
module A
|
40
|
+
module B
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class TheTest < Test::Unit::TestCase
|
45
|
+
def test_A
|
46
|
+
assert_equal [:A], A.split
|
47
|
+
end
|
48
|
+
def test_A_B
|
49
|
+
assert_equal [:A, :B], A::B.split
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
=end
|
54
|
+
|
55
|
+
|
@@ -0,0 +1,257 @@
|
|
1
|
+
#--
|
2
|
+
# Author:: Tyler Rick
|
3
|
+
# Copyright:: Copyright (c) 2007 QualitySmith, Inc.
|
4
|
+
# License:: Ruby License
|
5
|
+
# Submit to Facets?:: Yes.
|
6
|
+
# Developer notes::
|
7
|
+
# * May not have taken every single case into consideration. Needs a bit more testing.
|
8
|
+
# * public/private/protected?
|
9
|
+
# * Rename to origin_of_method (or source_of_method)?? Since strictly speaking it may return a method that is not from any *ancestors* but is from the Class class.
|
10
|
+
#++
|
11
|
+
|
12
|
+
require 'rubygems'
|
13
|
+
require 'qualitysmith_extensions/module/class_methods'
|
14
|
+
require 'qualitysmith_extensions/module/ancestry_of_instance_method'
|
15
|
+
|
16
|
+
|
17
|
+
class Object
|
18
|
+
# Returns the module/class which defined the given method. If more than one module/class defined the method, returns the _closest_
|
19
|
+
# ancestor to have defined it (would be +self+ if it is defined in +self+).
|
20
|
+
#
|
21
|
+
# This is (as far as I know -- patches welcome) <b>the method that would _would_ be called if you actually called the method</b>.
|
22
|
+
# So if you override
|
23
|
+
#
|
24
|
+
# It does this by first checking
|
25
|
+
# searching the methods defined in each ancestor in turn (in the order that <tt>self.ancestors</tt> returns them) and
|
26
|
+
# returning the first module/class that satisfies the search.
|
27
|
+
#
|
28
|
+
# This looks at the results of <tt>methods</tt>, which means that if you call this on a module/class, it will _not_ return
|
29
|
+
# any instance methods, only _class_ methods.
|
30
|
+
#
|
31
|
+
# class Base
|
32
|
+
# def self.it; end
|
33
|
+
# end
|
34
|
+
# class SubWithIt < Base
|
35
|
+
# def self.it; end
|
36
|
+
# end
|
37
|
+
# class SubWithoutIt < Base
|
38
|
+
# end
|
39
|
+
# SubWithIt.ancestry_of_instance_method(:it) # => SubWithIt # (Stops with self)
|
40
|
+
# SubWithoutIt.ancestry_of_instance_method(:it) # => Base # (Goes one step up the ancestry tree)
|
41
|
+
#
|
42
|
+
# If you call this on an object that is _not_ a module or a class (in other words, if you call it on an _instance_ of some
|
43
|
+
# class), then it will assume you actually want to know about an _instance_ method defined in self.class or one of the
|
44
|
+
# ancestors of self.class. (Since non-modules don't even technically have the concept of _ancestors_.) Therefore, this:
|
45
|
+
# class Klass
|
46
|
+
# def it; end
|
47
|
+
# end
|
48
|
+
# o = Klass.new
|
49
|
+
# o.ancestry_of_method(:it) # => Klass
|
50
|
+
# is really just a shorthand way of doing:
|
51
|
+
# o.class.ancestry_of_instance_method(:it) # => Klass
|
52
|
+
#
|
53
|
+
# If the method is a singleton method of +self+, it will return +self+:
|
54
|
+
# class << (foo = SubWithIt.new)
|
55
|
+
# def it; end
|
56
|
+
# end
|
57
|
+
# foo.ancestry_of_method(:it) # => #<SubWithIt:0xb7e5614c>
|
58
|
+
#
|
59
|
+
# Returns nil if it cannot be found in self or in any ancestor.
|
60
|
+
def ancestry_of_method(method_name)
|
61
|
+
method_name = method_name.to_s
|
62
|
+
(self if self.methods(false).include?(method_name)) \
|
63
|
+
||
|
64
|
+
if self.is_a?(Module)
|
65
|
+
self.ancestors.find do |ancestor|
|
66
|
+
ancestor.methods(false).include? method_name
|
67
|
+
end or
|
68
|
+
# The above search does not take into account *instance* methods provided by Class, Module, or Kernel.
|
69
|
+
# Remember that ancestors and instances/class/superclass are different concepts, and that although classes/modules
|
70
|
+
# do not have Class or Module as an "ancestor", they are still *instances* of Module or Class (which is a subclass of module).
|
71
|
+
# self.ancestors does NOT include Class or Module, and yet we're still able to "inherit" instance methods from Class or Module.
|
72
|
+
# So we have to do this extra search in case the method came from one of the instance methods of Class or Module or Kernel
|
73
|
+
# (are there any other cases I'm missing?).
|
74
|
+
begin
|
75
|
+
# self.class.ancestors is usually [Class, Module, Object, PP::ObjectMixin, Kernel]
|
76
|
+
self.class.ancestors.find do |ancestor|
|
77
|
+
ancestor.instance_methods(false).include? method_name
|
78
|
+
# || ancestor.private_instance_method_defined?( method_name.to_sym )
|
79
|
+
end
|
80
|
+
end
|
81
|
+
else
|
82
|
+
self.class.ancestry_of_instance_method(method_name)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# _____ _
|
88
|
+
# |_ _|__ ___| |_
|
89
|
+
# | |/ _ \/ __| __|
|
90
|
+
# | | __/\__ \ |_
|
91
|
+
# |_|\___||___/\__|
|
92
|
+
#
|
93
|
+
=begin test
|
94
|
+
require 'test/unit'
|
95
|
+
require 'rubygems'
|
96
|
+
require 'qualitysmith_extensions/test/assert_anything'
|
97
|
+
|
98
|
+
class Base
|
99
|
+
def it; end
|
100
|
+
end
|
101
|
+
class SubWithIt < Base
|
102
|
+
def it; end
|
103
|
+
end
|
104
|
+
class SubWithoutIt < Base
|
105
|
+
end
|
106
|
+
|
107
|
+
class << ($with_singleton_method = SubWithIt.new)
|
108
|
+
def it; end
|
109
|
+
end
|
110
|
+
|
111
|
+
class ClassyBase
|
112
|
+
def self.classy_it; end
|
113
|
+
end
|
114
|
+
class ClassySubWithIt < ClassyBase
|
115
|
+
def self.classy_it; end
|
116
|
+
end
|
117
|
+
class ClassySubWithoutIt < ClassyBase
|
118
|
+
end
|
119
|
+
|
120
|
+
class << ($class_with_singleton_method = ClassySubWithIt)
|
121
|
+
def classy_it; end
|
122
|
+
end
|
123
|
+
|
124
|
+
class ATest < Test::Unit::TestCase
|
125
|
+
def test_non_existent_method
|
126
|
+
assert_equal nil, Base.ancestry_of_method(:not_a_method)
|
127
|
+
assert_equal nil, Base.ancestry_of_instance_method(:not_a_method)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
class InstanceMethodsTest < Test::Unit::TestCase
|
132
|
+
def test_1
|
133
|
+
assert_equal [SubWithoutIt, Base, Object, PP::ObjectMixin, Kernel], SubWithoutIt.ancestors
|
134
|
+
assert_equal Base, Base.ancestry_of_instance_method(:it)
|
135
|
+
assert_equal Base, SubWithoutIt.ancestry_of_instance_method(:it)
|
136
|
+
assert_equal SubWithIt, SubWithIt.ancestry_of_instance_method(:it)
|
137
|
+
assert_equal SubWithIt, SubWithIt.ancestry_of_instance_method(:it)
|
138
|
+
end
|
139
|
+
def test_ancestry_of_method__falls_back_to_using__ancestry_of_instance_method__if_is_an_instance
|
140
|
+
assert_include? Base.instance_methods, :it.to_s
|
141
|
+
assert_equal Base, Base.new.ancestry_of_method(:it)
|
142
|
+
assert_equal Base, SubWithoutIt.new.ancestry_of_method(:it)
|
143
|
+
assert_equal SubWithIt, SubWithIt.new.ancestry_of_method(:it)
|
144
|
+
|
145
|
+
# In other words, it's a *shortcut*. See?:
|
146
|
+
o = SubWithIt.new
|
147
|
+
assert_equal o.class.ancestry_of_instance_method(:it), o.ancestry_of_method(:it)
|
148
|
+
end
|
149
|
+
def test_singleton_method
|
150
|
+
assert_equal $with_singleton_method, $with_singleton_method.ancestry_of_method(:it)
|
151
|
+
end
|
152
|
+
def test_that_you_cant_use_ancestry_of_instance_method_for_instances
|
153
|
+
# undefined method `ancestors' for #<SubWithIt:0xb7e0fbc0>
|
154
|
+
assert_raise(NoMethodError) { SubWithIt.new.ancestry_of_instance_method(:it) }
|
155
|
+
assert_raise(NoMethodError) { $with_singleton_method.ancestry_of_instance_method(:it) }
|
156
|
+
end
|
157
|
+
end
|
158
|
+
class ClassMethodsTest < Test::Unit::TestCase
|
159
|
+
def test_ancestry_of_method_doesnt_return_instance_methods
|
160
|
+
assert_include? Base.instance_methods, :it.to_s
|
161
|
+
assert_not_include? Base.methods, :it.to_s
|
162
|
+
|
163
|
+
assert_equal [SubWithoutIt, Base, Object, PP::ObjectMixin, Kernel], SubWithoutIt.ancestors
|
164
|
+
|
165
|
+
assert_equal nil, Base.ancestry_of_method(:it)
|
166
|
+
assert_equal nil, SubWithoutIt.ancestry_of_method(:it)
|
167
|
+
assert_equal nil, SubWithIt.ancestry_of_method(:it)
|
168
|
+
end
|
169
|
+
def test_ancestry_of_method_does_return_class_methods
|
170
|
+
assert_include? ClassyBase.methods, :classy_it.to_s
|
171
|
+
assert_not_include? ClassyBase.instance_methods, :classy_it.to_s
|
172
|
+
|
173
|
+
assert_equal [ClassySubWithoutIt, ClassyBase, Object, PP::ObjectMixin, Kernel], ClassySubWithoutIt.ancestors
|
174
|
+
|
175
|
+
assert_equal ClassyBase, ClassySubWithoutIt.ancestry_of_method(:classy_it)
|
176
|
+
assert_equal ClassyBase, ClassyBase.ancestry_of_method(:classy_it)
|
177
|
+
assert_equal ClassySubWithIt, ClassySubWithIt.ancestry_of_method(:classy_it)
|
178
|
+
end
|
179
|
+
def test_singleton_method
|
180
|
+
assert_equal $class_with_singleton_method, $class_with_singleton_method.ancestry_of_method(:classy_it)
|
181
|
+
assert_equal nil, $class_with_singleton_method.ancestry_of_instance_method(:classy_it)
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
class BuiltInMethodsTest < Test::Unit::TestCase
|
186
|
+
def test_1
|
187
|
+
assert_equal [Object, PP::ObjectMixin, Kernel], Object.ancestors
|
188
|
+
assert_equal Kernel, Object.ancestry_of_method(:binding)
|
189
|
+
assert_equal Kernel, Object.ancestry_of_method(:require)
|
190
|
+
assert_equal Kernel, Object.ancestry_of_method(:proc)
|
191
|
+
end
|
192
|
+
|
193
|
+
def test_looks_at_Class_Module_and_Kernel_instance_methods_if_necessary
|
194
|
+
# Sometimes it inherits a method NOT from any of its ancestors, but from Class (one of the *instance methods* of Class).
|
195
|
+
|
196
|
+
# (Class is *not* an ancestor of Object and yet that appears to be where these methods come from.)
|
197
|
+
assert_not_include? Object.ancestors, Class
|
198
|
+
assert_equal Class, Object.class
|
199
|
+
[
|
200
|
+
:superclass,
|
201
|
+
:new,
|
202
|
+
:allocate,
|
203
|
+
].each do |method|
|
204
|
+
assert_ancestry_of_method_is Object, method, Class
|
205
|
+
end
|
206
|
+
|
207
|
+
# superclass (and others) comes from Class, but instance_variable_get (and others) come from Module or Kernel.
|
208
|
+
# (See below for more examples)
|
209
|
+
assert_equal true, Class.instance_methods(false).include?('superclass')
|
210
|
+
assert_equal false, Class.instance_methods(false).include?('instance_variable_get')
|
211
|
+
assert_equal true, Kernel.instance_methods(false).include?('instance_variable_get')
|
212
|
+
|
213
|
+
# (Module is *not* an ancestor of Object and yet that appears to be where these methods come from.)
|
214
|
+
assert_not_include? Object.ancestors, Module
|
215
|
+
[
|
216
|
+
:instance_methods,
|
217
|
+
:included_modules,
|
218
|
+
:constants,
|
219
|
+
:ancestors,
|
220
|
+
:public_method_defined?,
|
221
|
+
].each do |method|
|
222
|
+
assert_equal Module, Object.ancestry_of_method(method), "Failed for #{method}"
|
223
|
+
end
|
224
|
+
|
225
|
+
# (Kernel *is* an ancestor of Object, but these methods come from Kernel.instance_methods and *not* from Kernel.methods.)
|
226
|
+
assert_include? Object.ancestors, Kernel
|
227
|
+
[
|
228
|
+
:puts,
|
229
|
+
:system,
|
230
|
+
:inspect,
|
231
|
+
:send,
|
232
|
+
:private_methods,
|
233
|
+
:instance_variable_get,
|
234
|
+
].each do |method|
|
235
|
+
assert_equal Kernel, Object.ancestry_of_method(method)
|
236
|
+
end
|
237
|
+
|
238
|
+
# proc apparently comes from *class method* Kernel.proc,
|
239
|
+
# while instance_variable_get comes from *intance method* Kernel.instance_variable_get
|
240
|
+
assert_equal true, Kernel.class_methods(false).include?('proc')
|
241
|
+
assert_equal false, Kernel.instance_methods(false).include?('proc')
|
242
|
+
assert_equal false, Kernel.class_methods(false).include?('instance_variable_get')
|
243
|
+
assert_equal true, Kernel.instance_methods(false).include?('instance_variable_get')
|
244
|
+
|
245
|
+
# Where does this method come from then???
|
246
|
+
[
|
247
|
+
:remove_class_variable,
|
248
|
+
:remove_const,
|
249
|
+
:remove_method,
|
250
|
+
:undef_method,
|
251
|
+
:nesting,
|
252
|
+
].each do |method|
|
253
|
+
assert_equal nil, Object.ancestry_of_method(method)
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end
|
257
|
+
=end
|