dry-behaviour 0.7.0 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +33 -1
- data/lib/dry/behaviour/black_tie.rb +33 -10
- data/lib/dry/behaviour/version.rb +1 -1
- data/lib/dry/errors/duplicate_definition.rb +9 -0
- data/lib/dry/errors/malformed_definition.rb +9 -0
- data/lib/dry/errors/not_implemented.rb +4 -3
- data/lib/dry/errors.rb +3 -0
- metadata +3 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c9950cb0ec4cecfed71f7cae1cd777a0693ed8b5
|
4
|
+
data.tar.gz: a77cc845e72319b08e222e3ab7c820f87359e6a2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d7f410dc7fb586256831916469d2d7bdcd74361235a74c891ac90ea8609bc69e343d9585d211a8b91abd9f88b443a60509bb9418df4201917fc01e170815346a
|
7
|
+
data.tar.gz: f4d1c1116169906a8efc11ea289c45d150cd920a3dcc2cbbc2c0f73870f449b2f102478e3a5aa54d6fb5a8c9e1d87031532f57a147d322d9d41d6ba885be75cc
|
data/README.md
CHANGED
@@ -100,9 +100,41 @@ end
|
|
100
100
|
|
101
101
|
## Changelog
|
102
102
|
|
103
|
+
### `0.8.0` :: Implicit Inheritance
|
104
|
+
|
105
|
+
- deprecate implicit delegation to the target instance; error message saying “it’ll be removed in 1.0”
|
106
|
+
- `implicit_inheritance: true` flag in call to `defprotocol` makes the implementation implicitly inherit the behaviour declared in the core protocol module itself, without the necessity to explicitly call `super`:
|
107
|
+
|
108
|
+
```diff
|
109
|
+
module ParentOKImplicit
|
110
|
+
include Dry::Protocol
|
111
|
+
|
112
|
+
- defprotocol do
|
113
|
+
+ defprotocol implicit_inheritance: true do
|
114
|
+
defmethod :foo
|
115
|
+
|
116
|
+
def foo(this)
|
117
|
+
:ok
|
118
|
+
end
|
119
|
+
|
120
|
+
defimpl target: String do
|
121
|
+
- def foo(this)
|
122
|
+
- super(this)
|
123
|
+
- end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
```
|
128
|
+
|
129
|
+
### `0.7.0` :: Handling Errors
|
130
|
+
|
131
|
+
- better error messages (very descriptive, with whys and howtos)
|
132
|
+
- the whole stacktrace is carefully saved with `cause`
|
133
|
+
- internal exceptions related to wrong implementation do now point to the proper lines in the client code (internal trace lines are removed)
|
134
|
+
|
103
135
|
### `0.6.0` :: Bugfix
|
104
136
|
|
105
|
-
-
|
137
|
+
- implementation for classes responding to **`to_a`** is handled properly
|
106
138
|
|
107
139
|
### `0.5.0` :: Guards
|
108
140
|
|
@@ -15,12 +15,14 @@ module Dry
|
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
|
-
def defprotocol
|
19
|
-
raise if BlackTie.protocols.key?(self)
|
20
|
-
raise unless block_given?
|
18
|
+
def defprotocol(implicit_inheritance: false, &λ)
|
19
|
+
raise ::Dry::Protocol::DuplicateDefinition.new(self) if BlackTie.protocols.key?(self)
|
20
|
+
raise ::Dry::Protocol::MalformedDefinition.new(self) unless block_given?
|
21
|
+
|
22
|
+
BlackTie.protocols[self][:__implicit_inheritance__] = !!implicit_inheritance
|
21
23
|
|
22
24
|
ims = instance_methods(false)
|
23
|
-
class_eval(
|
25
|
+
class_eval(&λ)
|
24
26
|
(instance_methods(false) - ims).each { |m| class_eval { module_function m } }
|
25
27
|
|
26
28
|
singleton_class.send :define_method, :method_missing do |method, *_args|
|
@@ -55,7 +57,7 @@ module Dry
|
|
55
57
|
end
|
56
58
|
|
57
59
|
singleton_class.send :define_method, :respond_to? do |method|
|
58
|
-
|
60
|
+
NORMALIZE_KEYS.(self).include? method
|
59
61
|
end
|
60
62
|
end
|
61
63
|
|
@@ -78,21 +80,42 @@ module Dry
|
|
78
80
|
end.enable
|
79
81
|
end
|
80
82
|
|
81
|
-
|
83
|
+
NORMALIZE_KEYS = lambda do |protocol|
|
84
|
+
BlackTie.protocols[protocol].keys.reject { |k| k.to_s =~ /\A__.*__\z/ }
|
85
|
+
end
|
86
|
+
|
87
|
+
IMPLICIT_DELEGATE_DEPRECATION =
|
88
|
+
"\n⚠️ DEPRECATED → Implicit delegation to the target class will be removed in 1.0\n" \
|
89
|
+
" ⮩ due to the lack of the explicit implementation of %s#%s for %s\n" \
|
90
|
+
" ⮩ it will be delegated to the target class itself.\n" \
|
91
|
+
" ⮩ Consider using explicit `delegate:' declaration in `defimpl' or\n" \
|
92
|
+
" ⮩ use `implicit_inheritance: true' parameter in protocol definition.".freeze
|
93
|
+
|
94
|
+
def defimpl(protocol = nil, target: nil, delegate: [], map: {}, &λ)
|
82
95
|
raise if target.nil? || !block_given? && delegate.empty? && map.empty?
|
83
96
|
|
84
97
|
mds = normalize_map_delegates(delegate, map)
|
85
98
|
|
86
99
|
Module.new do
|
87
100
|
mds.each(&DELEGATE_METHOD.curry[singleton_class])
|
88
|
-
singleton_class.class_eval(
|
101
|
+
singleton_class.class_eval(&λ) if block_given? # block takes precedence
|
89
102
|
end.tap do |mod|
|
90
103
|
protocol ? mod.extend(protocol) : POSTPONE_EXTEND.(mod, protocol = self)
|
91
104
|
|
92
105
|
mod.methods(false).tap do |meths|
|
93
|
-
(
|
94
|
-
BlackTie.
|
95
|
-
|
106
|
+
(NORMALIZE_KEYS.(protocol) - meths).each_with_object(meths) do |m, acc|
|
107
|
+
if BlackTie.protocols[protocol][:__implicit_inheritance__]
|
108
|
+
mod.singleton_class.class_eval do
|
109
|
+
define_method m do |*args, &λ|
|
110
|
+
super(*args, &λ)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
else
|
114
|
+
BlackTie.Logger.warn(
|
115
|
+
IMPLICIT_DELEGATE_DEPRECATION % [protocol.inspect, m, target]
|
116
|
+
)
|
117
|
+
DELEGATE_METHOD.(mod.singleton_class, [m] * 2)
|
118
|
+
end
|
96
119
|
acc << m
|
97
120
|
end
|
98
121
|
end.each do |m|
|
@@ -13,10 +13,11 @@ module Dry
|
|
13
13
|
when :method
|
14
14
|
"Protocol “#{@proto}” does not declare method “#{@details[:method]}”."
|
15
15
|
when :nested
|
16
|
-
"Protocol “#{@proto}” failed to invoke the implementation
|
17
|
-
" ⮩
|
16
|
+
"Protocol “#{@proto}” failed to invoke the implementation for\n" \
|
17
|
+
" ⮩ “#{@details[:receiver].class}##{@details[:method]}”.\n" \
|
18
|
+
" ⮩ Caused by “#{cause.class}” with a message\n" \
|
18
19
|
" ⮩ “#{cause.message}”\n" \
|
19
|
-
" ⮩
|
20
|
+
" ⮩ Rescue this exception and inspect `NotImplemented#cause' for details."
|
20
21
|
else
|
21
22
|
"Protocol “#{proto}” is invalid."
|
22
23
|
end
|
data/lib/dry/errors.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dry-behaviour
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aleksei Matiushkin
|
@@ -124,6 +124,8 @@ files:
|
|
124
124
|
- lib/dry/behaviour/cerberus.rb
|
125
125
|
- lib/dry/behaviour/version.rb
|
126
126
|
- lib/dry/errors.rb
|
127
|
+
- lib/dry/errors/duplicate_definition.rb
|
128
|
+
- lib/dry/errors/malformed_definition.rb
|
127
129
|
- lib/dry/errors/not_guardable.rb
|
128
130
|
- lib/dry/errors/not_implemented.rb
|
129
131
|
- lib/dry/errors/not_matched.rb
|