ruby_ext 0.4.6
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/Rakefile +64 -0
- data/lib/ruby_ext/array.rb +13 -0
- data/lib/ruby_ext/basic_object.rb +22 -0
- data/lib/ruby_ext/class.rb +11 -0
- data/lib/ruby_ext/declarative_cache.rb +85 -0
- data/lib/ruby_ext/deep_clone.rb +62 -0
- data/lib/ruby_ext/extra_blank_slate.rb +16 -0
- data/lib/ruby_ext/file.rb +20 -0
- data/lib/ruby_ext/hash.rb +15 -0
- data/lib/ruby_ext/kernel.rb +69 -0
- data/lib/ruby_ext/micelaneous.rb +14 -0
- data/lib/ruby_ext/module.rb +119 -0
- data/lib/ruby_ext/multiple_inheritance.rb +76 -0
- data/lib/ruby_ext/must.rb +192 -0
- data/lib/ruby_ext/not_defined.rb +2 -0
- data/lib/ruby_ext/object.rb +8 -0
- data/lib/ruby_ext/observable2.rb +23 -0
- data/lib/ruby_ext/open_constructor.rb +51 -0
- data/lib/ruby_ext/open_object.rb +157 -0
- data/lib/ruby_ext/prepare_arguments.rb +105 -0
- data/lib/ruby_ext/prototype_inheritance.rb +110 -0
- data/lib/ruby_ext/should.rb +166 -0
- data/lib/ruby_ext/string.rb +44 -0
- data/lib/ruby_ext/symbol.rb +21 -0
- data/lib/ruby_ext/synchronize.rb +24 -0
- data/lib/ruby_ext/tuple.rb +7 -0
- data/lib/ruby_ext.rb +50 -0
- data/lib/spec_ext.rb +10 -0
- data/readme.md +66 -0
- data/spec/_prototype_inheritance_spec.rb +190 -0
- data/spec/array_spec.rb +8 -0
- data/spec/declarative_cache_spec.rb +115 -0
- data/spec/deep_clone_spec.rb +37 -0
- data/spec/helper.rb +20 -0
- data/spec/kernel_spec/TheNamespace/ClassA.rb +7 -0
- data/spec/kernel_spec/another_class.rb +5 -0
- data/spec/kernel_spec/the_namespace/class_b.rb +11 -0
- data/spec/kernel_spec.rb +53 -0
- data/spec/module_spec.rb +160 -0
- data/spec/multiple_inheritance_spec.rb +131 -0
- data/spec/must_spec.rb +29 -0
- data/spec/observable2_spec.rb +42 -0
- data/spec/open_constructor_spec.rb +36 -0
- data/spec/open_object_spec.rb +29 -0
- data/spec/prepare_arguments_spec.rb +46 -0
- data/spec/should_spec.rb +24 -0
- data/spec/spec.opts +2 -0
- data/spec/synchronize_spec.rb +80 -0
- metadata +127 -0
data/Rakefile
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'fileutils'
|
3
|
+
current_dir = File.expand_path(File.dirname(__FILE__))
|
4
|
+
Dir.chdir current_dir
|
5
|
+
|
6
|
+
|
7
|
+
#
|
8
|
+
# Specs
|
9
|
+
#
|
10
|
+
require 'spec/rake/spectask'
|
11
|
+
|
12
|
+
task :default => :spec
|
13
|
+
|
14
|
+
Spec::Rake::SpecTask.new('spec') do |t|
|
15
|
+
t.spec_files = FileList["spec/**/*_spec.rb"].select{|f| f !~ /\/_/}
|
16
|
+
t.libs = ["#{current_dir}/lib"]
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
#
|
21
|
+
# Gem
|
22
|
+
#
|
23
|
+
require 'rake/clean'
|
24
|
+
require 'rake/gempackagetask'
|
25
|
+
|
26
|
+
gem_options = {
|
27
|
+
:name => "ruby_ext",
|
28
|
+
:version => "0.4.6",
|
29
|
+
:summary => "Ruby language extensions",
|
30
|
+
:dependencies => %w(facets)
|
31
|
+
}
|
32
|
+
|
33
|
+
spec = Gem::Specification.new do |s|
|
34
|
+
gem_options.delete(:dependencies).each{|d| s.add_dependency d}
|
35
|
+
gem_options.each{|k, v| s.send "#{k}=", v}
|
36
|
+
|
37
|
+
s.author = "Alexey Petrushin"
|
38
|
+
s.homepage = "http://github.com/alexeypetrushin/#{gem_options[:name]}"
|
39
|
+
s.require_path = "lib"
|
40
|
+
s.files = (%w{Rakefile readme.md} + Dir.glob("{lib,spec}/**/*"))
|
41
|
+
|
42
|
+
s.platform = Gem::Platform::RUBY
|
43
|
+
s.has_rdoc = true
|
44
|
+
end
|
45
|
+
|
46
|
+
package_dir = "#{current_dir}/build"
|
47
|
+
Rake::GemPackageTask.new(spec) do |p|
|
48
|
+
p.need_tar = true if RUBY_PLATFORM !~ /mswin/
|
49
|
+
p.need_zip = true
|
50
|
+
p.package_dir = package_dir
|
51
|
+
end
|
52
|
+
|
53
|
+
task :push do
|
54
|
+
# dir = Dir.chdir package_dir do
|
55
|
+
gem_file = Dir.glob("#{package_dir}/#{gem_options[:name]}*.gem").first
|
56
|
+
system "gem push #{gem_file}"
|
57
|
+
# end
|
58
|
+
end
|
59
|
+
|
60
|
+
task :clean do
|
61
|
+
system "rm -r #{package_dir}"
|
62
|
+
end
|
63
|
+
|
64
|
+
task :release => [:gem, :push, :clean]
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class Array
|
2
|
+
def sfilter *filters
|
3
|
+
filters = filters.first if filters.size == 1 and filters.first.is_a?(Array)
|
4
|
+
filters.collect!{|o| o.is_a?(Regexp) ? o : /#{Regexp.escape o}/}
|
5
|
+
self.select do |line|
|
6
|
+
!filters.any?{|re| line =~ re}
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.wrap value
|
11
|
+
Array(value)
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
if defined? ::BasicObject
|
2
|
+
# A class with no predefined methods that behaves similarly to Builder's
|
3
|
+
# BlankSlate. Used for proxy classes.
|
4
|
+
class BasicObject < ::BasicObject
|
5
|
+
begin
|
6
|
+
undef_method :==
|
7
|
+
undef_method :equal?
|
8
|
+
rescue
|
9
|
+
end
|
10
|
+
|
11
|
+
# Let ActiveSupport::BasicObject at least raise exceptions.
|
12
|
+
def raise(*args)
|
13
|
+
::Object.send(:raise, *args)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
else
|
17
|
+
class BasicObject #:nodoc:
|
18
|
+
instance_methods.each do |m|
|
19
|
+
undef_method(m) if m.to_s !~ /(?:^__|^nil\?$|^send$|^object_id$)/
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'monitor'
|
2
|
+
|
3
|
+
class Module
|
4
|
+
def cache_method *methods
|
5
|
+
DeclarativeCache.cache_method self, *methods
|
6
|
+
end
|
7
|
+
|
8
|
+
def cache_method_with_params *methods
|
9
|
+
DeclarativeCache.cache_method_with_params self, *methods
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class Object
|
14
|
+
def clear_cache_method
|
15
|
+
instance_variables.each do |iv|
|
16
|
+
remove_instance_variable iv if iv =~ /^@cached_/
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
module DeclarativeCache
|
22
|
+
DISABLED = false
|
23
|
+
|
24
|
+
warn "CASHE DISABLED" if DISABLED
|
25
|
+
unless DISABLED
|
26
|
+
class << self
|
27
|
+
|
28
|
+
def cache_method klass, *methods
|
29
|
+
methods.each do |method|
|
30
|
+
klass.class_eval do
|
31
|
+
als = "cached_#{escape_method(method)}"
|
32
|
+
iv_check = "@#{als}_check"
|
33
|
+
iv = "@#{als}"
|
34
|
+
|
35
|
+
raise "Can't cache the #{method} twice!" if instance_methods.include?(als)
|
36
|
+
|
37
|
+
alias_method als, method
|
38
|
+
|
39
|
+
define_method method do |*args|
|
40
|
+
raise "You tried to use cache without params for method with params (use 'cache_method_with_params' instead)!" unless args.empty?
|
41
|
+
unless cached = instance_variable_get(iv)
|
42
|
+
unless check = instance_variable_get(iv_check)
|
43
|
+
cached = send als
|
44
|
+
instance_variable_set iv, cached
|
45
|
+
instance_variable_set iv_check, true
|
46
|
+
end
|
47
|
+
end
|
48
|
+
cached
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def cache_method_with_params klass, *methods
|
55
|
+
methods.each do |method|
|
56
|
+
klass.class_eval do
|
57
|
+
als = "cached_#{escape_method(method)}"
|
58
|
+
iv = "@#{als}"
|
59
|
+
|
60
|
+
raise "Can't cache the '#{method}' twice!" if instance_methods.include?(als)
|
61
|
+
|
62
|
+
alias_method als, method
|
63
|
+
|
64
|
+
define_method method do |*args|
|
65
|
+
unless results = instance_variable_get(iv)
|
66
|
+
results = Hash.new(NotDefined)
|
67
|
+
instance_variable_set iv, results
|
68
|
+
end
|
69
|
+
|
70
|
+
result = results[args]
|
71
|
+
|
72
|
+
if result.equal? NotDefined
|
73
|
+
result = send als, *args
|
74
|
+
results[args] = result
|
75
|
+
end
|
76
|
+
|
77
|
+
result
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
class Object
|
2
|
+
def deep_clone
|
3
|
+
clone = self.clone
|
4
|
+
instance_variables.each do |name|
|
5
|
+
value = instance_variable_get name
|
6
|
+
clone.instance_variable_set name, value.deep_clone
|
7
|
+
end
|
8
|
+
clone
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
Hash.class_eval do
|
13
|
+
def deep_clone
|
14
|
+
clone = super
|
15
|
+
clone.clear
|
16
|
+
each{|k, v| clone[k.deep_clone] = v.deep_clone}
|
17
|
+
clone
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
OpenObject.class_eval do
|
22
|
+
def deep_clone
|
23
|
+
clone = super
|
24
|
+
clone.clear
|
25
|
+
each{|k, v| clone[k.deep_clone] = v.deep_clone}
|
26
|
+
clone
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
Struct.class_eval do
|
31
|
+
def deep_clone
|
32
|
+
clone = super
|
33
|
+
clone.clear
|
34
|
+
each_pair{|k, v| clone[k.deep_clone] = v.deep_clone}
|
35
|
+
clone
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
Array.class_eval do
|
40
|
+
def deep_clone
|
41
|
+
clone = super
|
42
|
+
clone.clear
|
43
|
+
each{|v| clone << v.deep_clone}
|
44
|
+
clone
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
[Class, Proc].each do |klass|
|
49
|
+
klass.class_eval do
|
50
|
+
def deep_clone
|
51
|
+
self
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
[Symbol, TrueClass, FalseClass, Numeric, TrueClass, FalseClass, NilClass].each do |klass|
|
57
|
+
klass.send :alias_method, :clone, :self
|
58
|
+
end
|
59
|
+
|
60
|
+
[String, Symbol, Range, Regexp, Time, Date].each do |klass|
|
61
|
+
klass.send :alias_method, :deep_clone, :clone
|
62
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class ExtraBlankSlate
|
2
|
+
instance_methods.each { |m| undef_method m unless m =~ /^__/ }
|
3
|
+
|
4
|
+
CUSTOM_UNDEFINE = [:p, :select, :puts]
|
5
|
+
|
6
|
+
undefine = Kernel.instance_methods + Object.instance_methods + CUSTOM_UNDEFINE
|
7
|
+
ExtraBlankSlate.instance_methods.each{|m| undefine.delete m}
|
8
|
+
|
9
|
+
undefine.each do |m|
|
10
|
+
script = %{\
|
11
|
+
def #{m} *p, &b
|
12
|
+
method_missing :#{m}, *p, &b
|
13
|
+
end}
|
14
|
+
class_eval script, __FILE__, __LINE__
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
File.class_eval do
|
4
|
+
class << self
|
5
|
+
|
6
|
+
def write(path, data)
|
7
|
+
File.open(path, "wb") do |file|
|
8
|
+
return file.write(data)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def create_directory dir
|
13
|
+
FileUtils.mkdir_p dir unless File.exist? dir
|
14
|
+
end
|
15
|
+
|
16
|
+
def delete_directory dir
|
17
|
+
FileUtils.rm_r dir, :force => true if File.exist? dir
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
Kernel.class_eval do
|
2
|
+
def respond_to sym, *args
|
3
|
+
return nil if not respond_to? sym
|
4
|
+
send sym, *args
|
5
|
+
end
|
6
|
+
|
7
|
+
# def _ &b
|
8
|
+
# raise "Block isn't provided!" unless b
|
9
|
+
# return b
|
10
|
+
# end
|
11
|
+
|
12
|
+
def singleton_class(&block)
|
13
|
+
if block_given?
|
14
|
+
(class << self; self; end).class_eval(&block)
|
15
|
+
self
|
16
|
+
else
|
17
|
+
(class << self; self; end)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
alias_method :metaclass, :singleton_class
|
21
|
+
alias_method :metaclass_eval, :singleton_class
|
22
|
+
|
23
|
+
# Removes the namespace (exact match and underscored) of given class (or self) from stacktrace
|
24
|
+
def raise_without_self *args
|
25
|
+
error, message, klasses = nil
|
26
|
+
if args.size == 1
|
27
|
+
error = RuntimeError
|
28
|
+
message = args[0]
|
29
|
+
klasses = [self]
|
30
|
+
elsif args.size == 2
|
31
|
+
message, klasses = args
|
32
|
+
error = RuntimeError
|
33
|
+
|
34
|
+
klasses = Array(klasses)
|
35
|
+
klasses << self
|
36
|
+
elsif args.size == 3
|
37
|
+
error, message, klasses = args
|
38
|
+
|
39
|
+
klasses = Array(klasses)
|
40
|
+
klasses << self
|
41
|
+
else
|
42
|
+
raise RuntimeError, "Invalid arguments!", caller
|
43
|
+
end
|
44
|
+
|
45
|
+
klasses.collect!{|c| (c.class == Class or c.class == Module or c.class == String) ? c : c.class}
|
46
|
+
|
47
|
+
# obtaining the namespace of each class
|
48
|
+
klasses.collect! do |c|
|
49
|
+
if c.respond_to? :namespace
|
50
|
+
c = c.namespace while c.namespace
|
51
|
+
c
|
52
|
+
else
|
53
|
+
c
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# building regexp
|
58
|
+
skip = []
|
59
|
+
klasses.each do |c|
|
60
|
+
skip.push(/\/#{c.to_s}/) # exact match
|
61
|
+
skip.push(/\/#{c.to_s.underscore}/) # underscored
|
62
|
+
end
|
63
|
+
|
64
|
+
# cleaning stacktrace
|
65
|
+
stack = caller.select{|path| !skip.any?{|re| re =~ path}}
|
66
|
+
|
67
|
+
raise error, message, stack
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
3
|
+
Module.class_eval do
|
4
|
+
def is?(base)
|
5
|
+
ancestors.include?(base)
|
6
|
+
end
|
7
|
+
|
8
|
+
def wrap_method( sym, prefix = "old_", &blk )
|
9
|
+
old_method = "#{prefix}_#{sym}".to_sym
|
10
|
+
alias_method old_method, sym
|
11
|
+
define_method(sym) do |*args|
|
12
|
+
instance_exec(old_method, *args, &blk)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def namespace
|
17
|
+
if @module_namespace_defined
|
18
|
+
@module_namespace
|
19
|
+
else
|
20
|
+
@module_namespace_defined = true
|
21
|
+
@module_namespace = Module.namespace_for name
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def each_namespace &block
|
26
|
+
current = namespace
|
27
|
+
while current do
|
28
|
+
block.call current
|
29
|
+
current = current.namespace
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def each_ancestor include_standard = false, &block
|
34
|
+
if include_standard
|
35
|
+
ancestors.each{|a| block.call a unless a == self}
|
36
|
+
else
|
37
|
+
exclude = [self, Object, Kernel]
|
38
|
+
ancestors.each do |a|
|
39
|
+
block.call a unless exclude.include? a
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def self_ancestors_and_namespaces &b
|
45
|
+
b.call self
|
46
|
+
each_ancestor &b
|
47
|
+
each_namespace &b
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.namespace_for class_name
|
51
|
+
list = class_name.split("::")
|
52
|
+
if list.size > 1
|
53
|
+
list.pop
|
54
|
+
return eval(list.join("::"), TOPLEVEL_BINDING, __FILE__, __LINE__)
|
55
|
+
else
|
56
|
+
return nil
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def inheritable_accessor attribute_name, default_value
|
61
|
+
raise "Can be used only for Class and Module" unless self.class.is? Module
|
62
|
+
# raise "Default value can't be nil!" unless default_value
|
63
|
+
|
64
|
+
iv_name = "@#{attribute_name}"
|
65
|
+
iv_defined = "@#{attribute_name}_defined"
|
66
|
+
|
67
|
+
define_method attribute_name do
|
68
|
+
unless instance_variable_get(iv_defined)
|
69
|
+
iv = nil
|
70
|
+
ancestors[1..-1].each do |a|
|
71
|
+
if a.respond_to?(attribute_name) and (value = a.send(attribute_name))
|
72
|
+
iv = value.deep_clone
|
73
|
+
break
|
74
|
+
end
|
75
|
+
end
|
76
|
+
iv ||= default_value.deep_clone
|
77
|
+
instance_variable_set iv_name, iv
|
78
|
+
instance_variable_set iv_defined, true
|
79
|
+
iv
|
80
|
+
else
|
81
|
+
instance_variable_get iv_name
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
define_method "#{attribute_name}=" do |value|
|
86
|
+
# raise "Value can't be nil!" unless value
|
87
|
+
instance_variable_set iv_name, value
|
88
|
+
instance_variable_set iv_defined, true
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
raise "Internal error, it shouldn't be loaded twice!" if defined? ESCAPE_METHOD_SYMBOLS # some tricky error when runing spec with rake
|
93
|
+
ESCAPE_METHOD_SYMBOLS = [
|
94
|
+
['==', 'assign'],
|
95
|
+
['>', 'gt'],
|
96
|
+
['<', 'lt'],
|
97
|
+
['>=', 'gte'],
|
98
|
+
['<=', 'lte'],
|
99
|
+
['?', 'qst'],
|
100
|
+
['!', 'imp'],
|
101
|
+
['<=>', 'lorg'],
|
102
|
+
['*', 'mp'],
|
103
|
+
['+', 'add'],
|
104
|
+
['-', 'sub'],
|
105
|
+
['=', 'assign'],
|
106
|
+
['**', 'pw'],
|
107
|
+
['=~', 'sim'],
|
108
|
+
['[]', 'sb'],
|
109
|
+
]
|
110
|
+
|
111
|
+
def escape_method method
|
112
|
+
m = method.to_s.clone
|
113
|
+
ESCAPE_METHOD_SYMBOLS.each{|from, to| m.gsub! from, to}
|
114
|
+
raise "Invalid method name '#{method}'!" unless m =~ /^[_a-zA-Z0-9]+$/
|
115
|
+
m
|
116
|
+
end
|
117
|
+
|
118
|
+
public :include
|
119
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
#
|
2
|
+
# Fix for ruby's broken include.
|
3
|
+
# Included modules doesn't propagated to it's children.
|
4
|
+
#
|
5
|
+
# Test case:
|
6
|
+
# module A; end
|
7
|
+
# module B
|
8
|
+
# include A
|
9
|
+
# end
|
10
|
+
#
|
11
|
+
# module Plugin; end
|
12
|
+
# A.send(:include, Plugin)
|
13
|
+
#
|
14
|
+
# p "Ancestors of A: " + A.ancestors.join(', ') # => "Ancestors of A: A, Plugin"
|
15
|
+
# p "Ancestors of B: " + B.ancestors.join(', ') # => "Ancestors of B: B, A" << NO PLUGIN!
|
16
|
+
#
|
17
|
+
class Module
|
18
|
+
def directly_included_by
|
19
|
+
@directly_included_by ||= Set.new
|
20
|
+
end
|
21
|
+
|
22
|
+
def fixed_include mod
|
23
|
+
unless mod.directly_included_by.include? self
|
24
|
+
mod.directly_included_by.add self
|
25
|
+
end
|
26
|
+
|
27
|
+
include mod
|
28
|
+
directly_included_by.each do |child|
|
29
|
+
child.fixed_include self
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
#
|
36
|
+
# Inheritance
|
37
|
+
#
|
38
|
+
class Module
|
39
|
+
def class_prototype
|
40
|
+
unless @class_prototype
|
41
|
+
unless const_defined? :ClassMethods
|
42
|
+
class_eval "module ClassMethods; end", __FILE__, __LINE__
|
43
|
+
end
|
44
|
+
@class_prototype = const_get :ClassMethods
|
45
|
+
|
46
|
+
(class << self; self end).fixed_include @class_prototype
|
47
|
+
end
|
48
|
+
@class_prototype
|
49
|
+
end
|
50
|
+
|
51
|
+
def class_methods &block
|
52
|
+
if block
|
53
|
+
class_prototype.class_eval &block
|
54
|
+
extend class_prototype
|
55
|
+
else
|
56
|
+
class_prototype.instance_methods
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def inherit *modules
|
61
|
+
modules.each do |mod|
|
62
|
+
# Instance Methods
|
63
|
+
fixed_include mod
|
64
|
+
|
65
|
+
# Class Methods
|
66
|
+
if self.class == Module
|
67
|
+
class_prototype.fixed_include mod.class_prototype
|
68
|
+
else
|
69
|
+
(class << self; self end).fixed_include mod.class_prototype
|
70
|
+
end
|
71
|
+
|
72
|
+
# callback
|
73
|
+
mod.inherited self if mod.respond_to? :inherited
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|