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 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
-