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

Sign up to get free protection for your applications and to get access to all the features.
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