qualitysmith_extensions 0.0.34 → 0.0.49
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|