dry-behaviour 0.7.0 → 0.8.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/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
|