base 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/.gemtest +0 -0
- data/CHANGELOG.md +5 -0
- data/Manifest.txt +6 -0
- data/README.md +39 -0
- data/Rakefile +23 -0
- data/lib/base.rb +95 -0
- data/spec/base_spec.rb +77 -0
- metadata +129 -0
data/.gemtest
ADDED
File without changes
|
data/CHANGELOG.md
ADDED
data/Manifest.txt
ADDED
data/README.md
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
# Base
|
2
|
+
|
3
|
+
* http://github.com/garybernhardt/base
|
4
|
+
|
5
|
+
## DESCRIPTION:
|
6
|
+
|
7
|
+
People love Base classes! They have tons of methods waiting to be used. Just check out ActiveRecord::Base's method list:
|
8
|
+
|
9
|
+
>> ActiveRecord::Base.methods.length
|
10
|
+
=> 530
|
11
|
+
|
12
|
+
But why stop there? Why not have even more methods? In fact, let's put EVERY METHOD on one Base class!
|
13
|
+
|
14
|
+
So I did. It's called Base. Just subclass it and feel free to directly reference any class method, instance method, or constant defined on any module or class in the system. Like this:
|
15
|
+
|
16
|
+
class Cantaloupe < Base
|
17
|
+
def embiggen
|
18
|
+
encode64(deflate(SEPARATOR))
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
>> Cantaloupe.new.embiggen
|
23
|
+
=> "eJzTBwAAMAAw\n"
|
24
|
+
|
25
|
+
See that `embiggen` method calling encode64 and deflate methods? Those come from the `Base64` and `Zlib` modules. And the `SEPARATOR` constant is defined in `File`. Base don't care where it's defined! Base will call it!
|
26
|
+
|
27
|
+
By the way, remember those 530 ActiveRecord methods? That's amateur stuff. Check out Base loaded inside a Rails app:
|
28
|
+
|
29
|
+
>> Base.new.methods.count
|
30
|
+
=> 6947
|
31
|
+
|
32
|
+
It's so badass that it takes FIVE SECONDS just to answer that question!
|
33
|
+
|
34
|
+
## SHOULD I USE THIS IN MY SYSTEM?
|
35
|
+
|
36
|
+
Yes. I am being completely serious. You should.
|
37
|
+
|
38
|
+
Definitely.
|
39
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'hoe'
|
3
|
+
|
4
|
+
Hoe.plugin :git, :doofus, :seattlerb
|
5
|
+
|
6
|
+
Hoe.spec 'base' do
|
7
|
+
developer 'Gary Bernhardt', 'gary.bernhardt@gmail.com'
|
8
|
+
|
9
|
+
### Use markdown for changelog and readme
|
10
|
+
self.history_file = 'CHANGELOG.md'
|
11
|
+
self.readme_file = 'README.md'
|
12
|
+
|
13
|
+
### Test with rspec
|
14
|
+
self.extra_dev_deps << [ 'rspec', '>= 2.1.0' ]
|
15
|
+
self.testlib = :rspec
|
16
|
+
|
17
|
+
### build zip files too
|
18
|
+
self.need_zip = true
|
19
|
+
end
|
20
|
+
|
21
|
+
# add pointer so gem test works. bleh.
|
22
|
+
task :test => [:spec]
|
23
|
+
|
data/lib/base.rb
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
class Base
|
2
|
+
VERSION = "0.0.1"
|
3
|
+
|
4
|
+
def initialize *args, &block
|
5
|
+
super *args, &block
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.const_missing name
|
9
|
+
name = name.to_s
|
10
|
+
all_modules.each do |mod|
|
11
|
+
mod.constants.each do |constant|
|
12
|
+
return mod.const_get(constant) if constant == name
|
13
|
+
end
|
14
|
+
end
|
15
|
+
super
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.all_modules
|
19
|
+
modules = []
|
20
|
+
ObjectSpace.each_object(Module) do |mod|
|
21
|
+
modules << mod if should_extract_from?(mod)
|
22
|
+
end
|
23
|
+
modules << Kernel
|
24
|
+
modules
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.should_extract_from?(mod)
|
28
|
+
return false if (mod < Base || mod == Base || mod.is_a?(Base))
|
29
|
+
return mod.is_a?(Module) && mod != Kernel
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.method_missing name, *args, &block
|
33
|
+
call_method(self, name, args, block)
|
34
|
+
end
|
35
|
+
|
36
|
+
def method_missing name, *args, &block
|
37
|
+
self.class.call_method(self, name, args, block)
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.call_method(object, name, args, block)
|
41
|
+
name_string = name.to_s
|
42
|
+
|
43
|
+
all_modules.each do |mod|
|
44
|
+
if mod.respond_to?(name)
|
45
|
+
return mod.send name, *args, &block
|
46
|
+
elsif mod.instance_methods.include?(name_string)
|
47
|
+
return call_instance_method(mod, name, args, block)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# 1. The world is all that is the case.
|
52
|
+
# 2. We failed to find a method to call.
|
53
|
+
# 2.1. So we need to call method_missing.
|
54
|
+
# 2.1.1. We can't just super it because we're not in method_missing.
|
55
|
+
# 2.1.1.1. We're not in method_missing because there are two of them
|
56
|
+
# (self and instance) that need to share this code.
|
57
|
+
# 2.1.1.2. We need to call the method that would be called if we said
|
58
|
+
# "super" in the object's method_missing.
|
59
|
+
# 2.1.1.2.1. Which is its class's superclass's method_missing method
|
60
|
+
# object.
|
61
|
+
Object.instance_method(:method_missing).bind(object).call(name, *args, &block)
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.call_instance_method(mod, name, args, block)
|
65
|
+
if mod.is_a? Class
|
66
|
+
klass = Class.new(mod)
|
67
|
+
else
|
68
|
+
klass = Class.new { include mod }
|
69
|
+
end
|
70
|
+
return klass.new.send name, *args, &block
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.methods
|
74
|
+
(giant_method_list_including_object(self) + super).uniq
|
75
|
+
end
|
76
|
+
|
77
|
+
def methods
|
78
|
+
(self.class.giant_method_list_including_object(self) + super).uniq
|
79
|
+
end
|
80
|
+
|
81
|
+
# INHERIT ALL THE METHODS!
|
82
|
+
def self.giant_method_list_including_object(object)
|
83
|
+
methods = []
|
84
|
+
all_modules.each_with_index do |m, i|
|
85
|
+
# Don't recurse into other Base objects' "methods" method
|
86
|
+
if m.is_a?(Base) || m < Base || m == Base
|
87
|
+
[]
|
88
|
+
else
|
89
|
+
methods += m.methods + m.instance_methods
|
90
|
+
end
|
91
|
+
end
|
92
|
+
methods
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
data/spec/base_spec.rb
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'lib/base'
|
2
|
+
|
3
|
+
module NormalModule
|
4
|
+
Something = 5
|
5
|
+
|
6
|
+
def self.a_class_method; 6; end
|
7
|
+
def a_module_method; 7; end
|
8
|
+
end
|
9
|
+
|
10
|
+
class NormalClass
|
11
|
+
def an_instance_method; 8; end
|
12
|
+
end
|
13
|
+
|
14
|
+
class InheritsFromBase < Base
|
15
|
+
end
|
16
|
+
|
17
|
+
describe Base do
|
18
|
+
it "should have other modules' constants" do
|
19
|
+
InheritsFromBase::Something.should == NormalModule::Something
|
20
|
+
end
|
21
|
+
|
22
|
+
it "still throws NameError if the constant doesn't exist" do
|
23
|
+
expect do
|
24
|
+
InheritsFromBase::SomethingElse
|
25
|
+
end.to raise_error NameError
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should have other modules' class methods" do
|
29
|
+
InheritsFromBase.a_class_method.should == 6
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should have other modules' instance methods" do
|
33
|
+
InheritsFromBase.a_module_method.should == 7
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should have other classes' instance methods" do
|
37
|
+
InheritsFromBase.an_instance_method.should == 8
|
38
|
+
end
|
39
|
+
|
40
|
+
it "still throws NoMethodError if the method doesn't exist" do
|
41
|
+
expect do
|
42
|
+
InheritsFromBase.not_a_method
|
43
|
+
end.to raise_error NoMethodError
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should have other modules' methods as instance methods" do
|
47
|
+
InheritsFromBase.new.a_class_method.should == 6
|
48
|
+
end
|
49
|
+
|
50
|
+
it "includes methods from the standard library" do
|
51
|
+
InheritsFromBase.inflate(InheritsFromBase.deflate("x")).should == "x"
|
52
|
+
end
|
53
|
+
|
54
|
+
it "checks Kernel last" do
|
55
|
+
InheritsFromBase.all_modules.last.should == Kernel
|
56
|
+
end
|
57
|
+
|
58
|
+
its "instance NoMethodErrors should reference the instance" do
|
59
|
+
expect do
|
60
|
+
InheritsFromBase.new.not_a_method
|
61
|
+
end.to raise_error(NoMethodError, /undefined method `not_a_method' for #<InheritsFromBase/)
|
62
|
+
end
|
63
|
+
|
64
|
+
it "lists a lot of class methods" do
|
65
|
+
InheritsFromBase.methods.count.should > 1500
|
66
|
+
end
|
67
|
+
|
68
|
+
it "lists a lot of instance methods" do
|
69
|
+
InheritsFromBase.new.methods.count.should > 1500
|
70
|
+
end
|
71
|
+
|
72
|
+
it "doesn't list duplicate methods" do
|
73
|
+
methods = InheritsFromBase.methods
|
74
|
+
methods.uniq.should == methods
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
metadata
ADDED
@@ -0,0 +1,129 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: base
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Gary Bernhardt
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-09-02 00:00:00 Z
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: rspec
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
hash: 11
|
29
|
+
segments:
|
30
|
+
- 2
|
31
|
+
- 1
|
32
|
+
- 0
|
33
|
+
version: 2.1.0
|
34
|
+
type: :development
|
35
|
+
version_requirements: *id001
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: hoe
|
38
|
+
prerelease: false
|
39
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ~>
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
hash: 27
|
45
|
+
segments:
|
46
|
+
- 2
|
47
|
+
- 12
|
48
|
+
version: "2.12"
|
49
|
+
type: :development
|
50
|
+
version_requirements: *id002
|
51
|
+
description: |-
|
52
|
+
People love Base classes! They have tons of methods waiting to be used. Just check out ActiveRecord::Base's method list:
|
53
|
+
|
54
|
+
>> ActiveRecord::Base.methods.length
|
55
|
+
=> 530
|
56
|
+
|
57
|
+
But why stop there? Why not have even more methods? In fact, let's put EVERY METHOD on one Base class!
|
58
|
+
|
59
|
+
So I did. It's called Base. Just subclass it and feel free to directly reference any class method, instance method, or constant defined on any module or class in the system. Like this:
|
60
|
+
|
61
|
+
class Cantaloupe < Base
|
62
|
+
def embiggen
|
63
|
+
encode64(deflate(SEPARATOR))
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
>> Cantaloupe.new.embiggen
|
68
|
+
=> "eJzTBwAAMAAw\n"
|
69
|
+
|
70
|
+
See that `embiggen` method calling encode64 and deflate methods? Those come from the `Base64` and `Zlib` modules. And the `SEPARATOR` constant is defined in `File`. Base don't care where it's defined! Base will call it!
|
71
|
+
|
72
|
+
By the way, remember those 530 ActiveRecord methods? That's amateur stuff. Check out Base loaded inside a Rails app:
|
73
|
+
|
74
|
+
>> Base.new.methods.count
|
75
|
+
=> 6947
|
76
|
+
|
77
|
+
It's so badass that it takes FIVE SECONDS just to answer that question!
|
78
|
+
email:
|
79
|
+
- gary.bernhardt@gmail.com
|
80
|
+
executables: []
|
81
|
+
|
82
|
+
extensions: []
|
83
|
+
|
84
|
+
extra_rdoc_files:
|
85
|
+
- Manifest.txt
|
86
|
+
files:
|
87
|
+
- CHANGELOG.md
|
88
|
+
- Manifest.txt
|
89
|
+
- README.md
|
90
|
+
- Rakefile
|
91
|
+
- lib/base.rb
|
92
|
+
- spec/base_spec.rb
|
93
|
+
- .gemtest
|
94
|
+
homepage: http://github.com/garybernhardt/base
|
95
|
+
licenses: []
|
96
|
+
|
97
|
+
post_install_message:
|
98
|
+
rdoc_options:
|
99
|
+
- --main
|
100
|
+
- README.md
|
101
|
+
require_paths:
|
102
|
+
- lib
|
103
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
104
|
+
none: false
|
105
|
+
requirements:
|
106
|
+
- - ">="
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
hash: 3
|
109
|
+
segments:
|
110
|
+
- 0
|
111
|
+
version: "0"
|
112
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
hash: 3
|
118
|
+
segments:
|
119
|
+
- 0
|
120
|
+
version: "0"
|
121
|
+
requirements: []
|
122
|
+
|
123
|
+
rubyforge_project: base
|
124
|
+
rubygems_version: 1.8.8
|
125
|
+
signing_key:
|
126
|
+
specification_version: 3
|
127
|
+
summary: People love Base classes! They have tons of methods waiting to be used
|
128
|
+
test_files: []
|
129
|
+
|