attic 0.3.1 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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.3 ALPHA
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. In particular:
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
@@ -1,7 +1,7 @@
1
1
  require 'rubygems'
2
2
  require 'rake/clean'
3
3
  require 'rake/gempackagetask'
4
- require 'rake/rdoctask'
4
+ require 'hanna/rdoctask'
5
5
  require 'fileutils'
6
6
  include FileUtils
7
7
 
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.3.1"
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.3.1'
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
- # * +String#timestamp+ for getting the value
44
- # * +String#timestamp+ for setting the value
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
- # Add the attic variables named to the list. Notice that we
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 |name|
55
- class_eval do
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
- metametaclass.instance_variable_get("@attic") || []
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
 
@@ -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
- if NOMETACLASS.member? self.class
21
- self.class
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
@@ -2,11 +2,12 @@ group "Mixins"
2
2
  library :attic, 'lib'
3
3
 
4
4
  tryouts "Object" do
5
- drill "has metaclass", 'Object' do
6
- Object.new.metaclass.superclass.to_s
7
- end
8
-
9
- drill "has metametaclass", '#<Class:Object>' do
10
- Object.new.metametaclass.superclass.to_s
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
@@ -6,7 +6,8 @@ tryouts "Basics" do
6
6
  class ::Worker
7
7
  extend Attic
8
8
  end
9
- Worker.methods.member? :attic
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 :methods, w.methods.sort
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
- drill "Symbol metaclass returns Symbol", Symbol do
12
- :any.metaclass
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", true do
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.3.1
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-13 00:00:00 -04:00
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
-