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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 68e9909166c5283d9505f7be6f541334aea5d161
4
- data.tar.gz: 2319fcbbb2da7b56aff3825e44788d44da99a688
3
+ metadata.gz: c9950cb0ec4cecfed71f7cae1cd777a0693ed8b5
4
+ data.tar.gz: a77cc845e72319b08e222e3ab7c820f87359e6a2
5
5
  SHA512:
6
- metadata.gz: cd3f037341b4f6f2e28d9e4478d763fc6bd554d09e5be20be2ac08c2fad405be3a2ce8e45a273cdd0c6bbbf26efd8ee0abaf4edb6d48e4760c933ebaf54d1397
7
- data.tar.gz: cea7c3a4b77dbc7cc4215e38b853c92d96670fe8677c771a2d1914b6e60293d163fc00d9bd3a60b97966849e5a7f025cb3b39c0b30afb933c62e25dfdafb4497
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
- - Implementation for classes responding to **`to_a`** is handled properly
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) # DUPLICATE DEF
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(&Proc.new)
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
- BlackTie.protocols[self].keys.include? method
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
- def defimpl(protocol = nil, target: nil, delegate: [], map: {})
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(&Proc.new) if block_given? # block takes precedence
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
- (BlackTie.protocols[protocol].keys - meths).each_with_object(meths) do |m, acc|
94
- BlackTie.Logger.warn("Implicit delegate #{protocol.inspect}##{m} to #{target}")
95
- DELEGATE_METHOD.(mod.singleton_class, [m] * 2)
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|
@@ -1,5 +1,5 @@
1
1
  module Dry
2
2
  module Behaviour
3
- VERSION = '0.7.0'.freeze
3
+ VERSION = '0.8.0'.freeze
4
4
  end
5
5
  end
@@ -0,0 +1,9 @@
1
+ module Dry
2
+ module Protocol
3
+ class DuplicateDefinition < StandardError
4
+ def initialize(suspect)
5
+ super "Duplicate definition of “#{suspect.inspect}” detected."
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Dry
2
+ module Protocol
3
+ class MalformedDefinition < StandardError
4
+ def initialize(suspect)
5
+ super "Malformed definition of “#{suspect.inspect}”. Block required."
6
+ end
7
+ end
8
+ end
9
+ end
@@ -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.\n" \
17
- " ⮩ caused by “#{cause.class}” with a message\n" \
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
- " ⮩ rescue this exception and inspect `NotImplemented#cause' for details."
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
@@ -1,4 +1,7 @@
1
1
  require 'dry/errors/not_implemented'
2
2
  require 'dry/errors/not_protocol'
3
+ require 'dry/errors/duplicate_definition'
4
+ require 'dry/errors/malformed_definition'
5
+
3
6
  require 'dry/errors/not_guardable'
4
7
  require 'dry/errors/not_matched'
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.7.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