attic 0.3 → 0.3.1

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,9 @@
1
1
  ATTIC, CHANGES
2
2
 
3
+ #### 0.3.1 (2009-07-13) ###############################
4
+
5
+ CRIPES! I'd forgotten to update the gemspec.
6
+
3
7
 
4
8
  #### 0.3 (2009-07-11) ###############################
5
9
 
@@ -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"
4
+ s.version = "0.3.1"
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"
@@ -39,6 +39,15 @@
39
39
  README.rdoc
40
40
  Rakefile
41
41
  attic.gemspec
42
+ lib/attic.rb
43
+ lib/attic/mixins.rb
44
+ lib/attic/mixins/object.rb
45
+ try/01_mixins_tryouts.rb
46
+ try/10_attic_tryouts.rb
47
+ try/20_accessing_tryouts.rb
48
+ try/25_string_tryouts.rb
49
+ try/30_nometaclass_tryouts.rb
50
+ try/metaclasses.rb
42
51
  )
43
52
 
44
53
  s.has_rdoc = true
@@ -0,0 +1,83 @@
1
+
2
+ require 'attic/mixins'
3
+
4
+ # = Attic
5
+ #
6
+ # A place to store instance variables.
7
+ #
8
+ module Attic
9
+ VERSION = '0.3.1'
10
+
11
+ def self.included(o)
12
+ raise "You probably meant to 'extend Attic' in #{o}"
13
+ end
14
+
15
+ def self.extended(o)
16
+ ## NOTE: This is just a reminder for a more descerning way to
17
+ ## include the meta methods, instead of using a global mixin.
18
+ ##o.class_eval do
19
+ ## include ObjectHelpers
20
+ ##end
21
+
22
+ # Create an instance method that returns the attic variables.
23
+ o.class_eval do
24
+ define_method :attic_vars do
25
+ self.class.attic_vars
26
+ end
27
+ end
28
+ end
29
+
30
+ # A class method for defining variables to store in the attic.
31
+ # * +junk+ is a list of variables names. Accessor methods are
32
+ # created for each variable name in the list.
33
+ #
34
+ # Returns the list of attic variable names or if not junk was
35
+ # given, returns the metaclass.
36
+ #
37
+ # e.g.
38
+ #
39
+ # String.extend Attic
40
+ # String.attic :timestamp
41
+ #
42
+ # In this example, attic created two instance methods:
43
+ # * +String#timestamp+ for getting the value
44
+ # * +String#timestamp+ for setting the value
45
+ #
46
+ def attic *junk
47
+ return metaclass if junk.empty?
48
+
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)
53
+
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
63
+ end
64
+
65
+ attic_vars
66
+ end
67
+
68
+ # Returns an Array of attic variables for the current class.
69
+ # e.g.
70
+ #
71
+ # String.extend Attic
72
+ # String.attic :timestamp
73
+ # String.attic_vars # => [:timestamp]
74
+ #
75
+ def attic_vars
76
+ metametaclass.instance_variable_get("@attic") || []
77
+ end
78
+
79
+
80
+ end
81
+
82
+ # - Module#instance_method returns an UnboundMethod
83
+ # - http://ruby-doc.org/core/classes/Module.html#M001659
@@ -0,0 +1,3 @@
1
+
2
+ require 'attic/mixins/object'
3
+
@@ -0,0 +1,57 @@
1
+
2
+ # = Object
3
+ #
4
+ # These methods are copied directly from _why's metaid.rb.
5
+ # See: http://whytheluckystiff.net/articles/seeingMetaclassesClearly.html
6
+ class Object
7
+
8
+ # An Array of classes which do not have metaclasses.
9
+ NOMETACLASS = [Symbol, Fixnum].freeze
10
+
11
+ # A convenient method for getting the metaclass of the current object.
12
+ # i.e.
13
+ #
14
+ # class << self; self; end;
15
+ #
16
+ # NOTE: Some Ruby class do not have meta classes (see: NOMETACLASS).
17
+ # For these classes, this method returns the class itself. That means
18
+ # the instance variables will stored in the class itself.
19
+ def metaclass;
20
+ if NOMETACLASS.member? self.class
21
+ self.class
22
+ else
23
+ class << self; self; end;
24
+ end
25
+ end
26
+
27
+ # Execute a block +&blk+ within the metaclass of the current object.
28
+ def meta_eval &blk; metaclass.instance_eval &blk; end
29
+
30
+ # Add an instance method called +name+ to metaclass for the current object.
31
+ # This is useful because it will be available as a singleton method
32
+ # to all subclasses too.
33
+ def meta_def name, &blk
34
+ meta_eval { define_method name, &blk }
35
+ end
36
+
37
+ # Add a class method called +name+ for the current object's class. This
38
+ # isn't so special but it maintains consistency with meta_def.
39
+ def class_def name, &blk
40
+ class_eval { define_method name, &blk }
41
+ end
42
+
43
+
44
+ # A convenient method for getting the metaclass of the metaclass
45
+ # i.e.
46
+ #
47
+ # self.metaclass.metaclass
48
+ #
49
+ def metametaclass; self.metaclass.metaclass; end
50
+
51
+ def metameta_eval &blk; metametaclass.instance_eval &blk; end
52
+
53
+ def metameta_def name, &blk
54
+ metameta_eval { define_method name, &blk }
55
+ end
56
+
57
+ end
@@ -0,0 +1,12 @@
1
+ group "Mixins"
2
+ library :attic, 'lib'
3
+
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
11
+ end
12
+ end
@@ -0,0 +1,28 @@
1
+ group "Attic"
2
+ library :attic, "lib"
3
+ tryouts "Basics" do
4
+
5
+ drill "can extend Attic", true do
6
+ class ::Worker
7
+ extend Attic
8
+ end
9
+ Worker.methods.member? :attic
10
+ end
11
+
12
+ drill "can't include Attic raises exception", :exception, RuntimeError do
13
+ class ::Worker
14
+ include Attic
15
+ end
16
+ end
17
+
18
+ drill "can define attic attribute", true do
19
+ Worker.attic :size
20
+ w = Worker.new
21
+ #w.attic :size
22
+ stash :methods, w.methods.sort
23
+ stash :metamethods, Worker.methods.sort
24
+ w.respond_to? :size
25
+ end
26
+
27
+ end
28
+
@@ -0,0 +1,34 @@
1
+ group "Attic"
2
+ library :attic, "lib"
3
+ tryouts "Setting and Getting" do
4
+
5
+ setup do
6
+ class ::Worker
7
+ extend Attic
8
+ attic :size
9
+ end
10
+ end
11
+
12
+ drill "save an instance variable the long way", 'S&F' do
13
+ w = Worker.new
14
+ w.metametaclass.instance_variable_set '@mattress', 'S&F'
15
+ w.metametaclass.instance_variable_get '@mattress'
16
+ end
17
+
18
+ drill "save an instance variable the short way", :california_king do
19
+ w = Worker.new
20
+ w.size = :california_king
21
+ w.size
22
+ end
23
+
24
+ drill "new instances don't cross streams", nil do
25
+ w = Worker.new
26
+ w.size
27
+ end
28
+
29
+ drill "instance variables are hidden", [] do
30
+ w = Worker.new
31
+ w.metametaclass.instance_variable_set '@mattress', 'S&F'
32
+ w.instance_variables
33
+ end
34
+ end
@@ -0,0 +1,38 @@
1
+ group "Attic"
2
+ library :attic, "lib"
3
+ tryouts "String Setting and Getting" do
4
+
5
+ drill "String can extend Attic", true do
6
+ String.extend Attic
7
+ String.respond_to? :attic
8
+ end
9
+
10
+ drill "save an instance variable the long way", 'S&F' do
11
+ s = ""
12
+ s.metametaclass.instance_variable_set '@mattress', 'S&F'
13
+ s.metametaclass.instance_variable_get '@mattress'
14
+ end
15
+
16
+ drill "can create attributes", [:goodies] do
17
+ String.attic :goodies
18
+ end
19
+
20
+ drill "save an instance variable the short way", :california_king do
21
+ s = ""
22
+ s.goodies = :california_king
23
+ stash :ivars, s.instance_variables
24
+ stash :avars, s.attic_vars
25
+ s.goodies
26
+ end
27
+
28
+ drill "String instances don't cross streams", false do
29
+ String.extend Attic
30
+ String.attic :name
31
+ a = "any"
32
+ a.name = :roger
33
+ a.name == "".name
34
+ end
35
+
36
+
37
+
38
+ end
@@ -0,0 +1,24 @@
1
+ group "No Meta Class"
2
+ library :attic, 'lib'
3
+ tryouts "Basics" do
4
+
5
+ dream :class, Array
6
+ dream [Symbol, Fixnum]
7
+ drill "has list of no metaclass classes" do
8
+ Object::NOMETACLASS
9
+ end
10
+
11
+ drill "Symbol metaclass returns Symbol", Symbol do
12
+ :any.metaclass
13
+ end
14
+
15
+ ## NOTE: fails
16
+ drill "Symbol instances don't cross streams", true do
17
+ Symbol.extend Attic
18
+ Symbol.attic :name
19
+ a = :any
20
+ a.name = :roger
21
+ [a.name, :another.name]
22
+ end
23
+
24
+ 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
+
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"
4
+ version: 0.3.1
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 00:00:00 -04:00
12
+ date: 2009-07-13 00:00:00 -04:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -29,6 +29,15 @@ files:
29
29
  - README.rdoc
30
30
  - Rakefile
31
31
  - attic.gemspec
32
+ - lib/attic.rb
33
+ - lib/attic/mixins.rb
34
+ - lib/attic/mixins/object.rb
35
+ - try/01_mixins_tryouts.rb
36
+ - try/10_attic_tryouts.rb
37
+ - try/20_accessing_tryouts.rb
38
+ - try/25_string_tryouts.rb
39
+ - try/30_nometaclass_tryouts.rb
40
+ - try/metaclasses.rb
32
41
  has_rdoc: true
33
42
  homepage: http://github.com/delano/attic
34
43
  licenses: []