footing 0.0.1
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/Gemfile +6 -0
- data/Gemfile.lock +18 -0
- data/README.md +54 -0
- data/lib/extensions/kernel.rb +5 -0
- data/lib/extensions/numeric.rb +26 -0
- data/lib/extensions/object.rb +21 -0
- data/lib/extensions/string.rb +15 -0
- data/lib/footing.rb +62 -0
- metadata +57 -0
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
coderay (1.0.7)
|
5
|
+
method_source (0.8)
|
6
|
+
pry (0.9.10)
|
7
|
+
coderay (~> 1.0.5)
|
8
|
+
method_source (~> 0.8)
|
9
|
+
slop (~> 3.3.1)
|
10
|
+
slop (3.3.2)
|
11
|
+
yard (0.8.2.1)
|
12
|
+
|
13
|
+
PLATFORMS
|
14
|
+
ruby
|
15
|
+
|
16
|
+
DEPENDENCIES
|
17
|
+
pry
|
18
|
+
yard
|
data/README.md
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
# Footing
|
2
|
+
|
3
|
+
#### NOTE: this lib is experimental at the moment
|
4
|
+
|
5
|
+
This lib extends native objects with additional functionality.
|
6
|
+
|
7
|
+
## No implicit monkey patching
|
8
|
+
|
9
|
+
**No surprises here.** You must explicitly ask for Footing goodness to be added to your objects.
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
# some examples of explicit patching
|
13
|
+
Footing.patch!(String)
|
14
|
+
String.ancestors
|
15
|
+
[
|
16
|
+
String,
|
17
|
+
Footing::String::InstanceMethods,
|
18
|
+
Comparable,
|
19
|
+
Object,
|
20
|
+
PP::ObjectMixin,
|
21
|
+
Kernel,
|
22
|
+
BasicObject
|
23
|
+
]
|
24
|
+
|
25
|
+
Footing.patch!(Numeric)
|
26
|
+
[
|
27
|
+
Numeric,
|
28
|
+
Footing::Numeric::InstanceMethods,
|
29
|
+
Comparable,
|
30
|
+
Object,
|
31
|
+
PP::ObjectMixin,
|
32
|
+
Kernel,
|
33
|
+
BasicObject
|
34
|
+
]
|
35
|
+
```
|
36
|
+
|
37
|
+
## Instance patching
|
38
|
+
|
39
|
+
If you don't want to corrupt your entire runtime, you can patch an instance.
|
40
|
+
|
41
|
+
```ruby
|
42
|
+
s = "foo"
|
43
|
+
Footing.patch!(s)
|
44
|
+
s.respond_to? :escape # => true
|
45
|
+
"foo".respond_to? :escape # => false
|
46
|
+
```
|
47
|
+
|
48
|
+
## Kick the tires
|
49
|
+
|
50
|
+
* `git clone git://github.com/hopsoft/footing.git`
|
51
|
+
* `cd /path/to/footing`
|
52
|
+
* `bundle`
|
53
|
+
* `./console`
|
54
|
+
* `Footing.patch(String)`
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Footing
|
2
|
+
module Numeric
|
3
|
+
|
4
|
+
module InstanceMethods
|
5
|
+
|
6
|
+
# Returns the percentage that this number is of the passed number.
|
7
|
+
# @example
|
8
|
+
# 8.percent_of(10) # => 80.0
|
9
|
+
# @param [Numeric] number The number to calculate the percentage with
|
10
|
+
def percent_of(number)
|
11
|
+
percent = (self.to_f / number.to_f) * 100 if number > 0
|
12
|
+
percent ||= 0.0
|
13
|
+
end
|
14
|
+
|
15
|
+
# Rounds the number to a certain number of decimal places.
|
16
|
+
# @example
|
17
|
+
# 1.784329.round_to(1) # => 1.8
|
18
|
+
# @param [Numeric] decimal_places The number of decimal places to round to
|
19
|
+
def round_to(decimal_places)
|
20
|
+
(self * 10**decimal_places).round.to_f / 10**decimal_places
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Footing
|
2
|
+
module Object
|
3
|
+
module InstanceMethods
|
4
|
+
|
5
|
+
# Returns the eigen class for the object.
|
6
|
+
def eigen
|
7
|
+
eigen = class << self
|
8
|
+
self
|
9
|
+
end
|
10
|
+
rescue Exception => ex
|
11
|
+
nil
|
12
|
+
end
|
13
|
+
|
14
|
+
# Indicates if the object has an eigen class.
|
15
|
+
def has_eigen?
|
16
|
+
!eigen.nil?
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Footing
|
2
|
+
module String
|
3
|
+
module InstanceMethods
|
4
|
+
|
5
|
+
# Escapes a series of chars in the current string.
|
6
|
+
# NOTE: A new string is returned.
|
7
|
+
def escape(*chars)
|
8
|
+
gsub(/(?<!\\)(#{chars.join("|")})/) do |char|
|
9
|
+
"\\" + char
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/lib/footing.rb
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
module Footing
|
2
|
+
|
3
|
+
# Patches the object with all applicable Hopsoft extensions and monkey patches.
|
4
|
+
# Works for Modules, Classes, and instances of objects.
|
5
|
+
# @param [Object] obj The object to patch.
|
6
|
+
def self.patch!(obj)
|
7
|
+
if obj.class == Module || obj.class == Class
|
8
|
+
# patching a Module or Class
|
9
|
+
violate(obj)
|
10
|
+
else
|
11
|
+
# patching an instance
|
12
|
+
eigen = nil
|
13
|
+
begin
|
14
|
+
eigen = class << obj
|
15
|
+
self
|
16
|
+
end
|
17
|
+
rescue Exception => ex
|
18
|
+
end
|
19
|
+
|
20
|
+
raise "#{obj.class.name} doesn't support instance patching!" unless eigen
|
21
|
+
violate(eigen)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
# Violates the object by applying all applicable Footing extensions and monkey patches.
|
28
|
+
# @param [Object] obj The object to voilate.
|
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
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
Dir[File.expand_path(File.join(File.dirname(__FILE__), "**/*.rb"))].each do |file|
|
56
|
+
next if file =~ /#{__FILE__.gsub(".", "\.")}$/
|
57
|
+
if ENV["FOOTING_DEV"]
|
58
|
+
load file
|
59
|
+
else
|
60
|
+
require file
|
61
|
+
end
|
62
|
+
end
|
metadata
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: footing
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Nathan Hopkins
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-07-23 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: ! " Footing provides some sanity for monkey patching practices.\n
|
15
|
+
\ It also is a utility lib that contains additional functionality for core objects
|
16
|
+
that you might find useful.\n"
|
17
|
+
email:
|
18
|
+
- natehop@gmail.com
|
19
|
+
executables: []
|
20
|
+
extensions: []
|
21
|
+
extra_rdoc_files: []
|
22
|
+
files:
|
23
|
+
- lib/extensions/kernel.rb
|
24
|
+
- lib/extensions/numeric.rb
|
25
|
+
- lib/extensions/object.rb
|
26
|
+
- lib/extensions/string.rb
|
27
|
+
- lib/footing.rb
|
28
|
+
- Gemfile
|
29
|
+
- Gemfile.lock
|
30
|
+
- README.md
|
31
|
+
homepage: https://github.com/hopsoft/footing
|
32
|
+
licenses:
|
33
|
+
- MIT
|
34
|
+
post_install_message:
|
35
|
+
rdoc_options: []
|
36
|
+
require_paths:
|
37
|
+
- lib
|
38
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
45
|
+
none: false
|
46
|
+
requirements:
|
47
|
+
- - ! '>='
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '0'
|
50
|
+
requirements: []
|
51
|
+
rubyforge_project:
|
52
|
+
rubygems_version: 1.8.10
|
53
|
+
signing_key:
|
54
|
+
specification_version: 3
|
55
|
+
summary: Foundational patching lib.
|
56
|
+
test_files: []
|
57
|
+
has_rdoc:
|