attic 0.4.0 → 0.5.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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