wrapper_based 0.5.0 → 1.0.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/.travis.yml +3 -0
- data/README.md +19 -14
- data/examples/dijkstra/data.rb +1 -1
- data/examples/dijkstra.rb +8 -14
- data/examples/money_transfer.rb +35 -28
- data/examples/toy_shop.rb +0 -3
- data/lib/wrapper_based/context/builder.rb +20 -0
- data/lib/wrapper_based/{cast.rb → context/casting.rb} +1 -1
- data/lib/wrapper_based/context/casting_director.rb +20 -0
- data/lib/wrapper_based/context/type_casting.rb +27 -0
- data/lib/wrapper_based/context.rb +14 -10
- data/lib/wrapper_based/dci.rb +3 -20
- data/lib/wrapper_based/version.rb +1 -1
- data/lib/wrapper_based.rb +4 -16
- data/wrapper_based.gemspec +3 -1
- metadata +21 -5
- data/lib/wrapper_based/decorator.rb +0 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8250109a727470549a4a5ad7eeeb2b83deb22ded
|
4
|
+
data.tar.gz: aad939be5697e39f97d8adfcb2978ef723702516
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 71ec411aaa5a9ebaeab67749f5adcc66e1b2921cbb58e22ce3a49385e4d8173a8502f3582c6187af6a3829cfda489ff81eb734ce5d55e6b559409d287a80d72e
|
7
|
+
data.tar.gz: 183610fab65d79dee5b6c08f8f1bc849718fb1241478d9937bff0fe283d3ebd429fdbb1d493122bd2c52109703d6c1dd6152cb301a33b2f602be07b748beb8eb
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# WrapperBased
|
2
2
|
|
3
3
|
[](https://badge.fury.io/rb/wrapper_based)
|
4
|
+
[](https://travis-ci.org/RichOrElse/wrapper-based)
|
4
5
|
|
5
6
|
Wrapper Based DCI implementation in Ruby.
|
6
7
|
|
@@ -20,23 +21,21 @@ Or install it yourself as:
|
|
20
21
|
|
21
22
|
$ gem install wrapper_based
|
22
23
|
|
23
|
-
|
24
|
+
Require DCI in your gems or save in your rails app as app/config/dci.rb:
|
25
|
+
|
24
26
|
|
25
27
|
```ruby
|
26
|
-
|
27
|
-
|
28
|
+
require 'wrapper_based/dci'
|
29
|
+
```
|
28
30
|
|
29
|
-
|
31
|
+
## Usage
|
30
32
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
end
|
33
|
+
[Dijkstra data](https://github.com/RichOrElse/wrapper-based/blob/master/examples/dijkstra/data.rb) |
|
34
|
+
[Dijkstra test](https://github.com/RichOrElse/wrapper-based/blob/master/test/dijkstra_test.rb) |
|
35
|
+
Djikstra example:
|
35
36
|
|
36
|
-
|
37
|
-
|
38
|
-
end
|
39
|
-
end
|
37
|
+
```ruby
|
38
|
+
require_relative 'dijkstra/data'
|
40
39
|
|
41
40
|
module CurrentIntersection
|
42
41
|
def neighbors(manhattan:)
|
@@ -53,9 +52,15 @@ module DestinationNode
|
|
53
52
|
end
|
54
53
|
end
|
55
54
|
|
56
|
-
|
55
|
+
module Map
|
56
|
+
def distance_between(a, b)
|
57
|
+
@distances[Edge.new(a, b)]
|
58
|
+
end
|
57
59
|
|
58
|
-
|
60
|
+
def distance_of(path)
|
61
|
+
GetDistance[within: self].of(path)
|
62
|
+
end
|
63
|
+
end
|
59
64
|
|
60
65
|
class GetDistance < DCI::Context(:within)
|
61
66
|
within.as Map
|
data/examples/dijkstra/data.rb
CHANGED
data/examples/dijkstra.rb
CHANGED
@@ -1,18 +1,6 @@
|
|
1
1
|
require_relative 'dijkstra/data'
|
2
2
|
# See https://github.com/RichOrElse/wrapper-based/blob/master/test/dijkstra_test.rb
|
3
3
|
|
4
|
-
# Behaviors
|
5
|
-
|
6
|
-
module Map
|
7
|
-
def distance_between(a, b)
|
8
|
-
@distances[Edge.new(a, b)]
|
9
|
-
end
|
10
|
-
|
11
|
-
def distance_of(path)
|
12
|
-
GetDistance[within: self].of(path)
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
4
|
module CurrentIntersection
|
17
5
|
def neighbors(manhattan:)
|
18
6
|
east_neighbor = manhattan.east_neighbor_of(self)
|
@@ -28,9 +16,15 @@ module DestinationNode
|
|
28
16
|
end
|
29
17
|
end
|
30
18
|
|
31
|
-
|
19
|
+
module Map
|
20
|
+
def distance_between(a, b)
|
21
|
+
@distances[Edge.new(a, b)]
|
22
|
+
end
|
32
23
|
|
33
|
-
|
24
|
+
def distance_of(path)
|
25
|
+
GetDistance[within: self].of(path)
|
26
|
+
end
|
27
|
+
end
|
34
28
|
|
35
29
|
class GetDistance < DCI::Context(:within)
|
36
30
|
within.as Map
|
data/examples/money_transfer.rb
CHANGED
@@ -1,41 +1,48 @@
|
|
1
1
|
LogTransaction = Struct.new(:transaction_type, :amount, :account_number)
|
2
|
-
Account = Struct.new(:number, :balance)
|
3
|
-
NotEnoughFunds = Class.new(StandardError)
|
4
2
|
|
5
|
-
module
|
6
|
-
|
7
|
-
|
8
|
-
|
3
|
+
module Funds
|
4
|
+
Insufficient = Class.new(StandardError)
|
5
|
+
|
6
|
+
module SourceAccount
|
7
|
+
def decrease_balance_by(amount)
|
8
|
+
fail Funds::Insufficient, "Balance is below amount.", caller if balance < amount
|
9
|
+
self.balance -= amount
|
10
|
+
end
|
9
11
|
end
|
10
|
-
end
|
11
12
|
|
12
|
-
module DestinationAccount
|
13
|
-
|
14
|
-
|
13
|
+
module DestinationAccount
|
14
|
+
def increase_balance_by(amount)
|
15
|
+
self.balance += amount
|
16
|
+
end
|
15
17
|
end
|
16
|
-
end
|
17
18
|
|
18
|
-
|
19
|
+
class TransferMoney < DCI::Context(:from, :to)
|
20
|
+
from.as SourceAccount
|
21
|
+
to.as DestinationAccount
|
19
22
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
+
def withdraw(amount)
|
24
|
+
from.decrease_balance_by(amount)
|
25
|
+
LogTransaction["Withdraw", amount, from.number]
|
26
|
+
end
|
23
27
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
+
def deposit(amount)
|
29
|
+
to.increase_balance_by(amount)
|
30
|
+
LogTransaction["Deposit", amount, to.number]
|
31
|
+
end
|
32
|
+
|
33
|
+
def accounts
|
34
|
+
[@from, @to]
|
35
|
+
end
|
28
36
|
|
29
|
-
|
30
|
-
|
31
|
-
|
37
|
+
def call(amount:)
|
38
|
+
transaction_logs = [withdraw(amount), deposit(amount)]
|
39
|
+
[:success, { logs: transaction_logs }, accounts]
|
40
|
+
rescue Funds::Insufficient => error
|
41
|
+
[:failure, { message: error.message }, accounts]
|
42
|
+
end
|
32
43
|
end
|
33
44
|
|
34
|
-
def
|
35
|
-
|
36
|
-
transaction_logs = [withdraw(amount), deposit(amount)]
|
37
|
-
[:success, { logs: transaction_logs }, accounts]
|
38
|
-
rescue NotEnoughFunds => error
|
39
|
-
[:failure, { message: error.message }, accounts]
|
45
|
+
def self.transfer(**where)
|
46
|
+
TransferMoney[**where]
|
40
47
|
end
|
41
48
|
end
|
data/examples/toy_shop.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
require_relative '../lib/wrapper_based'
|
2
|
-
|
3
1
|
# Data
|
4
2
|
|
5
3
|
Purchase = Struct.new(:toy, :buyer)
|
@@ -20,7 +18,6 @@ module Recipient
|
|
20
18
|
end
|
21
19
|
|
22
20
|
# Contexts
|
23
|
-
DCI = WrapperBased::DCI.new unless defined? DCI
|
24
21
|
|
25
22
|
class PurchaseToy < DCI::Context(:purchaser)
|
26
23
|
purchaser.as Buyer
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module WrapperBased
|
2
|
+
class Context::Builder < Module
|
3
|
+
def initialize(wrapper_for)
|
4
|
+
class_variable_set :@@wrapper_for,
|
5
|
+
Hash.new { |cache, type_casting| cache[type_casting] = wrapper_for[*type_casting] }
|
6
|
+
end
|
7
|
+
|
8
|
+
def wrapper_for(*type_casting)
|
9
|
+
class_variable_get(:@@wrapper_for)[type_casting]
|
10
|
+
end
|
11
|
+
|
12
|
+
def Context(*roles, &block)
|
13
|
+
dci = self
|
14
|
+
Class.new(WrapperBased::Context) do
|
15
|
+
roles.each { |role| add_role role, dci }
|
16
|
+
class_eval(&block) unless block.nil?
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end # Context::Builder class
|
20
|
+
end # WrapperBased module
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
3
|
+
module WrapperBased
|
4
|
+
class Context::CastingDirector
|
5
|
+
extend Forwardable
|
6
|
+
using Context::TypeCasting
|
7
|
+
|
8
|
+
def initialize(context_class)
|
9
|
+
@casts = {}
|
10
|
+
@re = context_class
|
11
|
+
end
|
12
|
+
|
13
|
+
def cast_as(role, actor)
|
14
|
+
@casts[role] = @casts[role].as_role_played_by(actor) { recast_as(role, actor) }
|
15
|
+
end
|
16
|
+
|
17
|
+
def_delegator :@re, :cast_as, :recast_as
|
18
|
+
def_delegators :@casts, :fetch, :[]
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'delegate'
|
2
|
+
|
3
|
+
module WrapperBased
|
4
|
+
module Context::TypeCasting
|
5
|
+
refine NilClass do
|
6
|
+
def as_role_played_by(actor)
|
7
|
+
yield
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
refine Delegator do
|
12
|
+
def as_role_played_by(actor)
|
13
|
+
return replace_role_player_with(actor) if role_type_same_as?(actor)
|
14
|
+
yield
|
15
|
+
end
|
16
|
+
|
17
|
+
def replace_role_player_with(actor)
|
18
|
+
__setobj__(actor)
|
19
|
+
self
|
20
|
+
end
|
21
|
+
|
22
|
+
def role_type_same_as?(actor)
|
23
|
+
actor.instance_of?(__getobj__.class)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module WrapperBased
|
2
2
|
class Context
|
3
3
|
def initialize(**where)
|
4
|
-
@
|
4
|
+
@casting_director = CastingDirector.new(self.class)
|
5
5
|
where.each { |role, player| send :"#{role}=", player }
|
6
6
|
end
|
7
7
|
|
@@ -18,17 +18,21 @@ module WrapperBased
|
|
18
18
|
class << self
|
19
19
|
alias_method :[], :new
|
20
20
|
|
21
|
+
def cast_as(role, actor)
|
22
|
+
send(role).typecast(actor)
|
23
|
+
end
|
24
|
+
|
21
25
|
protected
|
22
26
|
|
23
|
-
def add_role(role,
|
27
|
+
def add_role(role, dci)
|
24
28
|
add_reader_for(role)
|
25
29
|
add_writer_for(role)
|
26
|
-
|
30
|
+
add_to_class_cast_for role, Casting.new(role, dci)
|
27
31
|
end
|
28
32
|
|
29
33
|
def add_reader_for(role)
|
30
34
|
define_method(role) do
|
31
|
-
@
|
35
|
+
@casting_director.fetch(role) { raise UnassignedRole, "Role '#{role}' is missing.", caller }
|
32
36
|
end
|
33
37
|
end
|
34
38
|
|
@@ -37,19 +41,19 @@ module WrapperBased
|
|
37
41
|
|
38
42
|
define_method(:"#{role}=") do |actor|
|
39
43
|
instance_variable_set(role_player, actor)
|
40
|
-
@
|
44
|
+
@casting_director.cast_as role, actor
|
41
45
|
end
|
42
46
|
end
|
43
47
|
|
44
|
-
def
|
45
|
-
|
48
|
+
def add_to_class_cast_for(role, casting)
|
49
|
+
role_casting = :"@@#{role}"
|
46
50
|
|
47
51
|
singleton_class.class_eval do
|
48
|
-
define_method(role) { class_variable_get
|
52
|
+
define_method(role) { class_variable_get role_casting }
|
49
53
|
end
|
50
54
|
|
51
|
-
class_variable_set
|
55
|
+
class_variable_set role_casting, casting
|
52
56
|
end
|
53
|
-
end #
|
57
|
+
end # class methods
|
54
58
|
end # Context class
|
55
59
|
end # WrapperBased module
|
data/lib/wrapper_based/dci.rb
CHANGED
@@ -1,21 +1,4 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
def initialize(wrapper_for = FORWARDING)
|
4
|
-
@@wrapper_for = Hash.new do |cache, type_casting|
|
5
|
-
cache[type_casting] = wrapper_for[*type_casting]
|
6
|
-
end unless defined? @@wrapper_for
|
1
|
+
require "wrapper_based"
|
2
|
+
require "type_wrapper"
|
7
3
|
|
8
|
-
|
9
|
-
@@wrapper_for[type_casting]
|
10
|
-
end unless defined? self.wrapper_for
|
11
|
-
|
12
|
-
def Context(*roles, &block)
|
13
|
-
dci = self
|
14
|
-
Class.new(WrapperBased::Context) do
|
15
|
-
roles.each { |role| add_role role, WrapperBased::Cast.new(role, dci) }
|
16
|
-
class_eval(&block) unless block.nil?
|
17
|
-
end
|
18
|
-
end unless defined? self.Context
|
19
|
-
end # initialize method
|
20
|
-
end # DCI class
|
21
|
-
end # WrapperBased module
|
4
|
+
DCI = WrapperBased::Context::Builder.new(TypeWrapper)
|
data/lib/wrapper_based.rb
CHANGED
@@ -1,21 +1,9 @@
|
|
1
1
|
require "wrapper_based/version"
|
2
|
-
require "wrapper_based/cast"
|
3
2
|
require "wrapper_based/context"
|
4
|
-
require "wrapper_based/
|
5
|
-
require "wrapper_based/
|
3
|
+
require "wrapper_based/context/builder"
|
4
|
+
require "wrapper_based/context/casting"
|
5
|
+
require "wrapper_based/context/type_casting"
|
6
|
+
require "wrapper_based/context/casting_director"
|
6
7
|
|
7
8
|
module WrapperBased
|
8
|
-
FORWARDING = -> type, *behaviors do
|
9
|
-
Class.new(Decorator) do
|
10
|
-
using Module.new { refine(type) { prepend(*behaviors.reverse) } }
|
11
|
-
|
12
|
-
forwarding = behaviors.flat_map(&:public_instance_methods) - public_instance_methods
|
13
|
-
|
14
|
-
forwarding.uniq.each do |meth|
|
15
|
-
define_method(meth) do |*args, &block|
|
16
|
-
__getobj__.send(meth, *args, &block)
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
9
|
end
|
data/wrapper_based.gemspec
CHANGED
@@ -19,7 +19,9 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.bindir = "exe"
|
20
20
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
21
21
|
spec.require_paths = ["lib"]
|
22
|
-
spec.required_ruby_version = ">= 2.
|
22
|
+
spec.required_ruby_version = ">= 2.1.0"
|
23
|
+
|
24
|
+
spec.add_runtime_dependency "type_wrapper", "~> 1.0"
|
23
25
|
|
24
26
|
spec.add_development_dependency "bundler", "~> 1.15"
|
25
27
|
spec.add_development_dependency "rake", "~> 10.0"
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: wrapper_based
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ritchie Paul Buitre
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-07-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: type_wrapper
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.0'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: bundler
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -73,10 +87,12 @@ files:
|
|
73
87
|
- examples/money_transfer.rb
|
74
88
|
- examples/toy_shop.rb
|
75
89
|
- lib/wrapper_based.rb
|
76
|
-
- lib/wrapper_based/cast.rb
|
77
90
|
- lib/wrapper_based/context.rb
|
91
|
+
- lib/wrapper_based/context/builder.rb
|
92
|
+
- lib/wrapper_based/context/casting.rb
|
93
|
+
- lib/wrapper_based/context/casting_director.rb
|
94
|
+
- lib/wrapper_based/context/type_casting.rb
|
78
95
|
- lib/wrapper_based/dci.rb
|
79
|
-
- lib/wrapper_based/decorator.rb
|
80
96
|
- lib/wrapper_based/version.rb
|
81
97
|
- wrapper_based.gemspec
|
82
98
|
homepage: https://github.com/RichOrElse/wrapper-based/
|
@@ -91,7 +107,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
91
107
|
requirements:
|
92
108
|
- - ">="
|
93
109
|
- !ruby/object:Gem::Version
|
94
|
-
version: 2.
|
110
|
+
version: 2.1.0
|
95
111
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
96
112
|
requirements:
|
97
113
|
- - ">="
|
@@ -1,13 +0,0 @@
|
|
1
|
-
require 'delegate'
|
2
|
-
|
3
|
-
module WrapperBased
|
4
|
-
class Decorator < Delegator
|
5
|
-
alias_method :initialize, def __setobj__(obj)
|
6
|
-
@delegate_sd_obj = obj # change delegation object
|
7
|
-
end
|
8
|
-
|
9
|
-
alias_method :~@, def __getobj__
|
10
|
-
@delegate_sd_obj # return object we are delegating to
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|