interactor_support 1.0.5 → 1.0.6
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/CHANGELOG.md +6 -0
- data/README.md +13 -1
- data/lib/interactor_support/concerns/organizable.rb +15 -1
- data/lib/interactor_support/errors.rb +49 -2
- data/lib/interactor_support/request_object.rb +14 -6
- data/lib/interactor_support/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: bf8cda13999c9971a1499398e23135ef6e870af7581ffe7e9f173b9d7c4231ea
|
|
4
|
+
data.tar.gz: 48c401b5b42e80ccea3db170ecb1e8476861522804b800ad28651eebfa674222
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2adf5f317e6432571a24358e9e1ba453397fcfd5f6b83758930fd45bef652dfb01ead87aa68fcfec385151bd60646127a087968e332baa0193e5bb9f7ac14ff6
|
|
7
|
+
data.tar.gz: a6a670cacb4abd50812a82232dcbeb1e582eea72d3526b2659f4dccd827226c6e07c6b12f6c39b282eb276db482d02911cd4d0e125094f8c1d114fba5459c899
|
data/CHANGELOG.md
CHANGED
|
@@ -29,3 +29,9 @@
|
|
|
29
29
|
- Introduce `InteractorSupport.configuration.logger` and `log_level` for customizable logging
|
|
30
30
|
- Override `assign_attributes` to integrate attribute ignoring and error-raising behavior
|
|
31
31
|
- Improve test coverage for unknown attribute handling and logging
|
|
32
|
+
|
|
33
|
+
## [1.0.6] - 2025-09-24
|
|
34
|
+
|
|
35
|
+
- Wrap request object validation failures from `Organizable#organize` in `InteractorSupport::Errors::InvalidRequestObject` for consistent controller handling
|
|
36
|
+
- Honor `configuration.log_unknown_request_object_attributes` when logging ignored request object keys
|
|
37
|
+
- Improve request object error messaging for failed casts and unknown attributes
|
data/README.md
CHANGED
|
@@ -559,7 +559,7 @@ The Organizable concern provides utility methods to simplify working with intera
|
|
|
559
559
|
|
|
560
560
|
Features
|
|
561
561
|
|
|
562
|
-
- organize: Call interactors with request objects, optionally namespaced under a context_key.
|
|
562
|
+
- organize: Call interactors with request objects, optionally namespaced under a context_key, and wrap validation failures in a consistent error.
|
|
563
563
|
- request_params: Extract, shape, filter, rename, flatten, and merge incoming params in a clear and declarative way.
|
|
564
564
|
- Built for controllers or service entry points.
|
|
565
565
|
- Rails-native feel — works seamlessly with strong params.
|
|
@@ -588,6 +588,18 @@ organize(MyInteractor, params: request_params, request_object: MyRequest, contex
|
|
|
588
588
|
# => MyInteractor.call({ request: MyRequest.new(params) })
|
|
589
589
|
```
|
|
590
590
|
|
|
591
|
+
Validation failures inside the request object raise `InteractorSupport::Errors::InvalidRequestObject`. The exception exposes the request class and its validation messages, making it straightforward to surface errors back to the caller.
|
|
592
|
+
|
|
593
|
+
```rb
|
|
594
|
+
def create
|
|
595
|
+
organize(CreateUserInteractor, params: request_params(:user), request_object: CreateUserRequest)
|
|
596
|
+
redirect_to dashboard_path
|
|
597
|
+
rescue InteractorSupport::Errors::InvalidRequestObject => e
|
|
598
|
+
flash.now[:alert] = "Unable to continue: #{e.errors.to_sentence}"
|
|
599
|
+
render :new, status: :unprocessable_entity
|
|
600
|
+
end
|
|
601
|
+
```
|
|
602
|
+
|
|
591
603
|
#### #request_params(\*top_level_keys, merge: {}, except: [], rewrite: [])
|
|
592
604
|
|
|
593
605
|
Returns a shaped parameter hash derived from params.permit!. You can extract specific top-level keys, rename them, flatten values, apply defaults, and remove unwanted fields.
|
|
@@ -38,8 +38,22 @@ module InteractorSupport
|
|
|
38
38
|
# # => Calls MyInteractor with an instance of MyRequest initialized with request_params at :context_key.
|
|
39
39
|
# # # => The context will contain { request: MyRequest.new(request_params) }
|
|
40
40
|
def organize(interactor, params:, request_object:, context_key: nil)
|
|
41
|
+
request_payload = request_object.new(params)
|
|
42
|
+
|
|
41
43
|
@context = interactor.call(
|
|
42
|
-
context_key ? { context_key =>
|
|
44
|
+
context_key ? { context_key => request_payload } : request_payload,
|
|
45
|
+
)
|
|
46
|
+
rescue ActiveModel::ValidationError => e
|
|
47
|
+
errors =
|
|
48
|
+
if e.model&.respond_to?(:errors)
|
|
49
|
+
e.model.errors.full_messages
|
|
50
|
+
else
|
|
51
|
+
[]
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
raise InteractorSupport::Errors::InvalidRequestObject.new(
|
|
55
|
+
request_class: request_object,
|
|
56
|
+
errors: errors,
|
|
43
57
|
)
|
|
44
58
|
end
|
|
45
59
|
|
|
@@ -1,8 +1,55 @@
|
|
|
1
1
|
module InteractorSupport
|
|
2
2
|
module Errors
|
|
3
3
|
class UnknownAttribute < StandardError
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
attr_reader :attribute, :owner
|
|
5
|
+
|
|
6
|
+
def initialize(attribute, owner: nil)
|
|
7
|
+
@attribute = attribute
|
|
8
|
+
@owner = owner
|
|
9
|
+
super(build_message(attribute, owner))
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
private
|
|
13
|
+
|
|
14
|
+
def build_message(attribute, owner)
|
|
15
|
+
name =
|
|
16
|
+
case attribute
|
|
17
|
+
when String then attribute
|
|
18
|
+
when Symbol then attribute.to_s
|
|
19
|
+
else attribute.inspect
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
owner_name =
|
|
23
|
+
if owner.respond_to?(:name) && owner.name
|
|
24
|
+
owner.name
|
|
25
|
+
elsif owner.respond_to?(:to_s)
|
|
26
|
+
owner.to_s
|
|
27
|
+
else
|
|
28
|
+
owner
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
suffix = owner_name ? " for #{owner_name}" : ''
|
|
32
|
+
"Unknown attribute: #{name}#{suffix}"
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
class InvalidRequestObject < StandardError
|
|
37
|
+
attr_reader :request_class, :errors
|
|
38
|
+
|
|
39
|
+
def initialize(request_class:, errors: [])
|
|
40
|
+
@request_class = request_class
|
|
41
|
+
@errors = Array(errors)
|
|
42
|
+
|
|
43
|
+
request_name =
|
|
44
|
+
if request_class.respond_to?(:name) && request_class.name
|
|
45
|
+
request_class.name
|
|
46
|
+
else
|
|
47
|
+
request_class.to_s
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
detail = @errors.any? ? ": #{@errors.join(', ')}" : ''
|
|
51
|
+
|
|
52
|
+
super("Invalid #{request_name}#{detail}")
|
|
6
53
|
end
|
|
7
54
|
end
|
|
8
55
|
end
|
|
@@ -105,12 +105,14 @@ module InteractorSupport
|
|
|
105
105
|
if respond_to?(setter)
|
|
106
106
|
send(setter, v)
|
|
107
107
|
elsif respond_to?(:ignore_unknown_attributes?) && ignore_unknown_attributes?
|
|
108
|
-
InteractorSupport.configuration.
|
|
109
|
-
InteractorSupport.configuration.
|
|
110
|
-
|
|
111
|
-
|
|
108
|
+
if InteractorSupport.configuration.log_unknown_request_object_attributes
|
|
109
|
+
InteractorSupport.configuration.logger.log(
|
|
110
|
+
InteractorSupport.configuration.log_level,
|
|
111
|
+
"InteractorSupport::RequestObject ignoring unknown attribute '#{k}' for #{self.class.name}.",
|
|
112
|
+
)
|
|
113
|
+
end
|
|
112
114
|
else
|
|
113
|
-
raise Errors::UnknownAttribute,
|
|
115
|
+
raise Errors::UnknownAttribute.new(k, owner: self.class)
|
|
114
116
|
end
|
|
115
117
|
end
|
|
116
118
|
end
|
|
@@ -232,7 +234,13 @@ module InteractorSupport
|
|
|
232
234
|
message = ":#{type} is not a supported type. Supported types are: #{SUPPORTED_TYPES.join(", ")}"
|
|
233
235
|
raise TypeError, message
|
|
234
236
|
rescue
|
|
235
|
-
|
|
237
|
+
type_name =
|
|
238
|
+
if type.respond_to?(:name) && type.name
|
|
239
|
+
type.name
|
|
240
|
+
else
|
|
241
|
+
type.to_s
|
|
242
|
+
end
|
|
243
|
+
raise TypeError, "Cannot cast #{value.inspect} to #{type_name}"
|
|
236
244
|
end
|
|
237
245
|
end
|
|
238
246
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: interactor_support
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0.
|
|
4
|
+
version: 1.0.6
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Charlie Mitchell
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2025-
|
|
11
|
+
date: 2025-09-24 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description:
|
|
14
14
|
email:
|