unextendable 0.1.1 → 0.1.3
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/CHANGELOG.rdoc +13 -0
- data/README.textile +7 -1
- data/VERSION +1 -1
- data/lib/unextendable/object.rb +28 -5
- data/lib/unextendable/version.rb +1 -1
- data/test/object_instance_test.rb +27 -2
- metadata +5 -7
data/CHANGELOG.rdoc
CHANGED
@@ -1,5 +1,18 @@
|
|
1
1
|
= Unextendable CHANGELOG
|
2
2
|
|
3
|
+
== Version 0.1.3 (May 2, 2011)
|
4
|
+
|
5
|
+
* Always returning boolean when calling object.meta_class?
|
6
|
+
* Corrected the arguments definition of instance.respond_to? (being able to pass include_private)
|
7
|
+
|
8
|
+
== Version 0.1.2 (May 2, 2011)
|
9
|
+
|
10
|
+
* Improved object_instance.unextend
|
11
|
+
* Created a single point of definition for determination to whether or not unextend a certain module
|
12
|
+
* Added object.meta_class? (aliased with singleton_class?)
|
13
|
+
* Fixed error raised when trying to wrap a non-existing object instance method
|
14
|
+
* Corrected respond_to? and raising NoMethodError when calling an unextended module method which wasn't defined in the object instance itself
|
15
|
+
|
3
16
|
== Version 0.1.1 (May 1, 2011)
|
4
17
|
|
5
18
|
* Being able to pass a block to 'unextend' and only unextending a module when the block passes
|
data/README.textile
CHANGED
@@ -100,19 +100,25 @@ After that, you can do the following:
|
|
100
100
|
c.salutation #=> "Mr. X"
|
101
101
|
c.extend U
|
102
102
|
c.salutation #=> "Mr. U"
|
103
|
+
c.unextend U
|
104
|
+
c.salutation #=> "Mr. X"
|
103
105
|
c.unextend
|
104
106
|
c.salutation #=> "Mr. C"
|
105
107
|
c.extend A
|
106
108
|
c.salutation #=> "Mr. A"
|
107
109
|
c.extend X
|
108
110
|
c.salutation #=> "Mr. X"
|
111
|
+
c.unextend do |mod|
|
112
|
+
mod == U
|
113
|
+
end
|
114
|
+
c.salutation #=> "Mr. X"
|
109
115
|
c.unextend
|
110
116
|
c.salutation #=> "Mr. A" (because module A is NOT unextendable)
|
111
117
|
</pre>
|
112
118
|
|
113
119
|
h2. Last remarks
|
114
120
|
|
115
|
-
Please check out "https://github.com/archan937/unextendable/blob/master/test/object_instance_test.rb":https://github.com/archan937/unextendable/blob/master/test/object_instance_test.rb for most of the tests.
|
121
|
+
Please check out "https://github.com/archan937/unextendable/blob/master/test/object_instance_test.rb":https://github.com/archan937/unextendable/blob/master/test/object_instance_test.rb for most of the tests available. You can run the unit tests with @rake@ within the terminal.
|
116
122
|
|
117
123
|
Also, the Unextendable repo is provided with @script/console@ which you can run for testing purposes. The module and class definitions are already defined when starting up and the object instance <code>@c</code> of the class @C@ is also defined.
|
118
124
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.3
|
data/lib/unextendable/object.rb
CHANGED
@@ -8,6 +8,11 @@ class Object
|
|
8
8
|
end
|
9
9
|
alias :singleton_class :meta_class
|
10
10
|
|
11
|
+
def meta_class?
|
12
|
+
!!(meta_class rescue false)
|
13
|
+
end
|
14
|
+
alias :singleton_class? :meta_class?
|
15
|
+
|
11
16
|
meta_class do
|
12
17
|
def extended_modules
|
13
18
|
@extended_modules ||= []
|
@@ -29,17 +34,29 @@ class Object
|
|
29
34
|
def unextend(*modules, &block)
|
30
35
|
if modules.empty?
|
31
36
|
meta_class.extended_modules.delete_if do |mod|
|
32
|
-
|
37
|
+
unextend? mod, &block
|
33
38
|
end
|
34
39
|
else
|
35
40
|
modules.each do |mod|
|
36
|
-
meta_class.extended_modules.delete mod if
|
41
|
+
meta_class.extended_modules.delete mod if unextend? mod, &block
|
37
42
|
end
|
38
43
|
end
|
39
44
|
end
|
40
45
|
|
46
|
+
def respond_to?(symbol, include_private = false)
|
47
|
+
if meta_class? && meta_class.extended_modules.any?{|mod| mod.unextendable?}
|
48
|
+
meta_class.extended_modules.detect{|x| x.instance_methods.include? symbol.to_s} || meta_class.method_procs[symbol.to_s].class == Proc
|
49
|
+
else
|
50
|
+
!(meta_class? && meta_class.method_procs.key?(symbol.to_s) && meta_class.method_procs[symbol.to_s].nil?) && super
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
41
54
|
private
|
42
55
|
|
56
|
+
def unextend?(mod, &block)
|
57
|
+
mod.unextendable? && (!block_given? || !!block.call(mod))
|
58
|
+
end
|
59
|
+
|
43
60
|
def wrap_unextendable_module(mod)
|
44
61
|
return unless (mod.class == Module) && mod.unextendable?
|
45
62
|
|
@@ -51,7 +68,7 @@ private
|
|
51
68
|
def wrap_unextendable_method(name)
|
52
69
|
return if meta_class.method_procs.key? name
|
53
70
|
|
54
|
-
meta_class.method_procs[name] = method(name).to_proc
|
71
|
+
meta_class.method_procs[name] = respond_to?(name) ? method(name).to_proc : nil
|
55
72
|
|
56
73
|
instance_eval <<-CODE
|
57
74
|
def #{name}(*args, &block)
|
@@ -66,7 +83,11 @@ private
|
|
66
83
|
end
|
67
84
|
|
68
85
|
def call_unextendable_method(method_name, *args, &block)
|
69
|
-
method_for(method_name)
|
86
|
+
if method = method_for(method_name)
|
87
|
+
method.call(*args, &block)
|
88
|
+
else
|
89
|
+
raise NoMethodError, "undefined method `#{method_name}' for #{self.inspect}"
|
90
|
+
end
|
70
91
|
end
|
71
92
|
|
72
93
|
def method_for(method_name)
|
@@ -75,7 +96,9 @@ private
|
|
75
96
|
end
|
76
97
|
|
77
98
|
def proc_for(method_name)
|
78
|
-
meta_class.method_procs
|
99
|
+
meta_class.method_procs.key?(method_name.to_s) ?
|
100
|
+
meta_class.method_procs[method_name.to_s] :
|
101
|
+
method(method_name.to_s)
|
79
102
|
end
|
80
103
|
|
81
104
|
end
|
data/lib/unextendable/version.rb
CHANGED
@@ -77,6 +77,9 @@ class ObjectInstanceTest < Test::Unit::TestCase
|
|
77
77
|
def name
|
78
78
|
"U"
|
79
79
|
end
|
80
|
+
def foo
|
81
|
+
"bar"
|
82
|
+
end
|
80
83
|
end
|
81
84
|
end
|
82
85
|
|
@@ -86,10 +89,16 @@ class ObjectInstanceTest < Test::Unit::TestCase
|
|
86
89
|
end
|
87
90
|
|
88
91
|
should "call wrap_unextendable_method" do
|
89
|
-
@c.expects(:wrap_unextendable_method)
|
92
|
+
@c.expects(:wrap_unextendable_method).twice
|
90
93
|
@c.extend U
|
91
94
|
end
|
92
95
|
|
96
|
+
should "add nil value as method proc when not responding to module method name" do
|
97
|
+
@c.extend U
|
98
|
+
assert_equal 1, @c.meta_class.method_procs.select{|k, v| v.nil?}.size
|
99
|
+
assert_equal 1, @c.meta_class.method_procs.select{|k, v| v.class == Proc}.size
|
100
|
+
end
|
101
|
+
|
93
102
|
should "add the module to extended_modules" do
|
94
103
|
assert @c.meta_class.extended_modules.empty?
|
95
104
|
@c.extend U
|
@@ -99,7 +108,7 @@ class ObjectInstanceTest < Test::Unit::TestCase
|
|
99
108
|
should "add method proc to method_procs" do
|
100
109
|
assert @c.meta_class.send(:method_procs).empty?
|
101
110
|
@c.extend U
|
102
|
-
assert_equal
|
111
|
+
assert_equal 2, @c.meta_class.send(:method_procs).size
|
103
112
|
end
|
104
113
|
|
105
114
|
context "when calling an unextendable method" do
|
@@ -176,16 +185,32 @@ class ObjectInstanceTest < Test::Unit::TestCase
|
|
176
185
|
@c.title = "Dr."
|
177
186
|
assert_equal "Dr. C", @c.salutation
|
178
187
|
|
188
|
+
assert !@c.respond_to?(:foo)
|
189
|
+
assert_raise NoMethodError do
|
190
|
+
@c.foo
|
191
|
+
end
|
192
|
+
|
179
193
|
@c.extend U
|
180
194
|
assert_equal "Dr. U", @c.salutation
|
181
195
|
@c.title = "Sir"
|
182
196
|
assert_equal "Sir U", @c.salutation
|
183
197
|
|
198
|
+
assert @c.respond_to?(:foo)
|
199
|
+
assert_nothing_raised NoMethodError do
|
200
|
+
@c.foo
|
201
|
+
end
|
202
|
+
assert_equal "bar", @c.foo
|
203
|
+
|
184
204
|
@c.unextend U
|
185
205
|
assert_equal "Sir C", @c.salutation
|
186
206
|
@c.title = ""
|
187
207
|
assert_equal "C", @c.salutation
|
188
208
|
|
209
|
+
assert !@c.respond_to?(:foo)
|
210
|
+
assert_raise NoMethodError do
|
211
|
+
@c.foo
|
212
|
+
end
|
213
|
+
|
189
214
|
@c.extend U
|
190
215
|
assert_equal "U", @c.salutation
|
191
216
|
@c.title = "Ms."
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: unextendable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 29
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 0.1.
|
9
|
+
- 3
|
10
|
+
version: 0.1.3
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Paul Engel
|
@@ -15,8 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-05-
|
19
|
-
default_executable:
|
18
|
+
date: 2011-05-02 00:00:00 Z
|
20
19
|
dependencies:
|
21
20
|
- !ruby/object:Gem::Dependency
|
22
21
|
name: shoulda
|
@@ -73,7 +72,6 @@ files:
|
|
73
72
|
- test/object_instance_test.rb
|
74
73
|
- test/test_helper.rb
|
75
74
|
- unextendable.gemspec
|
76
|
-
has_rdoc: true
|
77
75
|
homepage: https://github.com/archan937/unextendable
|
78
76
|
licenses: []
|
79
77
|
|
@@ -103,7 +101,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
103
101
|
requirements: []
|
104
102
|
|
105
103
|
rubyforge_project: unextendable
|
106
|
-
rubygems_version: 1.
|
104
|
+
rubygems_version: 1.7.2
|
107
105
|
signing_key:
|
108
106
|
specification_version: 3
|
109
107
|
summary: A small gem making unextending extended module methods within object instances possible
|