attic 0.9.0.pre.rc2 → 1.0.0.pre.RC3

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5b8515c2812b3e4523d79d1fae98c348f041b4d6862d632e7a41ff4fb6555d7a
4
- data.tar.gz: 29f3b9a07abb04e0d4611724a015ff8a0fcb704d7d8f3038d4ecd99ed6ae6768
3
+ metadata.gz: cd963a291df8b9b731adac87c5886f9f25b83606c7a171347d0e6e8396c98533
4
+ data.tar.gz: '0113974e4554b99b6061005f7d0218398592384d7bcd85f2fe4899b0d51232e9'
5
5
  SHA512:
6
- metadata.gz: 37911f6e23435f00b28f5d75643d2e250ee760c9ddee7049b6296dc3f5eaf6a00a48a9a6d3c484e9e9fd24e3feb15b57afaf7cc33d1e9456be80a8383840a360
7
- data.tar.gz: bf9811b8008f3d292c0be8087202785ada8fda996ba352194d8d77652fc997ef0c2d9fe324f710493459f6aa79939472569d11bd68a25b6e4c7c31021b8c9c05
6
+ metadata.gz: 92fcb090695086fcfa85472d69f8f2631054c035c99f3024f7cebc67b730e418c6ed650f2c8042f4c6882e6782c1febea6fc73768c43258e6e84d28d6219c149
7
+ data.tar.gz: a22f7131a2aca63c30bde0546c3ad0fdf77ef095b3d2cd5ed23853da02b314535c26771a900df059de056a76e32d50ad5e4802eab943736e9b423719ad036731
data/Gemfile.lock CHANGED
@@ -5,7 +5,7 @@ GEM
5
5
  byebug (11.1.3)
6
6
  coderay (1.1.3)
7
7
  drydock (0.6.9)
8
- json (2.7.1)
8
+ json (2.7.2)
9
9
  language_server-protocol (3.17.0.3)
10
10
  method_source (1.0.0)
11
11
  parallel (1.24.0)
@@ -46,8 +46,7 @@ GEM
46
46
  yard (0.9.36)
47
47
 
48
48
  PLATFORMS
49
- arm64-darwin-23
50
- ruby
49
+ arm64-darwin-22
51
50
 
52
51
  DEPENDENCIES
53
52
  byebug
@@ -57,7 +56,7 @@ DEPENDENCIES
57
56
  tryouts (= 2.2.0.pre.RC1)
58
57
 
59
58
  RUBY VERSION
60
- ruby 3.1.4p223
59
+ ruby 3.2.0p0
61
60
 
62
61
  BUNDLED WITH
63
- 2.5.7
62
+ 2.4.12
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Attic - v1.0-RC1 (2023-03-15)
1
+ # Attic - v1.0-RC1 (2024-04-01)
2
2
 
3
3
  A place to hide private instance variables in your Ruby objects: in the attic.
4
4
 
@@ -11,6 +11,7 @@ Like, _why though_? Well sometimes you want to hide thing from the public interf
11
11
 
12
12
  ### Example
13
13
 
14
+
14
15
  ```ruby
15
16
  require 'attic'
16
17
 
@@ -49,7 +50,7 @@ Like, _why though_? Well sometimes you want to hide thing from the public interf
49
50
 
50
51
  ### **Objects without singleton classes
51
52
 
52
- Symbol, Integer, Float, TrueClass, FalseClass, NilClass, and Fixnum are all objects that do not have singleton classes. TrueClass, FalseClass, and NilClass are all singletons themselves. Fixnum is a singleton of Integer.
53
+ Symbol, Integer, Float, TrueClass, FalseClass, NilClass, and Integer are all objects that do not have singleton classes. TrueClass, FalseClass, and NilClass are all singletons themselves. Integer is a singleton of Integer.
53
54
 
54
55
  These objects do not have metaclasses so the attic is hidden in the object itself.
55
56
 
@@ -139,10 +140,6 @@ which produced the same results for both.
139
140
  ]
140
141
  ```
141
142
 
142
- ## Credits
143
-
144
- * (@delano) Delano Mandelbaum
145
-
146
143
 
147
144
  ## License
148
145
 
data/attic.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "attic"
3
- s.version = "0.9.0-rc2"
3
+ s.version = "1.0.0-RC3"
4
4
  s.summary = "When in doubt, store it in the attic"
5
5
  s.description = "Attic: a place to hide metadata about the class or variable itself (e.g. SHA hash summaries)."
6
6
  s.authors = ["Delano Mandelbaum"]
@@ -21,8 +21,8 @@ module Attic
21
21
  # for the object. In either case, objects that cannot have
22
22
  # cannot have a dedicated singleton class (e.g. nil, true,
23
23
  # false) will raise a TypeError. We rescue this and add the
24
- # object to the NoSingletonError list so we don't have to
25
- # keep trying to access its singleton class.
24
+ # object to the NoSingletonError list so we don't keep
25
+ # trying to access its singleton class over and over.
26
26
  !singleton_class.nil?
27
27
 
28
28
  rescue TypeError
@@ -40,6 +40,8 @@ module Attic
40
40
 
41
41
  safe_name = "@_attic_#{name}"
42
42
  instance_variable_set(safe_name, name)
43
+ rescue TypeError => e
44
+ raise NoSingletonError, name, caller
43
45
  end
44
46
 
45
47
  def attic_variable?(name)
@@ -8,12 +8,39 @@ module Attic
8
8
  module InstanceMethods
9
9
 
10
10
  def attic
11
- raise NoSingleton, self, caller unless attic?
11
+ raise NoSingletonError, self, caller unless attic?
12
12
 
13
13
  singleton_class
14
14
 
15
15
  rescue TypeError
16
- NoSingleton.add_member self
16
+ NoSingletonError.add_member self
17
+ end
18
+
19
+ # A quick way to check if this object instance already has a
20
+ # dedicated singleton class. We like to know this upfront
21
+ # because this is where our attic variables are to be stored.
22
+ def attic?
23
+ return false if NoSingletonError.member? self
24
+
25
+ # NOTE: Calling this on an object for the first time lazily
26
+ # creates a singleton class for itself. Another way of doing
27
+ # the same thing is to attempt defining a singleton method
28
+ # for the object. In either case, objects that cannot have
29
+ # cannot have a dedicated singleton class (e.g. nil, true,
30
+ # false) will raise a TypeError. We rescue this and add the
31
+ # object to the NoSingletonError list so we don't keep
32
+ # trying to access its singleton class over and over.
33
+ #
34
+ # NOTE 2: Module#singleton_class? is only available for
35
+ # modules and classes (which are also modules); it is not
36
+ # available for instances of classes.
37
+ #
38
+ !singleton_class.nil?
39
+
40
+ rescue TypeError
41
+ # Remember for next time.
42
+ NoSingletonError.add_member self
43
+ false
17
44
  end
18
45
 
19
46
  def attic_variables
data/lib/attic.rb CHANGED
@@ -100,8 +100,7 @@ require_relative "attic/instance_methods"
100
100
  # nil.attic.object_id #=> 800
101
101
  #
102
102
  module Attic
103
- VERSION = '0.9.0-RC1'.freeze unless defined?(VERSION)
104
- attr_reader :all_attic_variables
103
+ VERSION = '1.0.0-RC3'.freeze unless defined?(VERSION)
105
104
 
106
105
  # A convenince method at the class level for including
107
106
  # ConstructMethods in the given object specifically.
@@ -121,8 +120,10 @@ module Attic
121
120
  obj.include Attic::ClassMethods
122
121
  end
123
122
 
123
+ # Friendly exception to say we're not to be included
124
+ #
124
125
  def self.included(obj)
125
- raise Runtime, "Did you to `extend Attic`` in #{obj}"
126
+ raise RuntimeError, "Did you mean to `extend Attic`` in #{obj}"
126
127
  end
127
128
 
128
129
  def self.extended(obj)
@@ -145,28 +146,29 @@ module Attic
145
146
  attic_vars = self.attic_variables.clone
146
147
  klass.attic.instance_variable_set("@attic_variables", attic_vars)
147
148
  end
148
- if method_defined? :instance_variables
149
- instance_variables_orig = instance_method(:instance_variables)
150
- define_method :instance_variables do
151
- ret = _instance_variables_orig.bind(self).call.clone
149
+ if obj.method_defined? :instance_variables
150
+ instance_variables_orig = obj.instance_method(:instance_variables)
151
+ obj.define_method :instance_variables do
152
+ ret = instance_variables_orig.bind(self).call.clone
152
153
  ret.reject! { |v| v.to_s =~ /^@___?attic/ } # match 2 or 3 underscores
153
154
  ret
154
155
  end
155
- define_method :all_instance_variables do
156
- _instance_variables_orig.bind(self).call
156
+ obj.define_method :all_instance_variables do
157
+ instance_variables_orig.bind(self).call
157
158
  end
158
159
  end
159
160
 
160
161
  rescue TypeError => e
161
- raise NoSingleton, obj, caller
162
+ raise NoSingletonError, obj, caller
162
163
  end
163
164
 
164
165
  # A class method for defining variables to store in the attic.
165
166
  # * +names+ is a list of variables names. Accessor methods are
166
167
  # created for each variable name in the list.
167
168
  #
168
- # Returns the list of attic variable names or if no names were
169
- # given, returns the attic.
169
+ # Returns an Array of all attic variables for the current
170
+ # class unless no arguments are given in which case it
171
+ # returns its singleton.
170
172
  #
171
173
  # e.g.
172
174
  #
@@ -178,12 +180,12 @@ module Attic
178
180
  # * <tt>String#timestamp</tt> for setting the value
179
181
  #
180
182
  def attic(*names)
181
- return all_attic_variables if names.empty?
183
+ return singleton_class if names.empty?
182
184
 
183
185
  names.each do |name|
184
186
  next if attic_variable? name
185
187
 
186
- self.all_attic_variables << name
188
+ self.attic_variables << name
187
189
 
188
190
  unless method_defined?(name)
189
191
  define_method(name) do
@@ -198,7 +200,17 @@ module Attic
198
200
  end
199
201
  end
200
202
 
201
- all_attic_variables
203
+ attic_variables # only after defining new attic vars
204
+ end
205
+
206
+ def attic?
207
+ return false if NoSingletonError.member? self
208
+
209
+ singleton_class?
210
+
211
+ rescue TypeError
212
+ NoSingletonError.add_member self
213
+ false
202
214
  end
203
215
 
204
216
  # Returns an Array of attic variables for the current class.
@@ -208,12 +220,11 @@ module Attic
208
220
  # String.attic :timestamp
209
221
  # String.attic_variables # => [:timestamp]
210
222
  #
211
- # def attic_variables
212
- # a = attic.instance_variable_get('@attic_variables')
213
- # a ||= attic.instance_variable_set('@attic_variables', [])
214
- # a
215
- # end
216
- # alias attic_vars attic_variables
223
+ def attic_variables
224
+ a = attic.instance_variable_get('@attic_variables')
225
+ a ||= attic.instance_variable_set('@attic_variables', [])
226
+ a
227
+ end
217
228
 
218
229
  def attic_variable?(name)
219
230
  attic_variables.member? name
@@ -1,17 +1,65 @@
1
- require 'attic'
1
+ require_relative '../lib/attic'
2
2
 
3
- ## has metaclass", 'Object' do
4
- if Tryouts.sysinfo.ruby.to_s == "1.9.1"
5
- Object.new.metaclass.superclass.to_s
6
- else
7
- 'Object'
8
- end
9
- #=> 'Object'
3
+ #
4
+ # Tests for the Object mixins that Attic relies on.
5
+ #
6
+
7
+ ## Has a valid NoMetaClass exception class
8
+ NoMetaClass < RuntimeError
9
+ #=> true
10
10
 
11
- ## has metametaclass", '#<Class:Object>' do
12
- if Tryouts.sysinfo.ruby.to_s >= "1.9.1"
13
- Object.new.metaclass.superclass.to_s
14
- else
15
- '#<Class:Object>'
11
+ ## Has a pre-populated array of built-ins without a metaclass
12
+ begin
13
+ Object::NOMETACLASS
14
+ rescue NameError => e
15
+ e.class
16
16
  end
17
- #=> 'Object'
17
+ #=> NameError
18
+
19
+ ## Has Object#metaclass method
20
+ Object.new.respond_to? :metaclass
21
+ #=> false
22
+
23
+ ## Has Object#singleton_class method
24
+ Object.new.respond_to? :singleton_class
25
+ #=> true
26
+
27
+ ## Object#singleton_class is a class
28
+ Object.new.singleton_class.class
29
+ #=> Class
30
+
31
+ ## Object#singleton_class is a class
32
+ Object.new.singleton_class.object_id.class
33
+ #=> Integer
34
+
35
+ ## Object#singleton_class is a class
36
+ a = Object.new
37
+ b = Object.new
38
+ a.singleton_class.object_id == b.singleton_class.object_id
39
+ #=> false
40
+
41
+ ## Object#singleton_class is an Object class
42
+ Object.new.singleton_class.superclass
43
+ #=> Object
44
+
45
+ ## Object#singleton_class is equivalent to `class << self; self; end;`
46
+ a = Object.new
47
+ a.singleton_class == (class << a; self; end)
48
+ #=> true
49
+
50
+ ## Integer doesn't have a singleton_class
51
+ Integer.singleton_class?
52
+ #=> false
53
+
54
+ ## Symbol doesn't have a singleton_class
55
+ Symbol.singleton_class?
56
+ #=> false
57
+
58
+ ## Object has a singleton_class
59
+ Object.singleton_class?
60
+ #=> false
61
+
62
+ ## Object#singleton_class is equivalent to Object#singleton_class
63
+ a = Object.new
64
+ a.singleton_class == a.singleton_class
65
+ #=> true
@@ -1,41 +1,51 @@
1
- require 'attic'
2
-
3
- ## can extend Attic
4
- class ::Worker
1
+ require_relative '../lib/attic'
2
+
3
+ #
4
+ # Tests for the Attic module
5
+ #
6
+
7
+ ## A class we define can extend Attic
8
+ class ::ExampleClass
5
9
  extend Attic
6
- def kind() :true end
10
+ def kind() :unlikely_value end
7
11
  end
8
- # 1.9 # 1.8
9
- Worker.methods.member?(:attic) || Worker.methods.member?('attic')
12
+ ExampleClass.methods.member?(:attic)
10
13
  #=> true
11
-
12
- ## can't include Attic raises exception
14
+
15
+ ## Trying to include Attic raises an exception
13
16
  begin
14
- class ::Worker
17
+ class ::ExampleClass
15
18
  include Attic
16
19
  end
17
- rescue => RuntimeError
18
- :success
20
+ rescue => e
21
+ e.class
19
22
  end
20
- #=> :success
23
+ #=> RuntimeError
21
24
 
22
- ## can define attic attribute
23
- Worker.attic :size
24
- w = Worker.new
25
- #w.attic :size
26
- p Worker.instance_methods(false)
27
- p Worker.methods.sort
25
+ ## Can define attic variables at class level
26
+ ExampleClass.attic :size
27
+ w = ExampleClass.new
28
28
  w.respond_to? :size
29
- #=> true
30
-
31
- ## can access attic attributes explicitly"
32
- w = Worker.new
29
+ #=> true
30
+
31
+ ## Accessing attic vars at the instance level fails
32
+ begin
33
+ w = ExampleClass.new
34
+ w.attic :size, 2
35
+ rescue => e
36
+ e.class
37
+ end
38
+ #=> NoMethodError
39
+
40
+ ## Can access attic vars the long way though
41
+ w = ExampleClass.new
33
42
  w.attic_variable_set :size, 2
34
43
  w.attic_variable_get :size
35
44
  #=> 2
36
-
37
- ## won't define a method if on already exists
38
- Worker.attic :kind
39
- a = Worker.new
45
+
46
+ ## Won't clobber an existing method with the same name
47
+ ## NOTE: But also won't tell you it didn't define the method
48
+ ExampleClass.attic :kind
49
+ a = ExampleClass.new
40
50
  a.kind
41
- #=> :true
51
+ #=> :unlikely_value
@@ -1,29 +1,30 @@
1
- require 'attic'
1
+ require_relative '../lib/attic'
2
+
2
3
  class ::Worker
3
4
  extend Attic
4
5
  attic :size
5
6
  end
6
7
 
7
-
8
+
8
9
  ## save an instance variable the long way
9
10
  w = Worker.new
10
- w.metametaclass.instance_variable_set '@mattress', 'S&F'
11
- w.metametaclass.instance_variable_get '@mattress'
11
+ w.attic.instance_variable_set '@mattress', 'S&F'
12
+ w.attic.instance_variable_get '@mattress'
12
13
  #=> 'S&F'
13
-
14
+
14
15
  ## save an instance variable the short way
15
16
  w = Worker.new
16
17
  w.size = :california_king
17
18
  w.size
18
19
  #=> :california_king
19
-
20
+
20
21
  ## new instances don't cross streams
21
22
  w = Worker.new
22
23
  w.size
23
24
  #=> nil
24
-
25
+
25
26
  ## instance variables are hidden
26
27
  w = Worker.new
27
- w.metametaclass.instance_variable_set '@mattress', 'S&F'
28
+ w.attic.instance_variable_set '@mattress', 'S&F'
28
29
  w.instance_variables
29
30
  ## []
@@ -4,25 +4,25 @@ require 'attic'
4
4
  String.extend Attic
5
5
  String.respond_to? :attic
6
6
  #=> true
7
-
7
+
8
8
  ## save an instance variable the long way
9
9
  s = ""
10
- s.metametaclass.instance_variable_set '@mattress', 'S&F'
11
- s.metametaclass.instance_variable_get '@mattress'
10
+ s.attic.instance_variable_set '@mattress', 'S&F'
11
+ s.attic.instance_variable_get '@mattress'
12
12
  #=> 'S&F'
13
13
 
14
14
  ## can create attributes
15
15
  String.attic :goodies
16
16
  #=> [:goodies]
17
-
17
+
18
18
  ## save an instance variable the short way
19
19
  s = ""
20
20
  s.goodies = :california_king
21
21
  p s.instance_variables
22
- p s.attic_vars
22
+ p s.attic_variables
23
23
  s.goodies
24
24
  #=> :california_king
25
-
25
+
26
26
  ## String instances don't cross streams
27
27
  String.extend Attic
28
28
  String.attic :name
@@ -39,6 +39,14 @@ Symbol.extend Attic
39
39
  :any.attic?
40
40
  #=> false
41
41
 
42
+ ## A String's attic vars appear in `all_instance_variables` do
43
+ String.extend Attic
44
+ String.attic :_name
45
+ a, b = 'String1', 'String2'
46
+ a._name = :roger
47
+ a.all_instance_variables
48
+ #=> [:@___attic_name]
49
+
42
50
  ## A Symbol's attic vars appear in `all_instance_variables` do
43
51
  Symbol.extend Attic
44
52
  Symbol.attic :_name
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: attic
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0.pre.rc2
4
+ version: 1.0.0.pre.RC3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Delano Mandelbaum
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-04-03 00:00:00.000000000 Z
11
+ date: 2024-04-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -69,7 +69,6 @@ files:
69
69
  - attic.gemspec
70
70
  - lib/attic.rb
71
71
  - lib/attic/class_methods.rb
72
- - lib/attic/core_ext.rb
73
72
  - lib/attic/errors.rb
74
73
  - lib/attic/instance_methods.rb
75
74
  - try/01_mixins_tryouts.rb
@@ -78,9 +77,6 @@ files:
78
77
  - try/25_string_tryouts.rb
79
78
  - try/30_nometaclass_tryouts.rb
80
79
  - try/40_explicit_accessor_tryouts.rb
81
- - try/X1_metaclasses.rb
82
- - try/X2_extending.rb
83
- - try/X3_nosingleton.rb
84
80
  homepage: https://github.com/delano/attic
85
81
  licenses:
86
82
  - MIT
@@ -100,7 +96,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
100
96
  - !ruby/object:Gem::Version
101
97
  version: 1.3.1
102
98
  requirements: []
103
- rubygems_version: 3.3.26
99
+ rubygems_version: 3.4.12
104
100
  signing_key:
105
101
  specification_version: 4
106
102
  summary: When in doubt, store it in the attic
@@ -1,70 +0,0 @@
1
-
2
- class NoMetaClass < RuntimeError
3
- end
4
-
5
- # = Object
6
- #
7
- # These methods are copied directly from _why's metaid.rb.
8
- # See: http://whytheluckystiff.net/articles/seeingMetaclassesClearly.html
9
- class Object
10
-
11
- unless defined?(::Object::NOMETACLASS)
12
- # An Array of classes which do not have metaclasses.
13
- NOMETACLASS = [Symbol, Fixnum].freeze
14
- end
15
-
16
- def nometaclass?
17
- NOMETACLASS.member?(self)
18
- end
19
-
20
- def metaclass?
21
- !NOMETACLASS.member?(self.class)
22
- end
23
-
24
- # A convenient method for getting the metaclass of the current object.
25
- # i.e.
26
- #
27
- # class << self; self; end;
28
- #
29
- # NOTE: Some Ruby class do not have meta classes (see: NOMETACLASS).
30
- # For these classes, this method returns the class itself. That means
31
- # the instance variables will stored in the class itself.
32
- def metaclass
33
- if !self.metaclass?
34
- raise NoMetaClass, self
35
- else
36
- class << self; self; end;
37
- end
38
- end
39
-
40
- # Execute a block +&blk+ within the metaclass of the current object.
41
- def meta_eval &blk; metaclass.instance_eval &blk; end
42
-
43
- # Add an instance method called +name+ to metaclass for the current object.
44
- # This is useful because it will be available as a singleton method
45
- # to all subclasses too.
46
- def meta_def name, &blk
47
- meta_eval { define_method name, &blk }
48
- end
49
-
50
- # Add a class method called +name+ for the current object's class. This
51
- # isn't so special but it maintains consistency with meta_def.
52
- def class_def name, &blk
53
- class_eval { define_method name, &blk }
54
- end
55
-
56
-
57
- # A convenient method for getting the metaclass of the metaclass
58
- # i.e.
59
- #
60
- # self.metaclass.metaclass
61
- #
62
- def metametaclass; self.metaclass.metaclass; end
63
-
64
- def metameta_eval &blk; metametaclass.instance_eval &blk; end
65
-
66
- def metameta_def name, &blk
67
- metameta_eval { define_method name, &blk }
68
- end
69
-
70
- end
@@ -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
-
data/try/X2_extending.rb DELETED
@@ -1,27 +0,0 @@
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
-
@@ -1,44 +0,0 @@
1
-
2
-
3
- # "".has_singleton_class? # => true
4
- # :"".has_singleton_class? # => false
5
- # 1.has_singleton_class? # =>
6
- # nil.has_singleton_class? # => false
7
- # NilClass.has_singleton_class? # => true
8
-
9
- # members = ["", :food, 1, 1.00000001, nil, NilClass, true, TrueClass]
10
- # members2 = members.clone
11
-
12
- # members.each_with_index do |member, idx|
13
- # puts "member: #{member.inspect}"
14
- # member2 = members2[idx]
15
-
16
- # member.has_a_dedicated_singleton_class? # => false
17
- # member2.has_a_dedicated_singleton_class? # => false
18
- # member.bestow_a_singleton_class!
19
- # member.has_a_dedicated_singleton_class? # => true
20
- # member2.has_a_dedicated_singleton_class? # => false
21
- # member2.bestow_a_singleton_class!
22
- # member2.has_a_dedicated_singleton_class? # => true
23
-
24
- # member.singleton_class.object_id # => 600
25
- # member2.singleton_class.object_id # => 700
26
-
27
- # member.has_method?(:foo) # => false
28
- # member.foo # => NoMethodError
29
- # member.add_to_singleton_class(:foo)
30
- # member.has_method?(:foo) # => true
31
- # member.foo = :bar
32
- # member.foo # => :bar
33
- # member.foo.object_id # => 601
34
-
35
- # member2.has_method?(:foo) # => false
36
- # member2.foo # => NoMethodError
37
- # member2.add_to_singleton_class(:foo)
38
- # member2.has_method?(:foo) # => true
39
- # member2.foo = :bar
40
- # member2.foo # => :bar
41
- # member2.foo.object_id # => 701
42
-
43
- # member2.foo.object_id == member.foo.object_id # => false
44
- # end