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.
Files changed (25) hide show
  1. data/lib/qualitysmith_extensions/array/shell_escape.rb +2 -2
  2. data/lib/qualitysmith_extensions/kernel/remove_const.rb +178 -0
  3. data/lib/qualitysmith_extensions/kernel/remove_module.rb +127 -0
  4. data/lib/qualitysmith_extensions/module/ancestry_of_instance_method.rb +43 -0
  5. data/lib/qualitysmith_extensions/module/attribute_accessors.rb +3 -0
  6. data/lib/qualitysmith_extensions/module/basename.rb +76 -0
  7. data/lib/qualitysmith_extensions/module/class_methods.rb +87 -0
  8. data/lib/qualitysmith_extensions/module/create.rb +315 -0
  9. data/lib/qualitysmith_extensions/module/dirname.rb +4 -0
  10. data/lib/qualitysmith_extensions/module/guard_method.rb +0 -1
  11. data/lib/qualitysmith_extensions/module/join.rb +66 -0
  12. data/lib/qualitysmith_extensions/module/module_methods.rb +4 -0
  13. data/lib/qualitysmith_extensions/module/namespace.rb +111 -0
  14. data/lib/qualitysmith_extensions/module/parents.rb +61 -0
  15. data/lib/qualitysmith_extensions/module/remove_const.rb +117 -0
  16. data/lib/qualitysmith_extensions/module/split.rb +55 -0
  17. data/lib/qualitysmith_extensions/object/ancestry_of_method.rb +257 -0
  18. data/lib/qualitysmith_extensions/object/methods.rb +7 -2
  19. data/lib/qualitysmith_extensions/string/constantize.rb +4 -0
  20. data/lib/qualitysmith_extensions/string/shell_escape.rb +1 -1
  21. data/lib/qualitysmith_extensions/symbol/constantize.rb +69 -0
  22. data/lib/qualitysmith_extensions/template.rb +1 -0
  23. data/lib/qualitysmith_extensions/test/assert_anything.rb +93 -0
  24. metadata +19 -3
  25. data/lib/qualitysmith_extensions/class/class_methods.rb +0 -5
@@ -2,11 +2,11 @@
2
2
  # Author:: Tyler Rick
3
3
  # Copyright:: Copyright (c) 2007 QualitySmith, Inc.
4
4
  # License:: Ruby License
5
- # Submit to Facets?:: Yes. Symbol#to_proc -> Facets
5
+ # Submit to Facets?:: Yes.
6
6
  #++
7
7
 
8
8
  require 'rubygems'
9
- require 'extensions/symbol' unless Symbol.method_defined?(:to_proc)
9
+ require 'facets/core/symbol/to_proc' unless Symbol.method_defined?(:to_proc)
10
10
  require 'facets/core/kernel/require_local'
11
11
  require_local '../string/shell_escape.rb'
12
12
 
@@ -0,0 +1,178 @@
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
+ class Module
16
+ alias_method :remove_const_before_was_added_to_Kernel, :remove_const
17
+ end
18
+ module Kernel
19
+ # This is similar to the built-in <tt>Module#remove_const</tt>, but it is accessible from all "levels" (because it is defined
20
+ # in +Kernel+) and can handle hierarchy.
21
+ #
22
+ # Makes it possible to write simply:
23
+ # remove_const(A::B::C.name)
24
+ # rather than having to think about which module the constant is actually defined in and calling +remove_const+ on that module.
25
+ #
26
+ # This is how you would otherwise have to do it:
27
+ # A::B.send(:remove_const, :C)
28
+ #
29
+ # +const_name+ must be an object that responds to +to_s+.
30
+ #
31
+ # +const_name+ must be a <i>fully qualified name</i>. For example, this will not work as expected:
32
+ #
33
+ # module Mod
34
+ # Foo = 'foo'
35
+ # remove_const(:Foo)
36
+ # end
37
+ #
38
+ # because it will try to remove ::Foo instead of Mod::Foo. Fortunately, however, this will work as expected:
39
+ #
40
+ # module Mod
41
+ # Foo = 'foo'
42
+ # remove_const(Foo.name)
43
+ # end
44
+ #
45
+ # This method is partially inspired by Facets' Kernel#constant method, which provided a more user-friendly alternative to const_get.
46
+ #
47
+ def remove_const(const_name)
48
+ #require 'pp'
49
+ #puts "remove_const(#{const_name})"
50
+ raise ArgumentError unless const_name.respond_to?(:to_s)
51
+ nesting = const_name.to_s.split(/::/).map(&:to_sym)
52
+ if nesting.size > 1
53
+ parent_module = constant(nesting[0..-2].join('::')) # For example, would be A::B for A::B::C
54
+ const_to_remove = nesting[-1] # For example, would be :C for A::B::C
55
+ parent_module.ignore_access.remove_const_before_was_added_to_Kernel(const_to_remove)
56
+ else
57
+ ignore_access.remove_const_before_was_added_to_Kernel(const_name)
58
+ end
59
+ end
60
+ end
61
+
62
+ #p Module.private_instance_methods.grep(/remove_const/) # Lists it
63
+ Module.send(:remove_method, :remove_const)
64
+ #p Module.instance_methods.grep(/remove_const/) # Does list it, because inherits *public* remove_const from Kernel
65
+ #p Module.private_instance_methods.grep(/remove_const/) # Does not list it, because it's no longer private
66
+ Module.send(:define_method, :remove_const, Kernel.method(:remove_const))
67
+ #p Module.private_instance_methods.grep(/remove_const/) # Lists it
68
+
69
+ # _____ _
70
+ # |_ _|__ ___| |_
71
+ # | |/ _ \/ __| __|
72
+ # | | __/\__ \ |_
73
+ # |_|\___||___/\__|
74
+ #
75
+ =begin test
76
+ require 'test/unit'
77
+
78
+ # Important regression test. This was failing at one point.
79
+ module A
80
+ B = nil
81
+ remove_const :B
82
+ end
83
+
84
+ # How it would be done *without* this extension:
85
+ module TestRemoveABC_TheOldWay
86
+ module A
87
+ module B
88
+ C = 'foo'
89
+ end
90
+ end
91
+
92
+ class TheTest < Test::Unit::TestCase
93
+ def test_1
94
+ assert_nothing_raised { A::B::C }
95
+ A::B.send(:remove_const, :C)
96
+ assert_raise(NameError) { A::B::C }
97
+ end
98
+ end
99
+ end
100
+
101
+ # How it would be done *with* this extension (all tests that follow):
102
+
103
+ module TestRemoveABC_CIsString
104
+ module A
105
+ module B
106
+ C = 'foo'
107
+ end
108
+ end
109
+
110
+ class TheTest < Test::Unit::TestCase
111
+ def test_1
112
+ assert_nothing_raised { A::B::C }
113
+ assert_raise(NoMethodError) { remove_const(A::B::C.name) } # Because C is a *string*, not a *module*
114
+ assert_nothing_raised { remove_const A::B.name + '::C' }
115
+ assert_raise(NameError) { A::B::C }
116
+ end
117
+ end
118
+ end
119
+
120
+ module TestRemoveAB_UsingName
121
+ module A
122
+ module B
123
+ end
124
+ end
125
+
126
+ class TheTest < Test::Unit::TestCase
127
+ def test_1
128
+ assert_nothing_raised { A::B }
129
+ remove_const(A::B.name)
130
+ assert_raise(NameError) { A::B }
131
+ end
132
+ end
133
+ end
134
+
135
+ module TestRemoveAB_Symbol
136
+ module A
137
+ module B
138
+ Foo = :Foo
139
+ end
140
+ end
141
+
142
+ remove_const(:'A::B::Foo') # This tests that Module#remove_const was overriden as well.
143
+ # If we hadn't also overriden Module#remove_const, then this would have caused this error:
144
+ # in `remove_const': `A::B::Foo' is not allowed as a constant name (NameError)
145
+
146
+ class TheTest < Test::Unit::TestCase
147
+ def test_1
148
+ assert_nothing_raised { A::B }
149
+
150
+ assert_equal 'TestRemoveAB_Symbol::A', A.name
151
+ assert_raise(NameError) { remove_const(:'A::B') } # This doesn't work because A, when evaluated in this context,
152
+ # is TestRemoveAB_Symbol::TheTest::A, which is *not* defined.
153
+
154
+ remove_const(:'TestRemoveAB_Symbol::A::B')
155
+ assert_raise(NameError) { A::B }
156
+ end
157
+ end
158
+ end
159
+
160
+ module TestRemoveAB_Symbol2
161
+ class TheTest < Test::Unit::TestCase
162
+ module A
163
+ module B
164
+ end
165
+ end
166
+ def test_1
167
+ assert_nothing_raised { A::B }
168
+
169
+ assert_equal 'TestRemoveAB_Symbol2::TheTest::A', A.name
170
+ remove_const(:'A::B') # Does work, because A is defined *within* TheTest this time.
171
+ assert_raise(NameError) { A::B }
172
+ end
173
+ end
174
+ end
175
+
176
+ =end
177
+
178
+
@@ -0,0 +1,127 @@
1
+ #--
2
+ # Author:: Tyler Rick
3
+ # Copyright:: Copyright (c) 2007 QualitySmith, Inc.
4
+ # License:: Ruby License
5
+ # Submit to Facets?:: No.
6
+ # Developer notes::
7
+ # * Deprecated by qualitysmith_extensions/module/remove.rb
8
+ #++
9
+
10
+ require 'rubygems'
11
+ require 'qualitysmith_extensions/object/ignore_access'
12
+ require 'qualitysmith_extensions/module/split'
13
+ require 'facets/core/module/by_name'
14
+ require 'facets/core/module/modspace'
15
+
16
+ module Kernel
17
+ # This is similar to +remove_const+, but it _only_ works for modules/classes.
18
+ #
19
+ # This is similar to the built-in <tt>Module#remove_module</tt>, but it is accessible from all "levels" (because it is defined
20
+ # in +Kernel+) and can handle hierarchy.
21
+ #
22
+ # Makes it possible to write simply:
23
+ # remove_module(A::B::C)
24
+ # rather than having to think about which module the constant is actually defined in and calling +remove_const+ on that module.
25
+ # This is how you would have to otherwise do it:
26
+ # A::B.send(:remove_const, :C)
27
+ #
28
+ # You can pass in either a constant or a symbol. Passing in a constant is preferred
29
+ #
30
+ # This method is partially inspired by Facets' Kernel#constant method, which provided a more user-friendly alternative to const_get.
31
+ #
32
+ def remove_module(const)
33
+ const = Module.by_name(const.to_s) if const.is_a?(Symbol)
34
+ if const.split.size > 1
35
+ parent_module = const.modspace # For example, would be A::B for A::B::C
36
+ const_to_remove = const.split.last # For example, would be :C for A::B::C
37
+ parent_module.ignore_access.remove_const(const_to_remove)
38
+ else
39
+ Object.ignore_access.remove_const(const.name)
40
+ end
41
+ end
42
+ end
43
+
44
+ # _____ _
45
+ # |_ _|__ ___| |_
46
+ # | |/ _ \/ __| __|
47
+ # | | __/\__ \ |_
48
+ # |_|\___||___/\__|
49
+ #
50
+ =begin test
51
+ require 'test/unit'
52
+ 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.
53
+
54
+ # How it would be done *without* this extension:
55
+ module TestRemoveABC_TheOldWay
56
+ module A
57
+ module B
58
+ class C
59
+ end
60
+ end
61
+ end
62
+
63
+ class TheTest < Test::Unit::TestCase
64
+ def test_1
65
+ assert_nothing_raised { A::B::C }
66
+ A::B.send(:remove_const, :C)
67
+ assert_raise(NameError) { A::B::C }
68
+ end
69
+ end
70
+ end
71
+
72
+ # How it would be done *with* this extension:
73
+ module TestRemoveABC
74
+ module A
75
+ module B
76
+ class C
77
+ end
78
+ end
79
+ end
80
+
81
+ class TheTest < Test::Unit::TestCase
82
+ def test_1
83
+ assert_nothing_raised { A::B::C }
84
+ remove_module(A::B::C)
85
+ assert_raise(NameError) { A::B::C }
86
+ end
87
+ end
88
+ end
89
+
90
+ module TestRemoveAB
91
+ module A
92
+ module B
93
+ module C
94
+ end
95
+ end
96
+ end
97
+
98
+ class TheTest < Test::Unit::TestCase
99
+ def test_1
100
+ assert_nothing_raised { A::B }
101
+ remove_module(A::B)
102
+ assert_raise(NameError) { A::B }
103
+ end
104
+ end
105
+ end
106
+
107
+ module TestRemoveAB_Symbol
108
+ module A
109
+ module B
110
+ module C
111
+ end
112
+ end
113
+ end
114
+
115
+ class TheTest < Test::Unit::TestCase
116
+ def test_1
117
+ assert_nothing_raised { A::B }
118
+ assert_raise(NameError) { remove_module(:'A::B') } # This is why passing in the module itself is preferred.
119
+ remove_module(:'TestRemoveAB_Symbol::A::B')
120
+ assert_raise(NameError) { A::B }
121
+ end
122
+ end
123
+ end
124
+
125
+ =end
126
+
127
+
@@ -0,0 +1,43 @@
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
+ # * Tests for this method can be found in ../object/ancestry_of_method.rb . It made more sense to test those two methods together;
10
+ # yet it's still to _use_ module/ancestry_of_instance_method.rb without using ../object/ancestry_of_method.rb.
11
+ #++
12
+
13
+ class Module
14
+
15
+ # Returns the module/class which defined the given instance method. If more than one module/class defined the method, returns the _closest_
16
+ # ancestor to have defined it (would be +self+ if it is defined in +self+).
17
+ #
18
+ # This looks at the results of <tt>instance_methods</tt>, which means that if you call this on a module/class, it will _only_ look
19
+ # at _instance_ methods. Thus, (unlike +ancestry_of_method+) it _only_ makes sense to call this method on modules/classes,
20
+ # not _instances_ of those modules/classes.
21
+ #
22
+ # Example:
23
+ # class Base
24
+ # def it; end
25
+ # end
26
+ # class SubWithIt < Base
27
+ # def it; end
28
+ # end
29
+ # class SubWithoutIt < Base
30
+ # end
31
+ # SubWithIt.ancestors # => [SubWithIt, Base, Object, Kernel]
32
+ # SubWithIt.ancestry_of_instance_method(:it) # => SubWithIt # (Stops with self)
33
+ # SubWithoutIt.ancestry_of_instance_method(:it) # => Base # (Goes one step up the ancestry tree)
34
+ #
35
+ # Returns nil if it cannot be found in self or in any ancestor.
36
+ def ancestry_of_instance_method(method_name)
37
+ method_name = method_name.to_s
38
+ self.ancestors.find do |ancestor|
39
+ ancestor.instance_methods(false).include? method_name
40
+ end
41
+ end
42
+
43
+ end
@@ -20,6 +20,7 @@ class Module # :nodoc:
20
20
  EOS
21
21
  end
22
22
  end
23
+ alias_method :cattr_reader, :mattr_reader
23
24
 
24
25
  def mattr_writer(*syms)
25
26
  syms.each do |sym|
@@ -38,9 +39,11 @@ class Module # :nodoc:
38
39
  EOS
39
40
  end
40
41
  end
42
+ alias_method :cattr_writer, :mattr_writer
41
43
 
42
44
  def mattr_accessor(*syms)
43
45
  mattr_reader(*syms)
44
46
  mattr_writer(*syms)
45
47
  end
48
+ alias_method :cattr_accessor, :mattr_accessor
46
49
  end
@@ -0,0 +1,76 @@
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 'facets/core/module/basename'
13
+ require 'facets/core/string/basename'
14
+ require 'qualitysmith_extensions/module/namespace'
15
+
16
+ class Module
17
+ # Gets the basename of a "module path" (the name of the module without any of the namespace modules that it is contained in),
18
+ # in the same sense that <tt>File.basename</tt> returns the basename of a _filesystem_ path.
19
+ #
20
+ # This is identical to Facets' String#basename ('facets/core/string/basename') except that:
21
+ # * it is a class method instead of an instance method of String,
22
+ # * it accepts modules, strings, and symbols.
23
+ #
24
+ # See also <tt>Module.dirname</tt>/<tt>Module.namespace_name_of</tt>.
25
+ #
26
+ # These can be used together, such that the following is always true:
27
+ # OuterModule::MiddleModule::InnerModule == Module.join(Module.dirname(some_module), Module.basename(some_module)).constantize
28
+ #
29
+ def self.basename(module_or_name)
30
+ case module_or_name
31
+ when Module
32
+ module_or_name.basename
33
+ when Symbol
34
+ module_or_name.to_s.basename
35
+ when String
36
+ module_or_name.basename
37
+ else
38
+ raise ArgumentError
39
+ end
40
+ end
41
+ end
42
+
43
+
44
+
45
+
46
+ # _____ _
47
+ # |_ _|__ ___| |_
48
+ # | |/ _ \/ __| __|
49
+ # | | __/\__ \ |_
50
+ # |_|\___||___/\__|
51
+ #
52
+ =begin test
53
+ require 'test/unit'
54
+
55
+ module OuterModule; end
56
+ module OuterModule::MiddleModule; end
57
+ module OuterModule::MiddleModule::InnerModule; end
58
+
59
+ class BasenameTest < Test::Unit::TestCase
60
+ def test_simple
61
+ assert_equal 'OuterModule', Module.basename(OuterModule)
62
+ assert_equal 'OuterModule', Module.basename(:OuterModule)
63
+ assert_equal 'OuterModule', Module.basename('OuterModule')
64
+ end
65
+ def test_nesting
66
+ assert_equal 'InnerModule',
67
+ Module.basename(OuterModule::MiddleModule::InnerModule)
68
+ assert_equal 'InnerModule',
69
+ Module.basename(:'OuterModule::MiddleModule::InnerModule')
70
+ assert_equal 'InnerModule',
71
+ Module.basename('OuterModule::MiddleModule::InnerModule')
72
+ end
73
+ end
74
+ =end
75
+
76
+