include_complete 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,21 +1,20 @@
1
1
  Include Complete
2
2
  ----------------
3
3
 
4
- (c) John Mair (banisterfiend)
4
+ (c) John Mair (banisterfiend) 2010
5
5
  MIT license
6
6
 
7
- Removes the shackles from Module#include - use Module#real_include to
8
- bring in singleton classes from modules. No more ugly ClassMethods and
9
- included() hook hacks.
7
+ _Removes the shackles from Module#include_
10
8
 
11
- ** This is BETA software and has not yet been thoroughly tested, use
12
- at own risk **
9
+ Use `Module#include_complete` to bring in singleton classes from
10
+ modules. No more ugly ClassMethods and included() hook hacks.
13
11
 
14
- install the gem: **for testing purposes only**
15
- `gem install include_complete`
16
-
17
- example:
12
+ * Install the [gem](https://rubygems.org/gems/include_complete): `gem install include_complete`
13
+ * Read the [documentation](http://rdoc.info/github/banister/include_complete/master/file/README.markdown)
14
+ * See the [source code](http://github.com/banister/include_complete)
18
15
 
16
+ example: include_complete():
17
+ ----------------------------
19
18
  module M
20
19
  # class method
21
20
  def self.hello
@@ -38,3 +37,76 @@ example:
38
37
  # invoke instance method
39
38
  A.new.bye #=> bye!
40
39
 
40
+ Motivation
41
+ -----------
42
+
43
+ When a class inherits from another class it inherits both the
44
+ instance methods and class methods from its superclass.
45
+
46
+ Module inclusion does not work this way, only the module's instance methods
47
+ are mixed into the receiver's ancestor chain. This shortcoming
48
+ necessitates the `ClassMethods` included-hook-hack.
49
+
50
+ In my opinion this behaviour of modules violates the principle of
51
+ least surprise, though I'm aware not everyone agrees with this.
52
+
53
+ `include_complete` was written to make module inclusion work more like
54
+ class inheritance.
55
+
56
+ The extend_complete method
57
+ --------------------------
58
+
59
+ For completeness the `extend_complete` method has also been
60
+ implemented. Like traditional `extend` it mixes the module's instance
61
+ methods into the singleton class of the receiver. But where do the
62
+ singleton methods on the module end up? On the singleton class of the
63
+ singleton class of the receiver ;)
64
+
65
+ module M
66
+ def self.hello
67
+ :hello
68
+ end
69
+ end
70
+
71
+ class C
72
+ extend_complete M
73
+
74
+ class << self
75
+ hello #=> :hello
76
+ end
77
+ end
78
+
79
+ As a result of this, it is unlikely `extend_complete` will be of much
80
+ use to anyone :)
81
+
82
+ How does it work?
83
+ -----------------
84
+
85
+ `include_complete` is a C extension that implements a highly modified
86
+ `rb_include_module()` function. Traditional module inclusion uses the
87
+ class pointer of the Included Module to point to the original module;
88
+ `include_complete` instead uses the class pointer to point to a
89
+ wrapped version of the singleton class of the module and stores the original module in a
90
+ hidden `__module__` instance variable. This wrapped singleton class is
91
+ then injected into the ancestor chain of the receiver's singleton
92
+ class.
93
+
94
+ Limitations
95
+ ------------
96
+
97
+ `include_complete` uses a recursive function to generate the
98
+ Included Modules, and the base case of this recursion is reached when the singleton class of Module is
99
+ encountered. In the case where the module has a meta-meta class the recursive
100
+ function will not terminate and the program will hang.
101
+
102
+ It is highly unlikely and, as far as I know, next to useless for
103
+ a module to possess any higher order metaclasses so this limitation is
104
+ unlikely to be a problem in practice.
105
+
106
+ Contact
107
+ -------
108
+
109
+ Problems or questions contact me at [github](http://github.com/banister)
110
+
111
+
112
+
@@ -58,5 +58,6 @@ class Object
58
58
  # o.singleton_class.hello #=> "hello"
59
59
  def extend_complete(*mods)
60
60
  class << self; self; end.send(:include_complete, *mods)
61
+ self
61
62
  end
62
63
  end
@@ -1,3 +1,3 @@
1
1
  module IncludeComplete
2
- VERSION = "0.1.2"
2
+ VERSION = "0.1.3"
3
3
  end
@@ -1,14 +1,15 @@
1
- require '../lib/real_include'
1
+ direc = File.dirname(__FILE__)
2
+ require "#{direc}/../lib/include_complete"
2
3
 
3
4
  5000.times {
4
5
  m = Module.new
5
6
  n = Module.new
6
7
  k = Module.new
7
- n.real_include m
8
- k.real_include n
8
+ n.include_complete m
9
+ k.include_complete n
9
10
 
10
11
  c = Class.new
11
- c.real_include k
12
+ c.include_complete k
12
13
  }
13
14
 
14
15
  "stress test passed!".display
metadata CHANGED
@@ -1,12 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: include_complete
3
3
  version: !ruby/object:Gem::Version
4
+ hash: 29
4
5
  prerelease: false
5
6
  segments:
6
7
  - 0
7
8
  - 1
8
- - 2
9
- version: 0.1.2
9
+ - 3
10
+ version: 0.1.3
10
11
  platform: ruby
11
12
  authors:
12
13
  - John Mair (banisterfiend)
@@ -53,6 +54,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
53
54
  requirements:
54
55
  - - ">="
55
56
  - !ruby/object:Gem::Version
57
+ hash: 3
56
58
  segments:
57
59
  - 0
58
60
  version: "0"
@@ -61,6 +63,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
61
63
  requirements:
62
64
  - - ">="
63
65
  - !ruby/object:Gem::Version
66
+ hash: 3
64
67
  segments:
65
68
  - 0
66
69
  version: "0"