attic 0.4.0 → 0.5.2

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.
@@ -1,5 +1,21 @@
1
1
  ATTIC, CHANGES
2
2
 
3
+ #### 0.5.2 (2010-02-15) ###############################
4
+
5
+ * CHANGE: Remove hanna dependency
6
+
7
+ #### 0.5.0 (2009-11-29) ###############################
8
+
9
+ * FIXED: Classes can now only be extended once
10
+ * FIXED: Don't define the same attic variable more then once
11
+ * FIXED: Don't define instance_variable method for objects which
12
+ don't already have one.
13
+ * CHANGE: attic_vars method is now attic_variables
14
+ * CHANGE: Won't define accessor methods if methods with the same
15
+ name already exist.
16
+ * ADDED: all_instance_variables method (for no metaclasses)
17
+ * ADDED: Explicit attic_variable_set and attic_variable_get methods
18
+
3
19
 
4
20
  #### 0.4.0 (2009-07-17) ###############################
5
21
 
@@ -1,23 +1,27 @@
1
- = Attic - v0.4 ALPHA
1
+ = Attic - v0.5
2
2
 
3
- A place for Ruby objects to hide instance variables.
4
-
5
- == Alpha Notice
6
-
7
- This library is fresh (est 2009-07-06) and barely tested. It's fun to use but not reliable yet.
3
+ A place to hide private instance variables in your Ruby objects.
8
4
 
9
5
  == Example
10
6
 
11
7
  require 'attic'
12
8
 
13
- String.extend Attic
14
- String.attic :timestamp
9
+ class String
10
+ extend Attic
11
+ attic :timestamp
12
+ end
15
13
 
16
14
  a = "anything"
17
15
  a.timestamp = "1980-11-18"
18
- a.instance_variables # => []
19
- a.timestamp # 1980-11-18
20
-
16
+ a.instance_variables # => []
17
+ a.timestamp # 1980-11-18
18
+
19
+ a.attic_variables # => [:timestamp]
20
+
21
+ a.attic_variable_set :tags, [:a, :b, :c]
22
+ a.attic_variable_get :tags # [:a, :b, :c]
23
+
24
+ a.attic_variables # => [:timestamp, :tags]
21
25
 
22
26
  == Some objects have no metaclasses
23
27
 
@@ -29,7 +33,6 @@ Symbol and Fixnum objects do not have metaclasses so instance variables are hidd
29
33
  Via Rubygems, one of:
30
34
 
31
35
  $ gem install attic
32
- $ gem install delano-attic --source http://gems.github.com/
33
36
 
34
37
  or via download:
35
38
  * attic-latest.tar.gz[http://github.com/delano/attic/tarball/latest]
data/Rakefile CHANGED
@@ -1,10 +1,17 @@
1
1
  require 'rubygems'
2
2
  require 'rake/clean'
3
3
  require 'rake/gempackagetask'
4
- require 'hanna/rdoctask'
5
4
  require 'fileutils'
6
5
  include FileUtils
7
6
 
7
+
8
+ begin
9
+ require 'hanna/rdoctask'
10
+ rescue LoadError
11
+ require 'rake/rdoctask'
12
+ end
13
+
14
+
8
15
  task :default => :package
9
16
 
10
17
  # CONFIG =============================================================
@@ -1,8 +1,8 @@
1
1
  @spec = Gem::Specification.new do |s|
2
2
  s.name = "attic"
3
3
  s.rubyforge_project = "attic"
4
- s.version = "0.4.0"
5
- s.summary = "A place for Ruby objects to hide instance variables."
4
+ s.version = "0.5.2"
5
+ s.summary = "A place to hide private instance variables in your Ruby objects."
6
6
  s.description = s.summary
7
7
  s.author = "Delano Mandelbaum"
8
8
  s.email = "delano@solutious.com"
@@ -41,12 +41,14 @@
41
41
  attic.gemspec
42
42
  lib/attic.rb
43
43
  lib/attic/mixins.rb
44
- lib/attic/mixins/object.rb
45
44
  try/01_mixins_tryouts.rb
46
45
  try/10_attic_tryouts.rb
47
46
  try/20_accessing_tryouts.rb
48
47
  try/25_string_tryouts.rb
49
48
  try/30_nometaclass_tryouts.rb
49
+ try/40_explicit_accessor_tryouts.rb
50
+ try/X1_metaclasses.rb
51
+ try/X2_extending.rb
50
52
  )
51
53
 
52
54
  s.has_rdoc = true
@@ -6,67 +6,74 @@ require 'attic/mixins'
6
6
  # A place to store instance variables.
7
7
  #
8
8
  module Attic
9
- VERSION = '0.4.0'
9
+ VERSION = '0.5.2' unless defined?(VERSION)
10
+
11
+ module InstanceMethods
12
+ def attic_variables
13
+ self.class.attic_variables
14
+ end
15
+ alias_method :attic_vars, :attic_variables
16
+ def attic_variable? n
17
+ self.class.attic_variable? n
18
+ end
19
+ def attic_variable_set(n,v)
20
+ attic_variables << n unless attic_variable? n
21
+ if metaclass?
22
+ metaclass.instance_variable_set("@#{n}", v)
23
+ else
24
+ instance_variable_set("@___attic_#{n}", v)
25
+ end
26
+ end
27
+ def attic_variable_get(n)
28
+ if metaclass?
29
+ metaclass.instance_variable_get("@#{n}")
30
+ else
31
+ instance_variable_get("@___attic_#{n}")
32
+ end
33
+ end
34
+ end
10
35
 
11
36
  def self.included(o)
12
37
  raise "You probably meant to 'extend Attic' in #{o}"
13
38
  end
14
39
 
15
40
  def self.extended(o)
41
+ # This class has already been extended.
42
+ return if o.ancestors.member? Attic::InstanceMethods
43
+
44
+
16
45
  ## NOTE: This is just a reminder for a more descerning way to
17
46
  ## include the meta methods, instead of using a global mixin.
18
47
  ##o.class_eval do
19
48
  ## include ObjectHelpers
20
49
  ##end
21
-
22
50
  # Create an instance method that returns the attic variables.
51
+ o.send :include, Attic::InstanceMethods
52
+ #p [:extend, self, o]
53
+
54
+ o.metaclass.instance_variable_set("@attic_variables", [])
23
55
  o.class_eval do
24
- define_method :attic_vars do
25
- self.class.attic_vars
56
+ def self.inherited(o2)
57
+ #p [:inherit, self, o2]
58
+ attic_vars = self.attic_variables.clone
59
+ o2.metaclass.instance_variable_set("@attic_variables", attic_vars)
26
60
  end
27
- end
28
- end
29
-
30
- # Create instance methods that store variables in the metaclass.
31
- @@metaclass_proc = proc { |klass,name|
32
- klass.class_eval do
33
- # Add the attic variables named to the list. Notice that we
34
- # cheakily store this in the metameta class so as to not
35
- # disturb the metaclass instance variables.
36
- vars = attic_vars << name
37
- metametaclass.instance_variable_set("@attic", vars)
38
-
39
- define_method(name) do
40
- metaclass.instance_variable_get("@#{name}")
41
- end
42
- define_method("#{name}=") do |val|
43
- metaclass.instance_variable_set("@#{name}", val)
61
+ if method_defined? :instance_variables
62
+ old_instance_variables = instance_method(:instance_variables)
63
+ define_method :instance_variables do
64
+ ret = old_instance_variables.bind(self).call.clone
65
+ ret.reject! { |v| v.to_s =~ /^@___?attic/ } # match 2 or 3 underscores
66
+ ret
67
+ end
68
+ define_method :all_instance_variables do
69
+ old_instance_variables.bind(self).call
70
+ end
44
71
  end
45
72
  end
46
- }
47
73
 
48
- # Create instance methods that store variables in unlikely instance vars.
49
- @@nometaclass_proc = proc { |klass,name|
50
- klass.class_eval do
51
- # Add the attic variables named to the list. We use a
52
- # variable with 3 underscores to prevent collisions.
53
- vars = attic_vars << name
54
- instance_variable_set("@___attic_vars", vars)
55
-
56
- define_method(name) do
57
- instance_variable_get("@__attic_#{name}")
58
- end
59
- define_method("#{name}=") do |val|
60
- instance_variable_set("@__attic_#{name}", val)
61
- end
62
- define_method :instance_variables do |*args|
63
- ret = super *args
64
- ret.reject! { |v| v.to_s =~ /^@___?attic/ } # match 2 or 3 underscores
65
- ret
66
- end
67
- end
68
- }
69
-
74
+
75
+ end
76
+
70
77
 
71
78
  # A class method for defining variables to store in the attic.
72
79
  # * +junk+ is a list of variables names. Accessor methods are
@@ -85,15 +92,22 @@ module Attic
85
92
  # * <tt>String#timestamp</tt> for setting the value
86
93
  #
87
94
  def attic *junk
88
- #p [:attic, self, metaclass?]
89
95
  return metaclass if junk.empty?
90
-
91
- processor = metaclass? ? @@metaclass_proc : @@nometaclass_proc
92
-
93
- junk.each do |var|
94
- processor.call(self, var)
96
+ junk.each do |name|
97
+ next if attic_variable? name
98
+ self.attic_variables << name
99
+
100
+ unless method_defined? name
101
+ define_method(name) do
102
+ attic_variable_get name
103
+ end
104
+ end
105
+ unless method_defined? "#{name}="
106
+ define_method("#{name}=") do |val|
107
+ attic_variable_set name, val
108
+ end
109
+ end
95
110
  end
96
-
97
111
  attic_vars
98
112
  end
99
113
 
@@ -102,16 +116,18 @@ module Attic
102
116
  #
103
117
  # String.extend Attic
104
118
  # String.attic :timestamp
105
- # String.attic_vars # => [:timestamp]
119
+ # String.attic_variables # => [:timestamp]
106
120
  #
107
- def attic_vars
108
- if metaclass?
109
- metametaclass.instance_variable_get("@attic") || []
110
- else
111
- instance_variable_get("@___attic_vars") || []
112
- end
121
+ def attic_variables
122
+ a = self.metaclass.instance_variable_get("@attic_variables")
123
+ a ||= self.metaclass.instance_variable_set("@attic_variables", [])
124
+ a
125
+ end
126
+ alias_method :attic_vars, :attic_variables
127
+
128
+ def attic_variable?(n)
129
+ attic_variables.member? n
113
130
  end
114
-
115
131
 
116
132
  end
117
133
 
@@ -1,3 +1,68 @@
1
+ class NoMetaClass < RuntimeError
2
+ end
1
3
 
2
- require 'attic/mixins/object'
4
+ # = Object
5
+ #
6
+ # These methods are copied directly from _why's metaid.rb.
7
+ # See: http://whytheluckystiff.net/articles/seeingMetaclassesClearly.html
8
+ class Object
9
+
10
+ # An Array of classes which do not have metaclasses.
11
+ NOMETACLASS = [Symbol, Fixnum].freeze
12
+
13
+ def nometaclass?
14
+ NOMETACLASS.member?(self)
15
+ end
16
+
17
+ def metaclass?
18
+ !NOMETACLASS.member?(self.class)
19
+ end
20
+
21
+ # A convenient method for getting the metaclass of the current object.
22
+ # i.e.
23
+ #
24
+ # class << self; self; end;
25
+ #
26
+ # NOTE: Some Ruby class do not have meta classes (see: NOMETACLASS).
27
+ # For these classes, this method returns the class itself. That means
28
+ # the instance variables will stored in the class itself.
29
+ def metaclass
30
+ if !self.metaclass?
31
+ raise NoMetaClass, self
32
+ else
33
+ class << self; self; end;
34
+ end
35
+ end
36
+
37
+ # Execute a block +&blk+ within the metaclass of the current object.
38
+ def meta_eval &blk; metaclass.instance_eval &blk; end
39
+
40
+ # Add an instance method called +name+ to metaclass for the current object.
41
+ # This is useful because it will be available as a singleton method
42
+ # to all subclasses too.
43
+ def meta_def name, &blk
44
+ meta_eval { define_method name, &blk }
45
+ end
46
+
47
+ # Add a class method called +name+ for the current object's class. This
48
+ # isn't so special but it maintains consistency with meta_def.
49
+ def class_def name, &blk
50
+ class_eval { define_method name, &blk }
51
+ end
52
+
53
+
54
+ # A convenient method for getting the metaclass of the metaclass
55
+ # i.e.
56
+ #
57
+ # self.metaclass.metaclass
58
+ #
59
+ def metametaclass; self.metaclass.metaclass; end
60
+
61
+ def metameta_eval &blk; metametaclass.instance_eval &blk; end
62
+
63
+ def metameta_def name, &blk
64
+ metameta_eval { define_method name, &blk }
65
+ end
66
+
67
+ end
3
68
 
@@ -1,5 +1,5 @@
1
1
  group "Mixins"
2
- library :attic, 'lib'
2
+ library :attic, "lib"
3
3
 
4
4
  tryouts "Object" do
5
5
  if Tryouts.sysinfo.ruby == "1.9.1"
@@ -5,6 +5,7 @@ tryouts "Basics" do
5
5
  drill "can extend Attic", true do
6
6
  class ::Worker
7
7
  extend Attic
8
+ def kind() :true end
8
9
  end
9
10
  # 1.9 # 1.8
10
11
  Worker.methods.member?(:attic) || Worker.methods.member?('attic')
@@ -25,6 +26,18 @@ tryouts "Basics" do
25
26
  w.respond_to? :size
26
27
  end
27
28
 
29
+ drill "can access attic attributes explicitly", 2 do
30
+ w = Worker.new
31
+ w.attic_variable_set :size, 2
32
+ w.attic_variable_get :size
33
+ end
34
+
35
+ drill "won't define a method if on already exists", :true do
36
+ Worker.attic :kind
37
+ a = Worker.new
38
+ a.kind
39
+ end
40
+
28
41
  end
29
42
 
30
43
 
@@ -1,5 +1,5 @@
1
1
  group "No Meta Class"
2
- library :attic, 'lib'
2
+ library :attic, "lib"
3
3
  tryouts "Basics" do
4
4
 
5
5
  dream :class, Array
@@ -13,13 +13,12 @@ tryouts "Basics" do
13
13
  :any.metaclass
14
14
  end
15
15
 
16
- ## NOTE: fails
17
16
  drill "Symbol instances don't cross streams", [:roger, nil] do
18
17
  Symbol.extend Attic
19
18
  Symbol.attic :name
20
- a = :any
19
+ a, b = :symbol1, :symbol2
21
20
  a.name = :roger
22
- [a.name, :another.name]
21
+ [a.name, b.name]
23
22
  end
24
23
 
25
24
  drill "metaclass? method exists", true do
@@ -28,7 +27,30 @@ tryouts "Basics" do
28
27
  end
29
28
 
30
29
  drill "metaclass? method is false for a Symbol", false do
31
- :any.class.metaclass?
30
+ :any.metaclass?
31
+ end
32
+
33
+ dream [:@___attic_name]
34
+ drill "A Symbol's attic vars appear in all_instance_variables" do
35
+ Symbol.extend Attic
36
+ Symbol.attic :name
37
+ a, b = :symbol1, :symbol2
38
+ a.name = :roger
39
+ a.all_instance_variables
40
+ end
41
+
42
+ dream []
43
+ drill "A Symbol's attic vars do not appear in instance_variables" do
44
+ Symbol.extend Attic
45
+ Symbol.attic :name
46
+ a, b = :symbol1, :symbol2
47
+ a.name = :roger
48
+ a.instance_variables
49
+ end
50
+
51
+
52
+ drill "knows attic variables", [:name] do
53
+ Symbol.attic_variables
32
54
  end
33
55
 
34
56
  end
@@ -0,0 +1,23 @@
1
+ group "Attic"
2
+ library :attic, "lib"
3
+ tryouts "Explicit accessors" do
4
+
5
+ setup do
6
+ class ::Worker
7
+ extend Attic
8
+ end
9
+ end
10
+
11
+ drill "can set value", 100 do
12
+ a = Worker.new
13
+ a.attic_variable_set :space, 100
14
+ a.attic_variable_get :space
15
+ end
16
+
17
+ drill "doesn't create accessor methods", false do
18
+ a = Worker.new
19
+ a.attic_variable_set :space, 100
20
+ a.respond_to? :space
21
+ end
22
+
23
+ end
@@ -0,0 +1,112 @@
1
+ # $ ruby tryouts/metaclasses.rb
2
+
3
+ class Object
4
+
5
+ # A convenient method for getting the metaclass of the current object.
6
+ # i.e.
7
+ #
8
+ # class << self; self; end;
9
+ #
10
+ def metaclass; class << self; self; end; end
11
+
12
+ # Execute a block +&blk+ within the metaclass of the current object.
13
+ def meta_eval &blk; metaclass.instance_eval &blk; end
14
+
15
+ # Add an instance method called +name+ to metaclass for the current object.
16
+ # This is useful because it will be available as a singleton method
17
+ # to all subclasses too.
18
+ def meta_def name, &blk
19
+ meta_eval { define_method name, &blk }
20
+ end
21
+
22
+ # Add a class method called +name+ for the current object's class. This
23
+ # isn't so special but it maintains consistency with meta_def.
24
+ def class_def name, &blk
25
+ class_eval { define_method name, &blk }
26
+ end
27
+
28
+
29
+ # A convenient method for getting the metaclass of the metaclass
30
+ # i.e.
31
+ #
32
+ # self.metaclass.metaclass
33
+ #
34
+ def metametaclass; self.metaclass.metaclass; end
35
+
36
+ def metameta_eval &blk; metametaclass.instance_eval &blk; end
37
+
38
+ def metameta_def name, &blk
39
+ metameta_eval { define_method name, &blk }
40
+ end
41
+
42
+ end
43
+
44
+ # Create an instance method
45
+ class NamedArray1
46
+ class_eval do
47
+ define_method(:name) do
48
+ :roger
49
+ end
50
+ end
51
+ end
52
+ p [1, NamedArray1.new.name]
53
+
54
+ # Create getter and setter instance methods
55
+ class NamedArray2
56
+ class_eval do
57
+ define_method(:name) do
58
+ instance_variable_get("@name")
59
+ end
60
+ define_method(:name=) do |val|
61
+ instance_variable_set("@name", val)
62
+ end
63
+ end
64
+ end
65
+ a = NamedArray2.new
66
+ a.name = :roger
67
+ p [2, a.name, a.instance_variables]
68
+
69
+ # Create getter and setter instance methods,
70
+ # store instance variable in metaclass
71
+ class NamedArray3
72
+ class_eval do
73
+ define_method(:name) do
74
+ metaclass.instance_variable_get("@name")
75
+ end
76
+ define_method(:name=) do |val|
77
+ metaclass.instance_variable_set("@name", val)
78
+ end
79
+ end
80
+ end
81
+ a = NamedArray3.new
82
+ a.name = :roger
83
+ p [3, a.name, a.instance_variables, a.metaclass.instance_variables]
84
+
85
+ # Create a module with the which puts the functionality
86
+ # in NamedArray3 into a class method.
87
+ module StorageArea
88
+ def store *junk
89
+ junk.each do |name|
90
+ class_eval do
91
+ define_method(name) do
92
+ metaclass.instance_variable_get("@#{name}")
93
+ end
94
+ define_method("#{name}=") do |val|
95
+ metaclass.instance_variable_set("@#{name}", val)
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
101
+ class NamedArray4
102
+ extend StorageArea
103
+ store :name
104
+ end
105
+ a = NamedArray4.new
106
+ a.name = :roger
107
+ p [4, a.name, a.instance_variables, a.metaclass.instance_variables]
108
+
109
+
110
+
111
+
112
+
@@ -0,0 +1,27 @@
1
+ $:.unshift './lib'
2
+ require 'attic'
3
+
4
+ class A
5
+ extend Attic
6
+ attic :andy
7
+ end
8
+
9
+ class B < A
10
+ attic :size
11
+ end
12
+
13
+ class C
14
+ extend Attic
15
+ attic :third
16
+ end
17
+
18
+ a, b, c = A.new, B.new, C.new
19
+
20
+ a.andy, b.andy = 1, 2
21
+
22
+ p [a.respond_to?(:andy), b.respond_to?(:andy)] # true, true
23
+ p [a.andy, b.andy] # 1, 2
24
+
25
+ p [a.class.attic_vars, b.class.attic_vars, c.class.attic_vars]
26
+
27
+
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: attic
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Delano Mandelbaum
@@ -9,11 +9,11 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-07-17 00:00:00 -04:00
12
+ date: 2010-02-15 00:00:00 -05:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
16
- description: A place for Ruby objects to hide instance variables.
16
+ description: A place to hide private instance variables in your Ruby objects.
17
17
  email: delano@solutious.com
18
18
  executables: []
19
19
 
@@ -31,12 +31,14 @@ files:
31
31
  - attic.gemspec
32
32
  - lib/attic.rb
33
33
  - lib/attic/mixins.rb
34
- - lib/attic/mixins/object.rb
35
34
  - try/01_mixins_tryouts.rb
36
35
  - try/10_attic_tryouts.rb
37
36
  - try/20_accessing_tryouts.rb
38
37
  - try/25_string_tryouts.rb
39
38
  - try/30_nometaclass_tryouts.rb
39
+ - try/40_explicit_accessor_tryouts.rb
40
+ - try/X1_metaclasses.rb
41
+ - try/X2_extending.rb
40
42
  has_rdoc: true
41
43
  homepage: http://github.com/delano/attic
42
44
  licenses: []
@@ -45,7 +47,7 @@ post_install_message:
45
47
  rdoc_options:
46
48
  - --line-numbers
47
49
  - --title
48
- - A place for Ruby objects to hide instance variables.
50
+ - A place to hide private instance variables in your Ruby objects.
49
51
  - --main
50
52
  - README.rdoc
51
53
  require_paths:
@@ -65,9 +67,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
65
67
  requirements: []
66
68
 
67
69
  rubyforge_project: attic
68
- rubygems_version: 1.3.2
70
+ rubygems_version: 1.3.5
69
71
  signing_key:
70
72
  specification_version: 3
71
- summary: A place for Ruby objects to hide instance variables.
73
+ summary: A place to hide private instance variables in your Ruby objects.
72
74
  test_files: []
73
75
 
@@ -1,67 +0,0 @@
1
- class NoMetaClass < RuntimeError
2
- end
3
-
4
- # = Object
5
- #
6
- # These methods are copied directly from _why's metaid.rb.
7
- # See: http://whytheluckystiff.net/articles/seeingMetaclassesClearly.html
8
- class Object
9
-
10
- # An Array of classes which do not have metaclasses.
11
- NOMETACLASS = [Symbol, Fixnum].freeze
12
-
13
- def metaclass?
14
- #p [:metaclass?, self, !NOMETACLASS.member?(self)]
15
- !NOMETACLASS.member?(self)
16
- end
17
-
18
- # FIX: metaclass should check self or self.class? ??? Check previous version
19
-
20
- # A convenient method for getting the metaclass of the current object.
21
- # i.e.
22
- #
23
- # class << self; self; end;
24
- #
25
- # NOTE: Some Ruby class do not have meta classes (see: NOMETACLASS).
26
- # For these classes, this method returns the class itself. That means
27
- # the instance variables will stored in the class itself.
28
- def metaclass
29
- #p [:metaclass, self, self.class, self.class.metaclass?]
30
- if !self.class.metaclass?
31
- raise NoMetaClass, self
32
- else
33
- class << self; self; end;
34
- end
35
- end
36
-
37
- # Execute a block +&blk+ within the metaclass of the current object.
38
- def meta_eval &blk; metaclass.instance_eval &blk; end
39
-
40
- # Add an instance method called +name+ to metaclass for the current object.
41
- # This is useful because it will be available as a singleton method
42
- # to all subclasses too.
43
- def meta_def name, &blk
44
- meta_eval { define_method name, &blk }
45
- end
46
-
47
- # Add a class method called +name+ for the current object's class. This
48
- # isn't so special but it maintains consistency with meta_def.
49
- def class_def name, &blk
50
- class_eval { define_method name, &blk }
51
- end
52
-
53
-
54
- # A convenient method for getting the metaclass of the metaclass
55
- # i.e.
56
- #
57
- # self.metaclass.metaclass
58
- #
59
- def metametaclass; self.metaclass.metaclass; end
60
-
61
- def metameta_eval &blk; metametaclass.instance_eval &blk; end
62
-
63
- def metameta_def name, &blk
64
- metameta_eval { define_method name, &blk }
65
- end
66
-
67
- end