meta_instance 1.0.2 → 1.1.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.
- checksums.yaml +4 -4
- data/.codeclimate.yml +7 -0
- data/.gitignore +33 -16
- data/.travis.yml +8 -4
- data/Gemfile +2 -3
- data/Gemfile.lock +66 -0
- data/HISTORY.md +33 -0
- data/LICENSE.txt +23 -0
- data/README.md +56 -25
- data/docs/instance.md +201 -0
- data/docs/module.md +34 -0
- data/lib/meta_instance.rb +32 -53
- data/lib/meta_instance/freeze_method.rb +13 -0
- data/lib/meta_instance/instance_method_define.rb +61 -0
- data/lib/meta_instance/module_extensions.rb +61 -0
- data/lib/meta_instance/proxy.rb +270 -0
- data/lib/meta_instance/version.rb +2 -2
- data/meta_instance.gemspec +4 -3
- data/spec/instance_spec.rb +123 -0
- data/spec/{meta_instance_spec.rb → meta_instance/instance_method_define_spec.rb} +22 -15
- data/spec/module_spec.rb +0 -0
- data/spec/spec_helper.rb +1 -3
- metadata +35 -11
- data/.rspec +0 -2
- data/LICENSE +0 -22
- data/Rakefile +0 -1
- data/spec/support/foo.rb +0 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b5ac0a81bfddb2ae4fbf907fa143708453c7d0e9
|
4
|
+
data.tar.gz: 5a1caa2e9320ac41222b9ba149a1e7c5aec0c61d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fa17b965044435b3f57dd1b2c2b8a04fa5d60d827a973907b229e214725389228ef688f2c2b7a31c7ab449b416773b72746219d1646de685680fec40964befd0
|
7
|
+
data.tar.gz: 8a5f58deae6e2e3dae92c2a3812e25af21d2730b380de4753cc29c8c7ce9a8073b3fbfaaeb6498f0b794d9cfbfda06bfcb8470d54432be6c7afe8b2f50be6f84
|
data/.codeclimate.yml
ADDED
data/.gitignore
CHANGED
@@ -1,18 +1,35 @@
|
|
1
1
|
*.gem
|
2
2
|
*.rbc
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
3
|
+
/.config
|
4
|
+
/coverage/
|
5
|
+
/InstalledFiles
|
6
|
+
/pkg/
|
7
|
+
/spec/reports/
|
8
|
+
/test/tmp/
|
9
|
+
/test/version_tmp/
|
10
|
+
/tmp/
|
11
|
+
|
12
|
+
## Specific to RubyMotion:
|
13
|
+
.dat*
|
14
|
+
.repl_history
|
15
|
+
build/
|
16
|
+
|
17
|
+
## Documentation cache and generated files:
|
18
|
+
/.yardoc/
|
19
|
+
/_yardoc/
|
20
|
+
/doc/
|
21
|
+
/rdoc/
|
22
|
+
|
23
|
+
## Environment normalisation:
|
24
|
+
/.bundle/
|
25
|
+
/vendor/bundle
|
26
|
+
/lib/bundler/man/
|
27
|
+
|
28
|
+
# for a library or gem, you might want to ignore these files since the code is
|
29
|
+
# intended to run in multiple environments; otherwise, check them in:
|
30
|
+
# Gemfile.lock
|
31
|
+
# .ruby-version
|
32
|
+
# .ruby-gemset
|
33
|
+
|
34
|
+
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
35
|
+
.rvmrc
|
data/.travis.yml
CHANGED
@@ -1,13 +1,17 @@
|
|
1
1
|
language: ruby
|
2
2
|
bundler_args: --without guard
|
3
3
|
rvm:
|
4
|
-
-
|
5
|
-
-
|
4
|
+
- 2.0.0
|
5
|
+
- 2.2
|
6
6
|
- ruby-head
|
7
|
-
|
7
|
+
matrix:
|
8
|
+
allow_failures:
|
9
|
+
- rvm:
|
10
|
+
- ruby-head
|
11
|
+
script: bundle exec rspec
|
8
12
|
addons:
|
9
13
|
code_climate:
|
10
|
-
repo_token:
|
14
|
+
repo_token: "97758529c5c06792d2f683e15e6ffe819ac16d140fe244640dcf103f1d172fc4 "
|
11
15
|
branches:
|
12
16
|
only: master
|
13
17
|
notifications:
|
data/Gemfile
CHANGED
data/Gemfile.lock
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
meta_instance (1.1.0)
|
5
|
+
activesupport
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: https://rubygems.org/
|
9
|
+
specs:
|
10
|
+
activesupport (4.2.1)
|
11
|
+
i18n (~> 0.7)
|
12
|
+
json (~> 1.7, >= 1.7.7)
|
13
|
+
minitest (~> 5.1)
|
14
|
+
thread_safe (~> 0.3, >= 0.3.4)
|
15
|
+
tzinfo (~> 1.1)
|
16
|
+
byebug (4.0.5)
|
17
|
+
columnize (= 0.9.0)
|
18
|
+
codeclimate-test-reporter (0.4.7)
|
19
|
+
simplecov (>= 0.7.1, < 1.0.0)
|
20
|
+
coderay (1.1.0)
|
21
|
+
columnize (0.9.0)
|
22
|
+
diff-lcs (1.2.5)
|
23
|
+
docile (1.1.5)
|
24
|
+
i18n (0.7.0)
|
25
|
+
json (1.8.2)
|
26
|
+
method_source (0.8.2)
|
27
|
+
minitest (5.6.1)
|
28
|
+
pry (0.10.1)
|
29
|
+
coderay (~> 1.1.0)
|
30
|
+
method_source (~> 0.8.1)
|
31
|
+
slop (~> 3.4)
|
32
|
+
pry-byebug (3.1.0)
|
33
|
+
byebug (~> 4.0)
|
34
|
+
pry (~> 0.10)
|
35
|
+
rspec (3.2.0)
|
36
|
+
rspec-core (~> 3.2.0)
|
37
|
+
rspec-expectations (~> 3.2.0)
|
38
|
+
rspec-mocks (~> 3.2.0)
|
39
|
+
rspec-core (3.2.3)
|
40
|
+
rspec-support (~> 3.2.0)
|
41
|
+
rspec-expectations (3.2.1)
|
42
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
43
|
+
rspec-support (~> 3.2.0)
|
44
|
+
rspec-mocks (3.2.1)
|
45
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
46
|
+
rspec-support (~> 3.2.0)
|
47
|
+
rspec-support (3.2.2)
|
48
|
+
simplecov (0.10.0)
|
49
|
+
docile (~> 1.1.0)
|
50
|
+
json (~> 1.8)
|
51
|
+
simplecov-html (~> 0.10.0)
|
52
|
+
simplecov-html (0.10.0)
|
53
|
+
slop (3.6.0)
|
54
|
+
thread_safe (0.3.5)
|
55
|
+
tzinfo (1.2.2)
|
56
|
+
thread_safe (~> 0.1)
|
57
|
+
|
58
|
+
PLATFORMS
|
59
|
+
ruby
|
60
|
+
|
61
|
+
DEPENDENCIES
|
62
|
+
bundler
|
63
|
+
codeclimate-test-reporter
|
64
|
+
meta_instance!
|
65
|
+
pry-byebug
|
66
|
+
rspec
|
data/HISTORY.md
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# RELEASE HISTORY
|
2
|
+
|
3
|
+
## 1.1.0 | 2015-05-27
|
4
|
+
|
5
|
+
This release prepares for gemification.
|
6
|
+
|
7
|
+
Changes:
|
8
|
+
|
9
|
+
* Add RSpec Tests
|
10
|
+
* Prep for gem publishing
|
11
|
+
* Merge code with NullVoxPopuli/meta_instance
|
12
|
+
* New Architecture
|
13
|
+
* Rename to MetaInstance, replacing existing meta_instance gem
|
14
|
+
|
15
|
+
|
16
|
+
## 0.2.0 | 2014-02-02
|
17
|
+
|
18
|
+
This release adds an extra set of methods for modules and classes.
|
19
|
+
|
20
|
+
Changes:
|
21
|
+
|
22
|
+
* Add `method_definition` if object is a module or class.
|
23
|
+
* Add `method_definitions` if object is a module or class.
|
24
|
+
|
25
|
+
|
26
|
+
## 0.1.0 | 2014-02-01
|
27
|
+
|
28
|
+
This is the initial release of Instance, a class spun-off from
|
29
|
+
Ruby Facets.
|
30
|
+
|
31
|
+
Changes:
|
32
|
+
|
33
|
+
* Happy Release Day!
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
BSD-2-Clause License (http://spdx.org/licenses/BSD-2-Clause)
|
2
|
+
|
3
|
+
Redistribution and use in source and binary forms, with or without modification, are
|
4
|
+
permitted provided that the following conditions are met:
|
5
|
+
|
6
|
+
1. Redistributions of source code must retain the above copyright notice, this list of
|
7
|
+
conditions and the following disclaimer.
|
8
|
+
|
9
|
+
2. Redistributions in binary form must reproduce the above copyright notice, this list
|
10
|
+
of conditions and the following disclaimer in the documentation and/or other materials
|
11
|
+
provided with the distribution.
|
12
|
+
|
13
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
14
|
+
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
|
16
|
+
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
17
|
+
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
18
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
19
|
+
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
20
|
+
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
21
|
+
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
22
|
+
|
23
|
+
|
data/README.md
CHANGED
@@ -1,42 +1,73 @@
|
|
1
1
|
MetaInstance
|
2
|
-
|
2
|
+
========
|
3
|
+
[](http://badge.fury.io/rb/meta_instance)
|
4
|
+
[](https://travis-ci.org/NullVoxPopuli/MetaInstance)
|
5
|
+
[](https://codeclimate.com/github/NullVoxPopuli/MetaInstance)
|
6
|
+
[](https://codeclimate.com/github/NullVoxPopuli/MetaInstance)
|
7
|
+
[](https://gemnasium.com/NullVoxPopuli/MetaInstance)
|
3
8
|
|
4
|
-
[](http://badge.fury.io/rb/meta_instance)
|
5
|
-
[](https://travis-ci.org/NullVoxPopuli/MetaInstance)
|
6
|
-
[](https://codeclimate.com/github/NullVoxPopuli/MetaInstance)
|
7
|
-
[](https://codeclimate.com/github/NullVoxPopuli/MetaInstance)
|
8
|
-
[](https://gemnasium.com/NullVoxPopuli/MetaInstance)
|
9
|
-
[](https://hakiri.io/github/NullVoxPopuli/MetaInstance/master)
|
10
9
|
|
11
|
-
A few helpers for manipulating methods on an instance of an object.
|
12
10
|
|
11
|
+
## What Is It?
|
13
12
|
|
14
|
-
|
13
|
+
MetaInstance is a *convenient* and *safe* API for accessing and manipulating
|
14
|
+
an object's state.
|
15
15
|
|
16
|
-
|
16
|
+
## How Does It Work
|
17
17
|
|
18
|
-
|
18
|
+
MetaInstance adds a method to all objects called `#instance`. It returns
|
19
|
+
an `Instance` delegator that provides the full interface to the
|
20
|
+
object's state.
|
19
21
|
|
20
|
-
|
22
|
+
Of course, without implementing this in C, directly in the Ruby source,
|
23
|
+
we are left to depend on the current provisions Ruby has for accessing
|
24
|
+
the state of an object. So there are some limitations here. However,
|
25
|
+
we implement the Ruby code in such a way as to minimize the downsides
|
26
|
+
by caching all the method definitions the Instance class will utilize.
|
21
27
|
|
22
|
-
|
23
|
-
include MetaInstance
|
28
|
+
## Usage
|
24
29
|
|
25
|
-
|
30
|
+
Let's use a very simple example class with which to demonstrate usage.
|
31
|
+
|
32
|
+
```ruby
|
33
|
+
class Song
|
34
|
+
attr_accessor :title
|
35
|
+
attr_accessor :artist
|
36
|
+
attr_accessor :year
|
37
|
+
|
38
|
+
def initialize(title, artist, year)
|
39
|
+
@title = title
|
40
|
+
@artist = artist
|
41
|
+
@year = year
|
42
|
+
end
|
26
43
|
end
|
44
|
+
```
|
45
|
+
|
46
|
+
Now we can create an instance of Song and work with it's state.
|
47
|
+
|
48
|
+
```ruby
|
49
|
+
song = Song.new("Paranoid", "Black Sabbath", 1970)
|
50
|
+
|
51
|
+
song.instance.variables
|
52
|
+
# => [:@title, :@artist, :@year]
|
53
|
+
|
54
|
+
song.instance.get(:title)
|
55
|
+
# => "Paranoid"
|
56
|
+
|
57
|
+
song.instance[:artist]
|
58
|
+
# => "Black Sabbath"
|
59
|
+
|
60
|
+
song.instance.to_h
|
61
|
+
# => {:title => "Paranoid", :artist => "Black Sabbath", :year => 1970}
|
62
|
+
```
|
27
63
|
|
28
|
-
|
64
|
+
For a more complete set of usage examples see the [QED](http://rubyworks.github.com/instance/qed.html) documentation.
|
29
65
|
|
30
|
-
f = Foo.new
|
31
|
-
f.bar
|
32
|
-
# => "bar"
|
33
66
|
|
34
|
-
|
35
|
-
f.bar
|
36
|
-
# => "foo"
|
67
|
+
## Copyrights
|
37
68
|
|
38
|
-
|
39
|
-
# => "bar"
|
69
|
+
Copyright © 2014 [Rubyworks](http://rubyworks.github.io)
|
40
70
|
|
71
|
+
BSD-2-Clause License
|
41
72
|
|
42
|
-
See
|
73
|
+
See [LICENSE.txt](LICENSE.txt) file for license details.
|
data/docs/instance.md
ADDED
@@ -0,0 +1,201 @@
|
|
1
|
+
# Instance
|
2
|
+
|
3
|
+
First thing we need to do, of course, is load the library.
|
4
|
+
|
5
|
+
require 'instance'
|
6
|
+
|
7
|
+
Now we can create an example class with which to work.
|
8
|
+
|
9
|
+
class ::Friend
|
10
|
+
attr_accessor :name, :age, :phone
|
11
|
+
|
12
|
+
def initialize(name, age, phone)
|
13
|
+
@name, @age, @phone = name, age, phone
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
And now demonstrate the available API.
|
18
|
+
|
19
|
+
## Instance#variables
|
20
|
+
|
21
|
+
A list of instance variables can be had via the `#variables` method.
|
22
|
+
|
23
|
+
f = Friend.new("John", 30, "555-1212")
|
24
|
+
f.instance.variables.assert == [:@name, :@age, :@phone]
|
25
|
+
|
26
|
+
## Instance#names
|
27
|
+
|
28
|
+
To get a list of variables names as strings and without the `@` prefix,
|
29
|
+
use the `#names` method.
|
30
|
+
|
31
|
+
f = Friend.new("John", 30, "555-1212")
|
32
|
+
f.instance.names.assert == ["name", "age", "phone"]
|
33
|
+
|
34
|
+
## Instance#keys
|
35
|
+
|
36
|
+
Likewise, to get symbols instead of strings, use the `#keys` method.
|
37
|
+
|
38
|
+
f = Friend.new("John", 30, "555-1212")
|
39
|
+
f.instance.keys.assert == [:name, :age, :phone]
|
40
|
+
|
41
|
+
## Instance#values
|
42
|
+
|
43
|
+
The values of the instance variables alone can be had via the `#values` method.
|
44
|
+
|
45
|
+
f = Friend.new("John", 30, "555-1212")
|
46
|
+
f.instance.values.assert == ["John", 30, "555-1212"]
|
47
|
+
|
48
|
+
## Instance#size
|
49
|
+
|
50
|
+
The `#size` method reports how many instance variables are defined.
|
51
|
+
|
52
|
+
f = Friend.new("John", 30, "555-1212")
|
53
|
+
f.instance.size.assert == 3
|
54
|
+
|
55
|
+
This method is primarily of use to the Enumerable mixin.
|
56
|
+
|
57
|
+
## Instance#variable_defined?
|
58
|
+
|
59
|
+
f = Friend.new("John", 30, "555-1212")
|
60
|
+
f.instance.assert.variable_defined?(:@name)
|
61
|
+
f.instance.assert.variable_defined?(:name)
|
62
|
+
|
63
|
+
## Instance#update
|
64
|
+
|
65
|
+
The `#update` method can be used to change instance variables in mass via
|
66
|
+
method options.
|
67
|
+
|
68
|
+
f = Friend.new("John", 30, "555-1212")
|
69
|
+
f.name.assert == 'John'
|
70
|
+
f.instance.update(:name=>'Jerry')
|
71
|
+
f.name.assert == 'Jerry'
|
72
|
+
|
73
|
+
## Instance#assign
|
74
|
+
|
75
|
+
The `#assign` method is simply an alias for `#update`.
|
76
|
+
|
77
|
+
f = Friend.new("John", 30, "555-1212")
|
78
|
+
f.instance.assign(:name=>'Joe')
|
79
|
+
f.name.assert == 'Joe'
|
80
|
+
|
81
|
+
## Instance#to_h
|
82
|
+
|
83
|
+
We can convert the object's state, i.e. it's instance variable names and values
|
84
|
+
into a Hash very easily with the `#to_h` method.
|
85
|
+
|
86
|
+
f1 = Friend.new("John", 30, "555-1212")
|
87
|
+
f1.instance.to_h.assert == {:name=>"John", :age=>30, :phone=>"555-1212"}
|
88
|
+
|
89
|
+
Notice that the `@` has beenn removed from the instance variable names. If we
|
90
|
+
want the `@` to stay simply pass `true` to the `#to_h` method.
|
91
|
+
|
92
|
+
f1 = Friend.new("John", 30, "555-1212")
|
93
|
+
f1.instance.to_h(true).assert == {:@name=>"John", :@age=>30, :@phone=>"555-1212"}
|
94
|
+
|
95
|
+
## Instance#class
|
96
|
+
|
97
|
+
To know the class of an object use the `#class` method.
|
98
|
+
|
99
|
+
f = Friend.new("John", 30, "555-1212")
|
100
|
+
f.instance.class.assert == ::Friend
|
101
|
+
|
102
|
+
Note that to get the class of Instance itself, you must use `#object_class`.
|
103
|
+
|
104
|
+
## Instance#id
|
105
|
+
|
106
|
+
To know the id of an object use the `#id` method.
|
107
|
+
|
108
|
+
f = Friend.new("John", 30, "555-1212")
|
109
|
+
f.instance.id == f.object_id
|
110
|
+
|
111
|
+
## Instance#of?
|
112
|
+
|
113
|
+
f = Friend.new("John", 30, "555-1212")
|
114
|
+
f.instance.assert.of?(::Friend)
|
115
|
+
|
116
|
+
## Instance#get
|
117
|
+
|
118
|
+
To get the value of a specific instance variable use the `#get` or `#[]`
|
119
|
+
methods.
|
120
|
+
|
121
|
+
f = Friend.new("John", 30, "555-1212")
|
122
|
+
f.instance.get(:name).assert == "John"
|
123
|
+
f.instance[:name].assert == "John"
|
124
|
+
|
125
|
+
## Instance#set
|
126
|
+
|
127
|
+
To set the value of a specific instance variable use the `#set` or `#[]=`
|
128
|
+
methods.
|
129
|
+
|
130
|
+
f = Friend.new("John", 30, "555-1212")
|
131
|
+
|
132
|
+
f.instance.set(:name, "Bill")
|
133
|
+
f.name.assert == "Bill"
|
134
|
+
|
135
|
+
f.instance[:name] = "Billy"
|
136
|
+
f.name.assert == "Billy"
|
137
|
+
|
138
|
+
## Instance#remove
|
139
|
+
|
140
|
+
To remove an instance variable from an object use the `#remove` method.
|
141
|
+
|
142
|
+
f = Friend.new("John", 30, "555-1212")
|
143
|
+
f.instance.remove(:name)
|
144
|
+
f.instance.refute.variable_defined?(:@name)
|
145
|
+
|
146
|
+
## Instance#method
|
147
|
+
|
148
|
+
The Instance class provides a `method` method for getting a Method object for
|
149
|
+
any of the target object's methods by name.
|
150
|
+
|
151
|
+
f1 = Friend.new("John", 30, "555-1212")
|
152
|
+
m = f1.instance.method(:name)
|
153
|
+
m.assert.is_a?(::Method)
|
154
|
+
|
155
|
+
This can seem a little confusing because Ruby's `instance_method` method actually
|
156
|
+
returns an `UnboundMethod` object. Unfortunately Ruby's use of the term `instance_method`
|
157
|
+
is a complete misnomer. It should be something like `method_definition` instead.
|
158
|
+
The actual *instance method* is the object's method.
|
159
|
+
|
160
|
+
## Instance#methods
|
161
|
+
|
162
|
+
We can also get a whole list of an object's methods via the `#methods` method.
|
163
|
+
|
164
|
+
f = Friend.new("John", 30, "555-1212")
|
165
|
+
f.instance.methods
|
166
|
+
f.instance.methods(:private)
|
167
|
+
f.instance.methods(:protected)
|
168
|
+
f.instance.methods(:public)
|
169
|
+
f.instance.methods(:public, :private)
|
170
|
+
|
171
|
+
## Instance#eval
|
172
|
+
|
173
|
+
To evaluate code in the context to the object's instance use the `#eval` method.
|
174
|
+
|
175
|
+
f = Friend.new("John", 30, "555-1212")
|
176
|
+
f.instance.eval("@name").assert == "John"
|
177
|
+
|
178
|
+
## Instance#exec
|
179
|
+
|
180
|
+
Likewise the `#exec` method can also be used.
|
181
|
+
|
182
|
+
f = Friend.new("John", 30, "555-1212")
|
183
|
+
f.instance.exec{ @name }.assert == "John"
|
184
|
+
|
185
|
+
## Instance#send
|
186
|
+
|
187
|
+
Sending a message to an object as if within the object itself and thus by-passing
|
188
|
+
method visibility is somehting that should only be done as an act of *metaprogramming*.
|
189
|
+
Hence it makes sense for it to be done via the `instance` interface.
|
190
|
+
|
191
|
+
f = Friend.new("John", 30, "555-1212")
|
192
|
+
f.instance.send(:name).assert == "John"
|
193
|
+
|
194
|
+
## Instance#delegate
|
195
|
+
|
196
|
+
To get at the delegated object of an Instance, use the `#delegate` method.
|
197
|
+
|
198
|
+
f = Friend.new("John", 30, "555-1212")
|
199
|
+
f.instance.delegate.assert == f
|
200
|
+
|
201
|
+
|