Class: Module

Inherits:
Object show all
Defined in:
lib/ruby_ext/multiple_inheritance.rb,
lib/ruby_ext/synchronize.rb,
lib/ruby_ext/declarative_cache.rb,
lib/ruby_ext/multiple_inheritance.rb,
lib/ruby_ext/prototype_inheritance.rb

Overview

Fix for ruby’s broken include. Included modules doesn’t propagated to it’s children.

Test case: module A; end module B

include A

end

module Plugin; end A.send(:include, Plugin)

p “Ancestors of A: ” + A.ancestors.join(‘, ’) # => “Ancestors of A: A, Plugin” p “Ancestors of B: ” + B.ancestors.join(‘, ’) # => “Ancestors of B: B, A” << NO PLUGIN!

Instance Method Summary collapse

Instance Method Details

#cache_method(*methods) ⇒ Object



4
5
6
# File 'lib/ruby_ext/declarative_cache.rb', line 4

def cache_method *methods
  DeclarativeCache.cache_method self, *methods
end

#cache_method_with_params(*methods) ⇒ Object



8
9
10
# File 'lib/ruby_ext/declarative_cache.rb', line 8

def cache_method_with_params *methods
  DeclarativeCache.cache_method_with_params self, *methods
end

#class_methods(&block) ⇒ Object



51
52
53
54
55
56
57
58
# File 'lib/ruby_ext/multiple_inheritance.rb', line 51

def class_methods &block
  if block      
    class_prototype.class_eval &block      
    extend class_prototype
  else
    class_prototype.instance_methods
  end
end

#class_prototypeObject



39
40
41
42
43
44
45
46
47
48
49
# File 'lib/ruby_ext/multiple_inheritance.rb', line 39

def class_prototype
  unless @class_prototype
    unless const_defined? :ClassMethods
      class_eval "module ClassMethods; end", __FILE__, __LINE__        
    end      
    @class_prototype = const_get :ClassMethods
    
    (class << self; self end).fixed_include @class_prototype
  end
  @class_prototype
end

#directly_included_byObject



18
19
20
# File 'lib/ruby_ext/multiple_inheritance.rb', line 18

def directly_included_by
  @directly_included_by ||= Set.new
end

#fixed_include(mod) ⇒ Object



22
23
24
25
26
27
28
29
30
31
# File 'lib/ruby_ext/multiple_inheritance.rb', line 22

def fixed_include mod
  unless mod.directly_included_by.include? self
    mod.directly_included_by.add self
  end

  include mod
  directly_included_by.each do |child|
    child.fixed_include self
  end
end

#inherit(*modules) ⇒ Object



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/ruby_ext/multiple_inheritance.rb', line 60

def inherit *modules
  modules.each do |mod|
    # Instance Methods
    fixed_include mod
    
    # Class Methods
    if self.class == Module        
      class_prototype.fixed_include mod.class_prototype
    else
      (class << self; self end).fixed_include mod.class_prototype
    end          
    
    # callback
    mod.inherited self if mod.respond_to? :inherited
  end
end

#synchronize_all_methods(include_super = false) ⇒ Object



20
21
22
23
# File 'lib/ruby_ext/synchronize.rb', line 20

def synchronize_all_methods include_super = false
  methods = self.instance_methods(include_super).collect{|m| m.to_sym}
  synchronize_method *methods
end

#synchronize_method(*methods) ⇒ Object



4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# File 'lib/ruby_ext/synchronize.rb', line 4

def synchronize_method *methods
  methods.each do |method|              
    als = "sync_#{escape_method(method)}"
    
    raise "Can't synchronize the '#{method}' twice!" if instance_methods.include?(als)
    
    alias_method als, method
    script = "\
def #{method} *p, &b
@monitor ||= Monitor.new
@monitor.synchronize{#{als} *p, &b}
end"
    class_eval script, __FILE__, __LINE__
  end
end