symbiont-ruby 0.0.0 → 0.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/.gitignore +1 -2
- data/.hound.yml +2 -0
- data/.rspec +1 -1
- data/.rubocop.yml +119 -0
- data/.travis.yml +10 -3
- data/.yardopts +1 -0
- data/CHANGELOG.md +5 -0
- data/README.md +346 -18
- data/Rakefile +2 -2
- data/bin/console +4 -11
- data/lib/symbiont/context.rb +48 -0
- data/lib/symbiont/executor.rb +111 -0
- data/lib/symbiont/private_trigger.rb +24 -0
- data/lib/symbiont/public_trigger.rb +24 -0
- data/lib/symbiont/trigger.rb +269 -0
- data/lib/symbiont/version.rb +1 -1
- data/lib/symbiont.rb +37 -0
- data/symbiont-ruby.gemspec +30 -18
- metadata +113 -18
- data/CODE_OF_CONDUCT.md +0 -74
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 981797ea2447acb615faac8cefe3fc02c0d05b0e
|
4
|
+
data.tar.gz: 42fc09dd324faddd33a20d0c908251fb16e149e3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cfce829ffc18d93300100a9f25d474ab3907d40be4c81ce6abe4952e4fa2d5818d7fbb8d25f1f765db28ea0d1dd810d2afdeeac065afbbc22707deb4319df572
|
7
|
+
data.tar.gz: 956452d617195d896ec245e70b0b2ce04d9b2c42d21df1edb7e012cff670f8c61a3d811abdce0dd80f4cfe1c52aa91648ffdcea407febcbd2e978e0e51587255
|
data/.gitignore
CHANGED
data/.hound.yml
ADDED
data/.rspec
CHANGED
data/.rubocop.yml
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
require: rubocop-rspec
|
2
|
+
|
3
|
+
AllCops:
|
4
|
+
DisplayCopNames: true
|
5
|
+
DisplayStyleGuide: true
|
6
|
+
TargetRubyVersion: 2.4.3
|
7
|
+
Include:
|
8
|
+
- lib/**/*
|
9
|
+
- spec/**/*
|
10
|
+
Exclude:
|
11
|
+
- bin/**/*
|
12
|
+
- Gemfile
|
13
|
+
- Rakefile
|
14
|
+
- symbiont-ruby.gemspec
|
15
|
+
|
16
|
+
Style/SingleLineMethods:
|
17
|
+
Exclude:
|
18
|
+
- spec/**/*
|
19
|
+
|
20
|
+
Style/RescueModifier:
|
21
|
+
Exclude:
|
22
|
+
- spec/**/*
|
23
|
+
|
24
|
+
Style/AsciiComments:
|
25
|
+
Enabled: false
|
26
|
+
|
27
|
+
Style/Alias:
|
28
|
+
Enabled: false
|
29
|
+
|
30
|
+
Style/GuardClause:
|
31
|
+
Enabled: false
|
32
|
+
|
33
|
+
Style/DoubleNegation:
|
34
|
+
Enabled: false
|
35
|
+
|
36
|
+
Style/Documentation:
|
37
|
+
Enabled: false
|
38
|
+
|
39
|
+
Style/ClassAndModuleChildren:
|
40
|
+
Enabled: false
|
41
|
+
|
42
|
+
Style/EmptyCaseCondition:
|
43
|
+
Enabled: false
|
44
|
+
|
45
|
+
Style/FrozenStringLiteralComment:
|
46
|
+
Enabled: true
|
47
|
+
|
48
|
+
Style/InverseMethods:
|
49
|
+
Enabled: false
|
50
|
+
|
51
|
+
Style/ParallelAssignment:
|
52
|
+
Enabled: false
|
53
|
+
|
54
|
+
Style/CommentedKeyword:
|
55
|
+
Enabled: false
|
56
|
+
|
57
|
+
Layout/IndentArray:
|
58
|
+
Enabled: false
|
59
|
+
|
60
|
+
Lint/AmbiguousRegexpLiteral:
|
61
|
+
Enabled: false
|
62
|
+
|
63
|
+
Lint/UnusedMethodArgument:
|
64
|
+
Enabled: false
|
65
|
+
|
66
|
+
Naming/FileName:
|
67
|
+
Enabled: false
|
68
|
+
|
69
|
+
Naming/VariableNumber:
|
70
|
+
EnforcedStyle: snake_case
|
71
|
+
|
72
|
+
Metrics/LineLength:
|
73
|
+
Max: 100
|
74
|
+
|
75
|
+
Metrics/BlockLength:
|
76
|
+
Exclude:
|
77
|
+
- spec/**/*
|
78
|
+
|
79
|
+
Metrics/CyclomaticComplexity:
|
80
|
+
Max: 10
|
81
|
+
|
82
|
+
Metrics/PerceivedComplexity:
|
83
|
+
Max: 10
|
84
|
+
|
85
|
+
Metrics/MethodLength:
|
86
|
+
Max: 20
|
87
|
+
|
88
|
+
RSpec/ContextWording:
|
89
|
+
Enabled: false
|
90
|
+
|
91
|
+
RSpec/HookArgument:
|
92
|
+
Enabled: false
|
93
|
+
|
94
|
+
RSpec/NestedGroups:
|
95
|
+
Max: 6
|
96
|
+
|
97
|
+
RSpec/MessageSpies:
|
98
|
+
Enabled: false
|
99
|
+
|
100
|
+
RSpec/ExampleLength:
|
101
|
+
Enabled: false
|
102
|
+
|
103
|
+
RSpec/MultipleExpectations:
|
104
|
+
Enabled: false
|
105
|
+
|
106
|
+
RSpec/DescribeClass:
|
107
|
+
Enabled: false
|
108
|
+
|
109
|
+
RSpec/LetSetup:
|
110
|
+
Enabled: false
|
111
|
+
|
112
|
+
RSpec/AnyInstance:
|
113
|
+
Enabled: false
|
114
|
+
|
115
|
+
RSpec/MultipleSubjects:
|
116
|
+
Enabled: false
|
117
|
+
|
118
|
+
RSpec/EmptyLineAfterSubject:
|
119
|
+
Enabled: false
|
data/.travis.yml
CHANGED
data/.yardopts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--protected --private --markup markdown
|
data/CHANGELOG.md
ADDED
data/README.md
CHANGED
@@ -1,10 +1,11 @@
|
|
1
|
-
# Symbiont
|
1
|
+
# Symbiont · [](https://badge.fury.io/rb/symbiont-ruby) [](https://travis-ci.org/0exp/symbiont-ruby) [](https://coveralls.io/github/0exp/symbiont-ruby?branch=master)
|
2
2
|
|
3
|
-
|
3
|
+
**Symbiont** is a cool implementation of proc-objects execution algorithm: in the context of other object,
|
4
|
+
but with the preservation of the closed environment of the proc object and with the ability of control the method dispatch
|
5
|
+
inside it. A proc object is executed in three contexts: in the context of required object, in the context of
|
6
|
+
a closed proc's environment and in the global (Kernel) context.
|
4
7
|
|
5
|
-
|
6
|
-
|
7
|
-
## Installation
|
8
|
+
# Installation
|
8
9
|
|
9
10
|
Add this line to your application's Gemfile:
|
10
11
|
|
@@ -14,30 +15,357 @@ gem 'symbiont-ruby'
|
|
14
15
|
|
15
16
|
And then execute:
|
16
17
|
|
17
|
-
|
18
|
+
```shell
|
19
|
+
$ bundle install
|
20
|
+
```
|
18
21
|
|
19
22
|
Or install it yourself as:
|
20
23
|
|
21
|
-
|
24
|
+
```shell
|
25
|
+
$ gem install symbiont-ruby
|
26
|
+
```
|
27
|
+
|
28
|
+
After all:
|
29
|
+
|
30
|
+
```ruby
|
31
|
+
require 'symbiont'
|
32
|
+
```
|
33
|
+
|
34
|
+
# Table of contents
|
35
|
+
|
36
|
+
- [Problem and motivation](#problems-and-motivaiton)
|
37
|
+
- [Usage](#usage)
|
38
|
+
- [Context management](#context-management)
|
39
|
+
- [Supported method delegation directions](#supported-methods-delegation-directions)
|
40
|
+
- [Proc object invokation](#proc-object-invokation)
|
41
|
+
- [Considering public methods only (.evaluate)](#considering-public-methods-only-evaluate)
|
42
|
+
- [Considering private and public methods (.evaluate_private)](#considering-private-and-public-methods-evaluate_private)
|
43
|
+
- [Getting method-objects (Method)](#getting-method-objects-method)
|
44
|
+
- [Considering public methods only (.public_method)](#considering-public-methods-only-public_method)
|
45
|
+
- [Considering public and private methods (.private_method)](#considering-public-and-private-methods-private_method)
|
46
|
+
- [Symbiont Mixin](#symbiont-mixin)
|
47
|
+
- [Mixing a module with default delegation direction](#mixing-a-module-with-default-delegation-direction)
|
48
|
+
- [Mixing a module with certain delegation direction](#mixing-a-module-with-certain-delegation-direction)
|
49
|
+
|
50
|
+
# Problems and motivaiton
|
51
|
+
|
52
|
+
The main problem of `instance_eval` / `instance exec` / `class_eval` / `class_exec` is that the binding (self)
|
53
|
+
inside a proc-objec is replaced with the object in where a proc object is executed. This allows you to delegate all methods closed by a proc to another object.
|
54
|
+
But this leads to the fact that the proc object loses access to the original closed environment.
|
55
|
+
Symbiont solves this problem by allowing to proc to be executed in the required context while maintaining access to the methods of the closed environemnt
|
56
|
+
(including the global context).
|
57
|
+
|
58
|
+
---
|
59
|
+
|
60
|
+
A prroblem with `instance_eval` / `instance_exec` / `class_eval` / `class_exec`:
|
61
|
+
|
62
|
+
```ruby
|
63
|
+
class TableFactory
|
64
|
+
def initialize
|
65
|
+
@primary_key = nil
|
66
|
+
end
|
67
|
+
|
68
|
+
def primary_key(key)
|
69
|
+
@primary_key = key
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
class Migration
|
74
|
+
class << self
|
75
|
+
def create_table(&block)
|
76
|
+
TableFactory.new.tap do |table|
|
77
|
+
table.instance_eval(&block) # NOTE: closure invokation
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
class CreateUsers < Migration
|
84
|
+
class << self
|
85
|
+
def up
|
86
|
+
create_table do # NOTE: failing closure
|
87
|
+
primary_key(generate_pk(:id))
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def generate_pk(name)
|
92
|
+
"secure_#{name}"
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
CreateUsers.up
|
98
|
+
# => NoMethodError: undefined method `generate_pk' for #<TableFactory:0x00007f8560ca4a58>
|
99
|
+
```
|
100
|
+
|
101
|
+
Symbiont solves this:
|
102
|
+
|
103
|
+
```ruby
|
104
|
+
require 'symbiont'
|
105
|
+
|
106
|
+
class Migration
|
107
|
+
class << self
|
108
|
+
def create_table(&block)
|
109
|
+
TableFactory.new.tap do |table|
|
110
|
+
Symbiont::Executor.evaluate(table, &block) # NOTE: intercept closure invokation by Symbiont
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
CreateUsers.up
|
117
|
+
# => #<TableFactory:0x00007f990527f268 @primary_key="secure_id">
|
118
|
+
```
|
119
|
+
|
120
|
+
---
|
121
|
+
|
122
|
+
Proc-object is executed in three contexts at the same time:
|
123
|
+
|
124
|
+
- in the context of closure;
|
125
|
+
- in the context of required object;
|
126
|
+
- in the global context (Kernel).
|
127
|
+
|
128
|
+
Methods (called internally) are delegated to the context that is first able to respond.
|
129
|
+
The order of context selection depends on the corresponding context direction parameter.
|
130
|
+
By default the delegation order is: object context => closure context => global context.
|
131
|
+
If no context is able to respond to the method, an exception is thrown (`Symbiont::Trigger::ContextNoMethodError`).
|
132
|
+
Symbiont can consider the visiblity of methods when executing.
|
133
|
+
|
134
|
+
|
135
|
+
# Usage
|
136
|
+
|
137
|
+
## Context management
|
138
|
+
|
139
|
+
Imagine that in a real application we have the following gode and the corresponding closure:
|
140
|
+
|
141
|
+
```ruby
|
142
|
+
def object_data
|
143
|
+
'outer_context'
|
144
|
+
end
|
145
|
+
|
146
|
+
class SimpleObject
|
147
|
+
def format_data(data)
|
148
|
+
"Data: #{data}"
|
149
|
+
end
|
150
|
+
|
151
|
+
def object_data
|
152
|
+
'inner_context'
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
class << Kernel
|
157
|
+
def object_data
|
158
|
+
'kernel_data'
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
object = SimpleObject.new
|
163
|
+
|
164
|
+
closure = proc { format_data(object_data) } # NOTE: our closure
|
165
|
+
```
|
166
|
+
|
167
|
+
How a proc object will be processed, which context will be selected, how to make sure that nothing is broken - welcome to Symbiont.
|
168
|
+
|
169
|
+
## Supported methods delegation directions
|
170
|
+
|
171
|
+
Delegation order is set by a constant and passed as a parameter in the execution of the proc
|
172
|
+
and the generation of a special mixin module, allowing any class or instance to become a symbiont.
|
173
|
+
|
174
|
+
Supported contexts
|
175
|
+
|
176
|
+
- inner context - an object where proc is executed;
|
177
|
+
- outer context - external environment of the proc object;
|
178
|
+
- kernel context - global Kernel context.
|
179
|
+
|
180
|
+
Symbiont::IOK is chosen by default (`inner context => outer context => kernel context`)
|
181
|
+
|
182
|
+
```ruby
|
183
|
+
Symbiont::IOK # Inner Context => Outer Context => Kernel Context (DEFAULT)
|
184
|
+
Symbiont::OIK # Outer Context => Inner Context => Kernel Context
|
185
|
+
Symbiont::OKI # Outer Context => Kernel Context => Inner Context
|
186
|
+
Symbiont::IKO # Inner Context => Kernel Context => Outer Context
|
187
|
+
Symbiont::KOI # Kernel Context => Outer Context => Inner Context
|
188
|
+
Symbiont::KIO # Kernel Context => Inner Context => Outer Context
|
189
|
+
```
|
190
|
+
|
191
|
+
## Proc object invokation
|
192
|
+
|
193
|
+
`Symbiont::Executor` allows you to execute proc objects in two modes of the delegation:
|
194
|
+
|
195
|
+
- only public methods:
|
196
|
+
- `evaluate(required_context, [context_direction], &closure)`
|
197
|
+
- public and private methods:
|
198
|
+
- `evaluate_private(required_context, [context_direction], &closure)`
|
199
|
+
|
200
|
+
If no context is able to respond to the required method - `Symbiont::Trigger::ContextNoMethodError` exception is thrown.
|
201
|
+
|
202
|
+
In the case when an unsupported direction value is used - `Symbiont::Trigger::IncompatibleContextDirectionError` exception is thrown.
|
203
|
+
|
204
|
+
If proc object isnt passed to the executor - `Symbiont::Trigger::IncompatibleclosureObjectError` exception is thrown.
|
205
|
+
|
206
|
+
#### Considering public methods only (.evaluate)
|
207
|
+
|
208
|
+
```ruby
|
209
|
+
# with default delegation order (Symbiont::IOK)
|
210
|
+
Symbiont::Executor.evaluate(object) do
|
211
|
+
format_data(object_data)
|
212
|
+
end
|
213
|
+
# => "Data: inner_context"
|
214
|
+
|
215
|
+
# with a custom delegation order
|
216
|
+
Symbiont::Executor.evaluate(object, Symbiont::KIO) do
|
217
|
+
format_data(object_data)
|
218
|
+
end
|
219
|
+
# => "Data: kernel_context"
|
220
|
+
|
221
|
+
# SimpleObject#object_data is a private method (inner_context)
|
222
|
+
Symbiont::Executor.evaluate(object, Symbiont::IOK) do
|
223
|
+
format_data(object_data)
|
224
|
+
end
|
225
|
+
# => "Data: outer_context"
|
226
|
+
```
|
227
|
+
|
228
|
+
#### Considering private and public methods (.evaluate_private)
|
229
|
+
|
230
|
+
```ruby
|
231
|
+
# with default delegation order (Symbiont::IOK)
|
232
|
+
Symbiont::Executor.evaluate_private(object) do
|
233
|
+
format_data(object_data)
|
234
|
+
end
|
235
|
+
# => "Data: inner_context"
|
236
|
+
|
237
|
+
# with a custom delegation order
|
238
|
+
Symbiont::Executor.evaluate_private(object, Symbiont::KIO) do
|
239
|
+
format_data(object_data)
|
240
|
+
end
|
241
|
+
# => "Data: kernel_context"
|
242
|
+
|
243
|
+
# SimpleObject#object_data is a private method (inner_context)
|
244
|
+
Symbiont::Executor.evaluate_private(object, Symbiont::IOK) do
|
245
|
+
format_data(object_data)
|
246
|
+
end
|
247
|
+
# => "Data: inner_data"
|
248
|
+
```
|
249
|
+
|
250
|
+
## Getting method-objects (Method)
|
251
|
+
|
252
|
+
`Symbiont::Executor` provides the possibility of obtaining the method object with consideration of the chosen delegation order:
|
253
|
+
|
254
|
+
- only public methods:
|
255
|
+
- `public_method(method_name, required_context, [context_direction], &clojure)`
|
256
|
+
- public and private methods:
|
257
|
+
- `private_method(method_name, required_context, [context_direction], &clojure)`
|
258
|
+
|
259
|
+
If no context is able to respond to the required method - `Symbiont::Trigger::ContextNoMethodError` exception is thrown.
|
260
|
+
|
261
|
+
In the case when an unsupported direction value is used - `Symbiont::Trigger::IncompatibleContextDirectionError` exception is thrown.
|
262
|
+
|
263
|
+
#### Considering public methods only (.public_method)
|
264
|
+
|
265
|
+
```ruby
|
266
|
+
# with default delegation order (Symbiont::IOK)
|
267
|
+
Symbiont::Executor.public_method(:object_data, object, &closure)
|
268
|
+
# => #<Method: SimpleObject#object_data>
|
269
|
+
|
270
|
+
# with a custom delegation order
|
271
|
+
Symbiont::Executor.public_method(:object_data, object, Symbiont::OIK, &closure)
|
272
|
+
# => (main) #<Method: SimpleObject(object)#object_data>
|
273
|
+
|
274
|
+
# SimpleObject#object_data is a private method
|
275
|
+
Symbiont::Executor.public_method(:object_data, object, Symbiont::IOK, &closure)
|
276
|
+
# => (main) #<Method: SimpleObject(object)#object_data>
|
277
|
+
```
|
278
|
+
|
279
|
+
#### Considering public and private methods (.private_method)
|
280
|
+
|
281
|
+
```ruby
|
282
|
+
# with default delegation order (Symbiont::IOK)
|
283
|
+
Symbiont::Executor.private_method(:object_data, object, &clojure)
|
284
|
+
# => #<Method: SimpleObject#object_data>
|
285
|
+
|
286
|
+
# with a custom delegation order
|
287
|
+
Symbiont::Executor.private_method(:object_data, object, Symbiont::KIO, &clojure)
|
288
|
+
# => #<Method: Kernel.object_data>
|
289
|
+
|
290
|
+
# SimpleObject#object_data is a private_method
|
291
|
+
Symbiont::Executor.private_method(:object_data, object, Symbiotn::IKO, &clojure)
|
292
|
+
# => #<Method: SimpleObject#object_data>
|
293
|
+
```
|
294
|
+
|
295
|
+
## Symbiont Mixin
|
296
|
+
|
297
|
+
'Symbiont:: Context' is a mixin that allows any object to call proc objects in the context of itself as Symbiont::Executor
|
298
|
+
|
299
|
+
You can specify the default direction of the context delegation. `Symbiont::IOK` is used by default.
|
300
|
+
|
301
|
+
#### Mixing a module with default delegation direction
|
22
302
|
|
23
|
-
|
303
|
+
```ruby
|
304
|
+
class SimpleObject
|
305
|
+
include Symbiont::Context # Symbiont::IOK direction is used by default
|
306
|
+
|
307
|
+
# #evaluate([context_direction = Symbiont::IOK], &closure)
|
308
|
+
# #evaluate_private([context_direction = Symbiont::IOK], &closure)
|
309
|
+
# #public_method(method_name, [context_direction = Symbiont::IOK])
|
310
|
+
# #private_method(method_name, [context_direction = Symbiont::IOK])
|
24
311
|
|
25
|
-
|
312
|
+
extend Symbiont::Context # Symbiont::IOK direction is used by default
|
26
313
|
|
27
|
-
|
314
|
+
# .evaluate([context_direction = Symbiont::IOK], &closure)
|
315
|
+
# .evaluate_private([context_direction = Symbiont::IOK], &closure)
|
316
|
+
# .public_method(method_name, [context_direction = Symbiont::IOK])
|
317
|
+
# .private_method(method_name, [context_direction = Symbiont::IOK])
|
318
|
+
end
|
28
319
|
|
29
|
-
|
320
|
+
def object_data
|
321
|
+
'outer_context'
|
322
|
+
end
|
30
323
|
|
31
|
-
|
324
|
+
SimpleObject.new.evaluate { object_data }
|
325
|
+
# => object.object_data => "inner_context"
|
326
|
+
|
327
|
+
SimpleObject.new.evaluate(Symbiont::OIK) { object_data }
|
328
|
+
# => object_data() => "outer_context"
|
329
|
+
```
|
330
|
+
|
331
|
+
#### Mixing a module with certain delegation direction
|
332
|
+
|
333
|
+
```ruby
|
334
|
+
class SimpleObject
|
335
|
+
include Symbiont::Context(Symboiont::KOI) # use a custom direction
|
336
|
+
|
337
|
+
# #evaluate([context_direction = Symbiont::KOI], &closure)
|
338
|
+
# #evaluate_private([context_direction = Symbiont::KOI], &closure)
|
339
|
+
# #public_method(method_name, [context_direction = Symbiont::KOI])
|
340
|
+
# #private_method(method_name, [context_direction = Symbiont::KOI])
|
341
|
+
|
342
|
+
extend Symbiont::Context(Symbiont::KOI) # use a custom direction
|
343
|
+
|
344
|
+
# .evaluate([context_direction = Symbiont::KOI], &closure)
|
345
|
+
# .evaluate_private([context_direction = Symbiont::KOI], &closure)
|
346
|
+
# .public_method(method_name, [context_direction = Symbiont::KOI])
|
347
|
+
# .private_method(method_name, [context_direction = Symbiont::KOI])
|
348
|
+
end
|
349
|
+
|
350
|
+
SimpleObject.new.evaluate { object_data }
|
351
|
+
# => Kernel.object_data => "kernel_context"
|
352
|
+
|
353
|
+
SimpleObject.new.evaluate(Symbiont::IOK) { object_data }
|
354
|
+
# => object.object_data => "inner_context"
|
355
|
+
```
|
32
356
|
|
33
|
-
|
357
|
+
# Contributing
|
34
358
|
|
35
|
-
|
359
|
+
- Fork it ( https://github.com/0exp/symbiont-ruby/fork )
|
360
|
+
- Create your feature branch (`git checkout -b my-new-feature`)
|
361
|
+
- Commit your changes (`git commit -am 'Add some feature'`)
|
362
|
+
- Push to the branch (`git push origin my-new-feature`)
|
363
|
+
- Create new Pull Request
|
36
364
|
|
37
|
-
|
365
|
+
# License
|
38
366
|
|
39
|
-
|
367
|
+
Released under MIT License.
|
40
368
|
|
41
|
-
|
369
|
+
# About
|
42
370
|
|
43
|
-
|
371
|
+
Created by Rustam Ibragimov.
|
data/Rakefile
CHANGED
data/bin/console
CHANGED
@@ -1,14 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'symbiont/ruby'
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
-
# require "pry"
|
11
|
-
# Pry.start
|
12
|
-
|
13
|
-
require "irb"
|
14
|
-
IRB.start(__FILE__)
|
6
|
+
require 'pry'
|
7
|
+
Pry.start
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Symbiont
|
4
|
+
class << self
|
5
|
+
# Factory method for a mixin module that provides an ability to invoke procs and lambdas
|
6
|
+
# in many contexts to any object. Mixes up special methods that delegate execution logic to
|
7
|
+
# to a special mediator object (Symbiont::Executor).
|
8
|
+
#
|
9
|
+
# @param default_context_direction [Array<Symbol>] Delegation order.
|
10
|
+
# @return [Module]
|
11
|
+
#
|
12
|
+
# @see Symbiont::Executor
|
13
|
+
# @see Symbiont::Trigger
|
14
|
+
# @see Symbiont::PublicTrigger
|
15
|
+
# @see Symbiont::PrivateTrigger
|
16
|
+
#
|
17
|
+
# @api public
|
18
|
+
# @since 0.1.0
|
19
|
+
#
|
20
|
+
# rubocop:disable Naming/MethodName, Metrics/LineLength
|
21
|
+
def Context(default_context_direction = Trigger::IOK)
|
22
|
+
Module.new do
|
23
|
+
define_method :evaluate do |context_direction = default_context_direction, &closure|
|
24
|
+
Executor.evaluate(self, context_direction, &closure)
|
25
|
+
end
|
26
|
+
|
27
|
+
define_method :evaluate_private do |context_direction = default_context_direction, &closure|
|
28
|
+
Executor.evaluate_private(self, context_direction, &closure)
|
29
|
+
end
|
30
|
+
|
31
|
+
define_method :public_method do |method_name, context_direction = default_context_direction, &closure|
|
32
|
+
Executor.public_method(self, method_name, context_direction, &closure)
|
33
|
+
end
|
34
|
+
|
35
|
+
define_method :private_method do |method_name, context_direction = default_context_direction, &closure|
|
36
|
+
Executor.private_method(self, method_name, context_direction, &closure)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
# rubocop:enable Naming/MethodName, Metrics/LineLength
|
41
|
+
end
|
42
|
+
|
43
|
+
# @see Symbiont.Context
|
44
|
+
#
|
45
|
+
# @api public
|
46
|
+
# @since 0.1.0
|
47
|
+
Context = Context()
|
48
|
+
end
|