interactor_support 1.0.4 → 1.0.5

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4d6d8c9f46a3e48520652cdb83a9257d487a3411feef0b1efd69c1fc4a209c03
4
- data.tar.gz: 31b939d573a1dc042b671304ec777bf4a8bf53ad61bd3b4d63fccc3fd4dd2806
3
+ metadata.gz: 315dd265352ed997c5b69934609478e6e5f8b61bbe74bba065acf495f7dac41c
4
+ data.tar.gz: 6a942d0ccb3f3323d156d85f302987b4af7809cdcce852dca56fb9b1ae8419bc
5
5
  SHA512:
6
- metadata.gz: 2cf4e789be122df812109df549d3d94a4cf685af0a85eb3fa3d47e811fc73d2231a4fd5af95a2e3c397505102c363bb831df716f16fe701fa0e2fd33e586e757
7
- data.tar.gz: 8d6e5ee59b6c0523d0d7a9931d6b0ee4f1f98c7aa7d87aabfd45f8dcad8b9f7831444030803abc98bf0594b87a9e084cc9285e8f7382dd378f0d68f4fdc79823
6
+ metadata.gz: 2fb25732876e4702b12da283cf4d205504c597ecb904cc9406af3a9825814e8ba518e84bcc615c1c8aadc31ed81cfb9008e2addf759273c2688e029d5b07628e
7
+ data.tar.gz: 5615bf986b8ab272cff775eebbd874c336be93f4e17333d37fd6e87a04b9d74d110b2fcab2a48fb1e0ff86956785b4a7825d03f4201701700566825c2335c633
data/CHANGELOG.md CHANGED
@@ -21,3 +21,11 @@
21
21
  ## [1.0.4] - 2025-04-05
22
22
 
23
23
  - Added the organizable concern
24
+
25
+ ## [1.0.5] - 2025-06-30
26
+
27
+ - Add support for ignoring unknown attributes in RequestObjects via `ignore_unknown_attributes` class method
28
+ - Introduce `InteractorSupport.configuration.log_unknown_request_object_attributes` to optionally log ignored attributes
29
+ - Introduce `InteractorSupport.configuration.logger` and `log_level` for customizable logging
30
+ - Override `assign_attributes` to integrate attribute ignoring and error-raising behavior
31
+ - Improve test coverage for unknown attribute handling and logging
data/README.md CHANGED
@@ -148,6 +148,7 @@ Instead of raw hashes, **Request Objects** provide **validation, transformation,
148
148
  - Works just like an **ActiveRecord model**
149
149
  - Supports **validations** out of the box
150
150
  - Automatically **transforms & sanitizes** data
151
+ - Gracefully ignores unknown attributes if configured, with optional logging
151
152
 
152
153
  ```ruby
153
154
  class TodoRequest
@@ -162,6 +163,31 @@ class TodoRequest
162
163
  end
163
164
  ```
164
165
 
166
+ ### 🔍 Ignoring Unknown Attributes
167
+
168
+ To prevent `RequestObject` from raising an error on unexpected keys, declare `ignore_unknown_attributes` in your class.
169
+
170
+ ```ruby
171
+ class CalendarRequest
172
+ include InteractorSupport::RequestObject
173
+
174
+ ignore_unknown_attributes
175
+
176
+ attribute :start_date, type: :date
177
+ attribute :end_date, type: :date
178
+ attribute :timezone, transform: :strip
179
+
180
+ validates :start_date, :end_date, presence: true
181
+ end
182
+ ```
183
+
184
+ Now, if you initialize the request with an unexpected attribute, it will be logged (if logging is enabled) and ignored:
185
+
186
+ ```ruby
187
+ CalendarRequest.new(start_date: "2025-07-01", end_date: "2025-07-02", foo: "bar")
188
+ # => No exception raised; 'foo' is ignored.
189
+ ```
190
+
165
191
  ---
166
192
 
167
193
  ## 📖 **Documentation**
@@ -652,6 +678,34 @@ class ApplicationController < ActionController::Base
652
678
  end
653
679
  ```
654
680
 
681
+ ---
682
+
683
+ ## 🛠 Configuration Reference
684
+
685
+ All global settings for InteractorSupport can be set via the `InteractorSupport.configure` block. Here's a full list of configuration options:
686
+
687
+ <!-- prettier-ignore-start -->
688
+ | Key | Type | Default | Description |
689
+ | --- | ---- | ------- | -----------|
690
+ | `logger` | `Logger` | `Logger.new($stdout)` | Logger instance used for internal logging. |
691
+ | `log_level` | `Integer` (Logger constant) | `Logger::INFO` | Logging level (e.g., `Logger::DEBUG`, `Logger::WARN`, etc.). |
692
+ | `log_unknown_request_object_attributes` | `Boolean` | `true` | Whether to log unknown request attributes that are ignored. |
693
+ | `request_object_behavior` | `Symbol` | `:returns_context` | Controls what `RequestObject.new(...)` returns (`:returns_self` or `:returns_context`). |
694
+ | `request_object_key_type` | `Symbol` | `:symbol` | Controls the output format of keys in `#to_context` (`:symbol`, `:string`, `:struct`). |
695
+ <!-- prettier-ignore-end -->
696
+
697
+ To update these settings, use:
698
+
699
+ ```ruby
700
+ InteractorSupport.configure do |config|
701
+ config.logger = Rails.logger
702
+ config.log_level = Logger::WARN
703
+ config.log_unknown_request_object_attributes = true
704
+ config.request_object_behavior = :returns_self
705
+ config.request_object_key_type = :struct
706
+ end
707
+ ```
708
+
655
709
  ## 🤝 **Contributing**
656
710
 
657
711
  Pull requests are welcome on [GitHub](https://github.com/charliemitchell/interactor_support).
@@ -29,13 +29,35 @@ module InteractorSupport
29
29
  # @return [:string, :symbol, :struct]
30
30
  attr_accessor :request_object_key_type
31
31
 
32
+ ##
33
+ # Logger for InteractorSupport, defaults to STDOUT.
34
+ # @return [Logger]
35
+ attr_accessor :logger
36
+
37
+ ##
38
+ # The log level for InteractorSupport logs.
39
+ # @return [Integer]
40
+ attr_accessor :log_level
41
+
42
+ ##
43
+ # Whether to log unknown request object attributes when they are ignored.
44
+ # If true, logs a warning when an unknown attribute is encountered.
45
+ # @see InteractorSupport::RequestObject#ignore_unknown_attributes
46
+ attr_accessor :log_unknown_request_object_attributes
47
+
32
48
  ##
33
49
  # Initializes the configuration with default values:
34
50
  # - `request_object_behavior` defaults to `:returns_context`
35
51
  # - `request_object_key_type` defaults to `:symbol`
52
+ # - `logger` defaults to a new Logger instance writing to STDOUT
53
+ # - `log_level` defaults to `Logger::INFO`
54
+ # - `log_unknown_request_object_attributes` defaults to `true`
36
55
  def initialize
37
56
  @request_object_behavior = :returns_context
38
57
  @request_object_key_type = :symbol
58
+ @logger = Logger.new($stdout)
59
+ @log_level = Logger::INFO
60
+ @log_unknown_request_object_attributes = true
39
61
  end
40
62
  end
41
63
  end
@@ -0,0 +1,9 @@
1
+ module InteractorSupport
2
+ module Errors
3
+ class UnknownAttribute < StandardError
4
+ def initialize(attribute)
5
+ super("Unknown attribute: #{attribute}")
6
+ end
7
+ end
8
+ end
9
+ end
@@ -40,6 +40,7 @@ module InteractorSupport
40
40
  included do
41
41
  include ActiveModel::Model
42
42
  include ActiveModel::Attributes
43
+ include ActiveModel::AttributeAssignment
43
44
  include ActiveModel::Validations::Callbacks
44
45
 
45
46
  ##
@@ -88,6 +89,32 @@ module InteractorSupport
88
89
  attrs
89
90
  end
90
91
 
92
+ ##
93
+ # Assigns the given attributes to the request object.
94
+ #
95
+ # - Known attributes are assigned normally via their setters.
96
+ # - If `ignore_unknown_attributes?` is defined and true, unknown keys are ignored and logged.
97
+ # - Otherwise, raises `Errors::UnknownAttribute`.
98
+ #
99
+ # @param attrs [Hash] input attributes to assign
100
+ # @raise [Errors::UnknownAttribute] if unknown attribute is encountered and not ignored
101
+ # @return [void]
102
+ def assign_attributes(attrs)
103
+ attrs.each do |k, v|
104
+ setter = "#{k}="
105
+ if respond_to?(setter)
106
+ send(setter, v)
107
+ elsif respond_to?(:ignore_unknown_attributes?) && ignore_unknown_attributes?
108
+ InteractorSupport.configuration.logger.log(
109
+ InteractorSupport.configuration.log_level,
110
+ "InteractorSupport::RequestObject ignoring unknown attribute '#{k}' for #{self.class.name}.",
111
+ )
112
+ else
113
+ raise Errors::UnknownAttribute, "`#{k}` for #{self.class.name}."
114
+ end
115
+ end
116
+ end
117
+
91
118
  class << self
92
119
  ##
93
120
  # Custom constructor that optionally returns the context instead of the object itself.
@@ -103,6 +130,19 @@ module InteractorSupport
103
130
  super(*args, **kwargs).to_context
104
131
  end
105
132
 
133
+ ##
134
+ # Defines whether to ignore unknown attributes during assignment.
135
+ # If true, unknown attributes are logged but not raised as errors.
136
+ # @example
137
+ # class MyRequest
138
+ # include InteractorSupport::RequestObject
139
+ # ignore_unknown_attributes
140
+ # end
141
+ # @return [void]
142
+ def ignore_unknown_attributes
143
+ define_method(:ignore_unknown_attributes?) { true }
144
+ end
145
+
106
146
  ##
107
147
  # Defines one or more attributes with optional coercion, default values, transformation,
108
148
  # and an optional `rewrite:` key to rename the underlying attribute.
File without changes
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module InteractorSupport
4
- VERSION = '1.0.4'
4
+ VERSION = '1.0.5'
5
5
  end
@@ -3,6 +3,7 @@
3
3
  require 'interactor'
4
4
  require 'logger'
5
5
  require 'active_support/concern'
6
+ require 'interactor_support/errors'
6
7
  require_relative 'interactor_support/core'
7
8
  require_relative 'interactor_support/version'
8
9
  require_relative 'interactor_support/actions'
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
4
+ version: 1.0.5
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-04-05 00:00:00.000000000 Z
11
+ date: 2025-07-01 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
14
  email:
@@ -37,7 +37,9 @@ files:
37
37
  - lib/interactor_support/concerns/updatable.rb
38
38
  - lib/interactor_support/configuration.rb
39
39
  - lib/interactor_support/core.rb
40
+ - lib/interactor_support/errors.rb
40
41
  - lib/interactor_support/request_object.rb
42
+ - lib/interactor_support/response_object.rb
41
43
  - lib/interactor_support/rubocop.rb
42
44
  - lib/interactor_support/rubocop/cop/base_interactor_cop.rb
43
45
  - lib/interactor_support/rubocop/cop/require_required_for_interactor_support.rb