footing 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +23 -9
- data/lib/extensions/numeric.rb +4 -0
- data/lib/extensions/object.rb +5 -0
- data/lib/extensions/string.rb +5 -0
- data/lib/footing.rb +26 -42
- metadata +2 -2
data/README.md
CHANGED
@@ -2,33 +2,39 @@
|
|
2
2
|
|
3
3
|
#### NOTE: this lib is experimental at the moment
|
4
4
|
|
5
|
-
|
5
|
+
Footing provides some sanity for monkey patching practices.
|
6
|
+
It's also a utility lib that contains additional functionality for core objects that you might find useful.
|
6
7
|
|
7
8
|
## No implicit monkey patching
|
8
9
|
|
9
|
-
**No surprises here.** You must explicitly
|
10
|
+
**No surprises here.** You must explicitly patch.
|
10
11
|
|
11
12
|
```ruby
|
12
13
|
# some examples of explicit patching
|
13
|
-
Footing.patch!
|
14
|
+
Footing.patch! String, Footing::String
|
15
|
+
Footing.patch! Numeric, Footing::Numeric
|
16
|
+
```
|
17
|
+
|
18
|
+
```ruby
|
19
|
+
# instrospect the changes
|
14
20
|
String.ancestors
|
15
21
|
[
|
16
22
|
String,
|
17
23
|
Footing::String::InstanceMethods,
|
24
|
+
Footing::String,
|
18
25
|
Comparable,
|
19
26
|
Object,
|
20
|
-
PP::ObjectMixin,
|
21
27
|
Kernel,
|
22
28
|
BasicObject
|
23
29
|
]
|
24
30
|
|
25
|
-
|
31
|
+
Numeric.ancestors
|
26
32
|
[
|
27
33
|
Numeric,
|
28
34
|
Footing::Numeric::InstanceMethods,
|
35
|
+
Footing::Numeric,
|
29
36
|
Comparable,
|
30
37
|
Object,
|
31
|
-
PP::ObjectMixin,
|
32
38
|
Kernel,
|
33
39
|
BasicObject
|
34
40
|
]
|
@@ -36,19 +42,27 @@ Footing.patch!(Numeric)
|
|
36
42
|
|
37
43
|
## Instance patching
|
38
44
|
|
39
|
-
If you don't want to corrupt
|
45
|
+
If you don't want to corrupt the entire runtime, you can patch an instance.
|
40
46
|
|
41
47
|
```ruby
|
42
48
|
s = "foo"
|
43
|
-
Footing.patch!
|
49
|
+
Footing.patch! s, Footing::String
|
44
50
|
s.respond_to? :escape # => true
|
45
51
|
"foo".respond_to? :escape # => false
|
46
52
|
```
|
47
53
|
|
54
|
+
## Shotgun patching
|
55
|
+
|
56
|
+
For the lazy and brave, you can also patch everything at once.
|
57
|
+
|
58
|
+
```ruby
|
59
|
+
Footing.patch_all!
|
60
|
+
```
|
61
|
+
|
48
62
|
## Kick the tires
|
49
63
|
|
50
64
|
* `git clone git://github.com/hopsoft/footing.git`
|
51
65
|
* `cd /path/to/footing`
|
52
66
|
* `bundle`
|
53
67
|
* `./console`
|
54
|
-
* `Footing.patch
|
68
|
+
* `Footing.patch String, Footing::String`
|
data/lib/extensions/numeric.rb
CHANGED
data/lib/extensions/object.rb
CHANGED
data/lib/extensions/string.rb
CHANGED
data/lib/footing.rb
CHANGED
@@ -1,55 +1,39 @@
|
|
1
1
|
module Footing
|
2
2
|
|
3
|
-
#
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
3
|
+
# Applies all Footing patches.
|
4
|
+
def self.patch_all!
|
5
|
+
list = [
|
6
|
+
"Kernel",
|
7
|
+
"Object",
|
8
|
+
"String",
|
9
|
+
"Numeric"
|
10
|
+
]
|
11
|
+
|
12
|
+
list.each do |name|
|
13
|
+
context = Object.const_get(name)
|
14
|
+
footing = Footing.const_get(name)
|
15
|
+
patch! context, footing
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# Patches a Module or instance with the given extension.
|
20
|
+
# @param [Module, Object] obj The Module or instance to patch.
|
21
|
+
# @param [Module] extension The Module that contains the patches.
|
22
|
+
def self.patch!(obj, extension)
|
23
|
+
context = obj if obj.is_a? Module
|
24
|
+
if context.nil?
|
13
25
|
begin
|
14
|
-
|
26
|
+
context = class << obj
|
15
27
|
self
|
16
28
|
end
|
17
29
|
rescue Exception => ex
|
18
30
|
end
|
19
|
-
|
20
|
-
raise "#{obj.class.name} doesn't support instance patching!" unless eigen
|
21
|
-
violate(eigen)
|
22
31
|
end
|
23
|
-
end
|
24
|
-
|
25
|
-
private
|
26
32
|
|
27
|
-
|
28
|
-
|
29
|
-
def self.violate(obj)
|
30
|
-
chain = obj.ancestors.reduce({}) do |memo, ancestor|
|
31
|
-
memo[ancestor] = ancestor.name.split("::")
|
32
|
-
memo
|
33
|
-
end
|
34
|
-
chain[obj] = obj.name.split("::") if obj.name
|
35
|
-
|
36
|
-
chain.each do |ancestor, names|
|
37
|
-
context = obj
|
38
|
-
footing_context = Footing
|
39
|
-
|
40
|
-
names.each do |name|
|
41
|
-
const = context.const_get(name)
|
42
|
-
footing_const = footing_context.const_get(name) if footing_context.const_defined?(name) break unless footing_const.name =~ /^Footing/
|
43
|
-
break if footing_const.name =~ /^(Footing|Footing::Object)$/
|
44
|
-
const.extend footing_const::ClassMethods if defined?(footing_const::ClassMethods)
|
45
|
-
const.send :include, footing_const::InstanceMethods if defined?(footing_const::InstanceMethods)
|
46
|
-
context = const
|
47
|
-
footing_context = footing_const
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
true
|
33
|
+
raise "#{obj.class.name} doesn't support patching!" unless context
|
34
|
+
context.send :include, extension
|
52
35
|
end
|
36
|
+
|
53
37
|
end
|
54
38
|
|
55
39
|
Dir[File.expand_path(File.join(File.dirname(__FILE__), "**/*.rb"))].each do |file|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: footing
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -12,7 +12,7 @@ cert_chain: []
|
|
12
12
|
date: 2012-07-23 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: ! " Footing provides some sanity for monkey patching practices.\n
|
15
|
-
\ It also
|
15
|
+
\ It's also a utility lib that contains additional functionality for core objects
|
16
16
|
that you might find useful.\n"
|
17
17
|
email:
|
18
18
|
- natehop@gmail.com
|