attic 0.3.1 → 0.4.0
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/CHANGES.txt +9 -1
- data/README.rdoc +9 -6
- data/Rakefile +1 -1
- data/attic.gemspec +1 -2
- data/lib/attic.rb +53 -17
- data/lib/attic/mixins/object.rb +13 -3
- data/try/01_mixins_tryouts.rb +7 -6
- data/try/10_attic_tryouts.rb +5 -3
- data/try/30_nometaclass_tryouts.rb +13 -3
- metadata +2 -3
- data/try/metaclasses.rb +0 -112
data/CHANGES.txt
CHANGED
@@ -1,10 +1,17 @@
|
|
1
1
|
ATTIC, CHANGES
|
2
2
|
|
3
|
+
|
4
|
+
#### 0.4.0 (2009-07-17) ###############################
|
5
|
+
|
6
|
+
* ADDED: Support for objects that don't have metaclasses:
|
7
|
+
Currently: Symbols, Fixnum
|
8
|
+
* CHANGE: Objects with no metaclass raise NoMetaClass exception.
|
9
|
+
|
10
|
+
|
3
11
|
#### 0.3.1 (2009-07-13) ###############################
|
4
12
|
|
5
13
|
CRIPES! I'd forgotten to update the gemspec.
|
6
14
|
|
7
|
-
|
8
15
|
#### 0.3 (2009-07-11) ###############################
|
9
16
|
|
10
17
|
NOTE: A complete re-write from 0.2
|
@@ -12,6 +19,7 @@ NOTE: A complete re-write from 0.2
|
|
12
19
|
* FIXED: Now works on any Object except Symbol and Fixnum
|
13
20
|
* ADDED: attic_vars method
|
14
21
|
|
22
|
+
|
15
23
|
#### 0.2 (2009-07-08) ###############################
|
16
24
|
|
17
25
|
NOTE: Initial public release
|
data/README.rdoc
CHANGED
@@ -1,12 +1,10 @@
|
|
1
|
-
= Attic - v0.
|
1
|
+
= Attic - v0.4 ALPHA
|
2
2
|
|
3
3
|
A place for Ruby objects to hide instance variables.
|
4
4
|
|
5
5
|
== Alpha Notice
|
6
6
|
|
7
|
-
This library is fresh (est 2009-07-06) and barely tested. It's fun to use but not reliable yet.
|
8
|
-
|
9
|
-
* Does not work with Symbols or Fixnum object
|
7
|
+
This library is fresh (est 2009-07-06) and barely tested. It's fun to use but not reliable yet.
|
10
8
|
|
11
9
|
== Example
|
12
10
|
|
@@ -19,8 +17,13 @@ This library is fresh (est 2009-07-06) and barely tested. It's fun to use but no
|
|
19
17
|
a.timestamp = "1980-11-18"
|
20
18
|
a.instance_variables # => []
|
21
19
|
a.timestamp # 1980-11-18
|
22
|
-
|
23
|
-
|
20
|
+
|
21
|
+
|
22
|
+
== Some objects have no metaclasses
|
23
|
+
|
24
|
+
Symbol and Fixnum objects do not have metaclasses so instance variables are hidden in the object itself.
|
25
|
+
|
26
|
+
|
24
27
|
== Installation
|
25
28
|
|
26
29
|
Via Rubygems, one of:
|
data/Rakefile
CHANGED
data/attic.gemspec
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
@spec = Gem::Specification.new do |s|
|
2
2
|
s.name = "attic"
|
3
3
|
s.rubyforge_project = "attic"
|
4
|
-
s.version = "0.
|
4
|
+
s.version = "0.4.0"
|
5
5
|
s.summary = "A place for Ruby objects to hide instance variables."
|
6
6
|
s.description = s.summary
|
7
7
|
s.author = "Delano Mandelbaum"
|
@@ -47,7 +47,6 @@
|
|
47
47
|
try/20_accessing_tryouts.rb
|
48
48
|
try/25_string_tryouts.rb
|
49
49
|
try/30_nometaclass_tryouts.rb
|
50
|
-
try/metaclasses.rb
|
51
50
|
)
|
52
51
|
|
53
52
|
s.has_rdoc = true
|
data/lib/attic.rb
CHANGED
@@ -6,7 +6,7 @@ require 'attic/mixins'
|
|
6
6
|
# A place to store instance variables.
|
7
7
|
#
|
8
8
|
module Attic
|
9
|
-
VERSION = '0.
|
9
|
+
VERSION = '0.4.0'
|
10
10
|
|
11
11
|
def self.included(o)
|
12
12
|
raise "You probably meant to 'extend Attic' in #{o}"
|
@@ -27,6 +27,47 @@ module Attic
|
|
27
27
|
end
|
28
28
|
end
|
29
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)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
}
|
47
|
+
|
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
|
+
|
70
|
+
|
30
71
|
# A class method for defining variables to store in the attic.
|
31
72
|
# * +junk+ is a list of variables names. Accessor methods are
|
32
73
|
# created for each variable name in the list.
|
@@ -40,26 +81,17 @@ module Attic
|
|
40
81
|
# String.attic :timestamp
|
41
82
|
#
|
42
83
|
# In this example, attic created two instance methods:
|
43
|
-
# *
|
44
|
-
# *
|
84
|
+
# * <tt>String#timestamp</tt> for getting the value
|
85
|
+
# * <tt>String#timestamp</tt> for setting the value
|
45
86
|
#
|
46
87
|
def attic *junk
|
88
|
+
#p [:attic, self, metaclass?]
|
47
89
|
return metaclass if junk.empty?
|
48
90
|
|
49
|
-
|
50
|
-
# cheakily store this in the metameta class so as to not
|
51
|
-
# disturb the metaclass instance variables.
|
52
|
-
metametaclass.instance_variable_set("@attic", [attic_vars, *junk].flatten)
|
91
|
+
processor = metaclass? ? @@metaclass_proc : @@nometaclass_proc
|
53
92
|
|
54
|
-
junk.each do |
|
55
|
-
|
56
|
-
define_method(name) do
|
57
|
-
metaclass.instance_variable_get("@#{name}")
|
58
|
-
end
|
59
|
-
define_method("#{name}=") do |val|
|
60
|
-
metaclass.instance_variable_set("@#{name}", val)
|
61
|
-
end
|
62
|
-
end
|
93
|
+
junk.each do |var|
|
94
|
+
processor.call(self, var)
|
63
95
|
end
|
64
96
|
|
65
97
|
attic_vars
|
@@ -73,7 +105,11 @@ module Attic
|
|
73
105
|
# String.attic_vars # => [:timestamp]
|
74
106
|
#
|
75
107
|
def attic_vars
|
76
|
-
|
108
|
+
if metaclass?
|
109
|
+
metametaclass.instance_variable_get("@attic") || []
|
110
|
+
else
|
111
|
+
instance_variable_get("@___attic_vars") || []
|
112
|
+
end
|
77
113
|
end
|
78
114
|
|
79
115
|
|
data/lib/attic/mixins/object.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
class NoMetaClass < RuntimeError
|
2
|
+
end
|
1
3
|
|
2
4
|
# = Object
|
3
5
|
#
|
@@ -8,6 +10,13 @@ class Object
|
|
8
10
|
# An Array of classes which do not have metaclasses.
|
9
11
|
NOMETACLASS = [Symbol, Fixnum].freeze
|
10
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
|
+
|
11
20
|
# A convenient method for getting the metaclass of the current object.
|
12
21
|
# i.e.
|
13
22
|
#
|
@@ -16,9 +25,10 @@ class Object
|
|
16
25
|
# NOTE: Some Ruby class do not have meta classes (see: NOMETACLASS).
|
17
26
|
# For these classes, this method returns the class itself. That means
|
18
27
|
# the instance variables will stored in the class itself.
|
19
|
-
def metaclass
|
20
|
-
|
21
|
-
|
28
|
+
def metaclass
|
29
|
+
#p [:metaclass, self, self.class, self.class.metaclass?]
|
30
|
+
if !self.class.metaclass?
|
31
|
+
raise NoMetaClass, self
|
22
32
|
else
|
23
33
|
class << self; self; end;
|
24
34
|
end
|
data/try/01_mixins_tryouts.rb
CHANGED
@@ -2,11 +2,12 @@ group "Mixins"
|
|
2
2
|
library :attic, 'lib'
|
3
3
|
|
4
4
|
tryouts "Object" do
|
5
|
-
|
6
|
-
Object
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
5
|
+
if Tryouts.sysinfo.ruby == "1.9.1"
|
6
|
+
drill "has metaclass", 'Object' do
|
7
|
+
Object.new.metaclass.superclass.to_s
|
8
|
+
end
|
9
|
+
drill "has metametaclass", '#<Class:Object>' do
|
10
|
+
Object.new.metametaclass.superclass.to_s
|
11
|
+
end
|
11
12
|
end
|
12
13
|
end
|
data/try/10_attic_tryouts.rb
CHANGED
@@ -6,7 +6,8 @@ tryouts "Basics" do
|
|
6
6
|
class ::Worker
|
7
7
|
extend Attic
|
8
8
|
end
|
9
|
-
|
9
|
+
# 1.9 # 1.8
|
10
|
+
Worker.methods.member?(:attic) || Worker.methods.member?('attic')
|
10
11
|
end
|
11
12
|
|
12
13
|
drill "can't include Attic raises exception", :exception, RuntimeError do
|
@@ -14,15 +15,16 @@ tryouts "Basics" do
|
|
14
15
|
include Attic
|
15
16
|
end
|
16
17
|
end
|
17
|
-
|
18
|
+
|
18
19
|
drill "can define attic attribute", true do
|
19
20
|
Worker.attic :size
|
20
21
|
w = Worker.new
|
21
22
|
#w.attic :size
|
22
|
-
stash :
|
23
|
+
stash :instance_methods, Worker.instance_methods(false)
|
23
24
|
stash :metamethods, Worker.methods.sort
|
24
25
|
w.respond_to? :size
|
25
26
|
end
|
26
27
|
|
27
28
|
end
|
28
29
|
|
30
|
+
|
@@ -8,12 +8,13 @@ tryouts "Basics" do
|
|
8
8
|
Object::NOMETACLASS
|
9
9
|
end
|
10
10
|
|
11
|
-
|
12
|
-
|
11
|
+
dream :exception, NoMetaClass
|
12
|
+
drill "Symbol metaclass raises exception" do
|
13
|
+
:any.metaclass
|
13
14
|
end
|
14
15
|
|
15
16
|
## NOTE: fails
|
16
|
-
drill "Symbol instances don't cross streams",
|
17
|
+
drill "Symbol instances don't cross streams", [:roger, nil] do
|
17
18
|
Symbol.extend Attic
|
18
19
|
Symbol.attic :name
|
19
20
|
a = :any
|
@@ -21,4 +22,13 @@ tryouts "Basics" do
|
|
21
22
|
[a.name, :another.name]
|
22
23
|
end
|
23
24
|
|
25
|
+
drill "metaclass? method exists", true do
|
26
|
+
Symbol.extend Attic
|
27
|
+
:any.respond_to? :metaclass?
|
28
|
+
end
|
29
|
+
|
30
|
+
drill "metaclass? method is false for a Symbol", false do
|
31
|
+
:any.class.metaclass?
|
32
|
+
end
|
33
|
+
|
24
34
|
end
|
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
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Delano Mandelbaum
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-07-
|
12
|
+
date: 2009-07-17 00:00:00 -04:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -37,7 +37,6 @@ files:
|
|
37
37
|
- try/20_accessing_tryouts.rb
|
38
38
|
- try/25_string_tryouts.rb
|
39
39
|
- try/30_nometaclass_tryouts.rb
|
40
|
-
- try/metaclasses.rb
|
41
40
|
has_rdoc: true
|
42
41
|
homepage: http://github.com/delano/attic
|
43
42
|
licenses: []
|
data/try/metaclasses.rb
DELETED
@@ -1,112 +0,0 @@
|
|
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
|
-
|