cmdx 1.13.0 → 1.14.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.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +84 -76
  3. data/LICENSE.txt +3 -20
  4. data/README.md +8 -7
  5. data/lib/cmdx/attribute.rb +21 -5
  6. data/lib/cmdx/context.rb +16 -0
  7. data/lib/cmdx/executor.rb +9 -9
  8. data/lib/cmdx/result.rb +27 -7
  9. data/lib/cmdx/task.rb +19 -0
  10. data/lib/cmdx/version.rb +1 -1
  11. data/mkdocs.yml +62 -36
  12. metadata +3 -57
  13. data/.cursor/prompts/docs.md +0 -12
  14. data/.cursor/prompts/llms.md +0 -8
  15. data/.cursor/prompts/rspec.md +0 -24
  16. data/.cursor/prompts/yardoc.md +0 -15
  17. data/.cursor/rules/cursor-instructions.mdc +0 -68
  18. data/.irbrc +0 -18
  19. data/.rspec +0 -4
  20. data/.rubocop.yml +0 -95
  21. data/.ruby-version +0 -1
  22. data/.yard-lint.yml +0 -174
  23. data/.yardopts +0 -7
  24. data/docs/.DS_Store +0 -0
  25. data/docs/assets/favicon.ico +0 -0
  26. data/docs/assets/favicon.svg +0 -1
  27. data/docs/attributes/coercions.md +0 -155
  28. data/docs/attributes/defaults.md +0 -77
  29. data/docs/attributes/definitions.md +0 -283
  30. data/docs/attributes/naming.md +0 -68
  31. data/docs/attributes/transformations.md +0 -63
  32. data/docs/attributes/validations.md +0 -336
  33. data/docs/basics/chain.md +0 -108
  34. data/docs/basics/context.md +0 -121
  35. data/docs/basics/execution.md +0 -152
  36. data/docs/basics/setup.md +0 -107
  37. data/docs/callbacks.md +0 -157
  38. data/docs/configuration.md +0 -314
  39. data/docs/deprecation.md +0 -143
  40. data/docs/getting_started.md +0 -137
  41. data/docs/index.md +0 -134
  42. data/docs/internationalization.md +0 -126
  43. data/docs/interruptions/exceptions.md +0 -52
  44. data/docs/interruptions/faults.md +0 -169
  45. data/docs/interruptions/halt.md +0 -216
  46. data/docs/logging.md +0 -90
  47. data/docs/middlewares.md +0 -191
  48. data/docs/outcomes/result.md +0 -197
  49. data/docs/outcomes/states.md +0 -66
  50. data/docs/outcomes/statuses.md +0 -65
  51. data/docs/retries.md +0 -121
  52. data/docs/stylesheets/extra.css +0 -42
  53. data/docs/tips_and_tricks.md +0 -157
  54. data/docs/workflows.md +0 -226
  55. data/examples/active_record_database_transaction.md +0 -27
  56. data/examples/active_record_query_tagging.md +0 -46
  57. data/examples/flipper_feature_flags.md +0 -50
  58. data/examples/paper_trail_whatdunnit.md +0 -39
  59. data/examples/redis_idempotency.md +0 -71
  60. data/examples/sentry_error_tracking.md +0 -46
  61. data/examples/sidekiq_async_execution.md +0 -29
  62. data/examples/stoplight_circuit_breaker.md +0 -36
  63. data/src/cmdx-dark-logo.png +0 -0
  64. data/src/cmdx-favicon.svg +0 -1
  65. data/src/cmdx-light-logo.png +0 -0
  66. data/src/cmdx-logo.svg +0 -1
data/docs/basics/setup.md DELETED
@@ -1,107 +0,0 @@
1
- # Basics - Setup
2
-
3
- Tasks are the heart of CMDx—self-contained units of business logic with built-in validation, error handling, and execution tracking.
4
-
5
- ## Structure
6
-
7
- Tasks need only two things: inherit from `CMDx::Task` and define a `work` method:
8
-
9
- ```ruby
10
- class ValidateDocument < CMDx::Task
11
- def work
12
- # Your logic here...
13
- end
14
- end
15
- ```
16
-
17
- Without a `work` method, execution raises `CMDx::UndefinedMethodError`.
18
-
19
- ```ruby
20
- class IncompleteTask < CMDx::Task
21
- # No `work` method defined
22
- end
23
-
24
- IncompleteTask.execute #=> raises CMDx::UndefinedMethodError
25
- ```
26
-
27
- ## Rollback
28
-
29
- Undo any operations linked to the given status, helping to restore a pristine state.
30
-
31
- ```ruby
32
- class ChargeCard < CMDx::Task
33
- def work
34
- # Your logic here, ex: charge $100
35
- end
36
-
37
- # Called automatically if a later step in the workflow fails
38
- def rollback
39
- # Your undo logic, ex: void $100 charge
40
- end
41
- end
42
- ```
43
-
44
- ## Inheritance
45
-
46
- Share configuration across tasks using inheritance:
47
-
48
- ```ruby
49
- class ApplicationTask < CMDx::Task
50
- register :middleware, SecurityMiddleware
51
-
52
- before_execution :initialize_request_tracking
53
-
54
- attribute :session_id
55
-
56
- private
57
-
58
- def initialize_request_tracking
59
- context.tracking_id ||= SecureRandom.uuid
60
- end
61
- end
62
-
63
- class SyncInventory < ApplicationTask
64
- def work
65
- # Your logic here...
66
- end
67
- end
68
- ```
69
-
70
- ## Lifecycle
71
-
72
- Tasks follow a predictable execution pattern:
73
-
74
- ```mermaid
75
- stateDiagram-v2
76
- Initialized: Instantiation
77
- Initialized --> Validating: execute
78
- Validating --> Executing: Valid?
79
- Validating --> Failed: Invalid
80
- Executing --> Success: Work done
81
- Executing --> Skipped: skip!
82
- Executing --> Failed: fail! / Exception
83
- Executed
84
-
85
- state Executed {
86
- Success
87
- Skipped
88
- Failed
89
- Rollback
90
-
91
- Skipped --> Rollback
92
- Failed --> Rollback
93
- }
94
- ```
95
-
96
- !!! danger "Caution"
97
-
98
- Tasks are single-use objects. Once executed, they're frozen and immutable.
99
-
100
- | Stage | State | Status | Description |
101
- |-------|-------|--------|-------------|
102
- | **Instantiation** | `initialized` | `success` | Task created with context |
103
- | **Validation** | `executing` | `success`/`failed` | Attributes validated |
104
- | **Execution** | `executing` | `success`/`failed`/`skipped` | `work` method runs |
105
- | **Completion** | `executed` | `success`/`failed`/`skipped` | Result finalized |
106
- | **Freezing** | `executed` | `success`/`failed`/`skipped` | Task becomes immutable |
107
- | **Rollback** | `executed` | `failed`/`skipped` | Work undone |
data/docs/callbacks.md DELETED
@@ -1,157 +0,0 @@
1
- # Callbacks
2
-
3
- Run custom logic at specific points during task execution. Callbacks have full access to task context and results, making them perfect for logging, notifications, cleanup, and more.
4
-
5
- See [Global Configuration](getting_started.md#callbacks) for framework-wide callback setup.
6
-
7
- !!! warning "Important"
8
-
9
- Callbacks execute in declaration order (FIFO). Multiple callbacks of the same type run sequentially.
10
-
11
- ## Available Callbacks
12
-
13
- Callbacks execute in a predictable lifecycle order:
14
-
15
- ```ruby
16
- 1. before_validation # Pre-validation setup
17
- 2. before_execution # Prepare for execution
18
-
19
- # --- Task#work executes ---
20
-
21
- 3. on_[complete|interrupted] # State-based (execution lifecycle)
22
- 4. on_executed # Always runs after work completes
23
- 5. on_[success|skipped|failed] # Status-based (business outcome)
24
- 6. on_[good|bad] # Outcome-based (success/skip vs fail)
25
- ```
26
-
27
- ## Declarations
28
-
29
- ### Symbol References
30
-
31
- Reference instance methods by symbol for simple callback logic:
32
-
33
- ```ruby
34
- class ProcessBooking < CMDx::Task
35
- before_execution :find_reservation
36
-
37
- # Batch declarations (works for any type)
38
- on_complete :notify_guest, :update_availability
39
-
40
- def work
41
- # Your logic here...
42
- end
43
-
44
- private
45
-
46
- def find_reservation
47
- @reservation ||= Reservation.find(context.reservation_id)
48
- end
49
-
50
- def notify_guest
51
- GuestNotifier.call(context.guest, result)
52
- end
53
-
54
- def update_availability
55
- AvailabilityService.update(context.room_ids, result)
56
- end
57
- end
58
- ```
59
-
60
- ### Proc or Lambda
61
-
62
- Use anonymous functions for inline callback logic:
63
-
64
- ```ruby
65
- class ProcessBooking < CMDx::Task
66
- # Proc
67
- on_interrupted proc { ReservationSystem.pause! }
68
-
69
- # Lambda
70
- on_complete -> { ReservationSystem.resume! }
71
- end
72
- ```
73
-
74
- ### Class or Module
75
-
76
- Implement reusable callback logic in dedicated modules and classes:
77
-
78
- ```ruby
79
- class BookingConfirmationCallback
80
- def call(task)
81
- if task.result.success?
82
- MessagingApi.send_confirmation(task.context.guest)
83
- else
84
- MessagingApi.send_issue_alert(task.context.manager)
85
- end
86
- end
87
- end
88
-
89
- class ProcessBooking < CMDx::Task
90
- # Class or Module
91
- on_success BookingConfirmationCallback
92
-
93
- # Instance
94
- on_interrupted BookingConfirmationCallback.new
95
- end
96
- ```
97
-
98
- ### Conditional Execution
99
-
100
- Control callback execution with conditional logic:
101
-
102
- ```ruby
103
- class MessagingPermissionCheck
104
- def call(task)
105
- task.context.guest.can?(:receive_messages)
106
- end
107
- end
108
-
109
- class ProcessBooking < CMDx::Task
110
- # If and/or Unless
111
- before_execution :notify_guest, if: :messaging_enabled?, unless: :messaging_blocked?
112
-
113
- # Proc
114
- on_failure :increment_failure, if: -> { Rails.env.production? && self.class.name.include?("Legacy") }
115
-
116
- # Lambda
117
- on_success :ping_housekeeping, if: proc { context.rooms_need_cleaning? }
118
-
119
- # Class or Module
120
- on_complete :send_confirmation, unless: MessagingPermissionCheck
121
-
122
- # Instance
123
- on_complete :send_confirmation, if: MessagingPermissionCheck.new
124
-
125
- def work
126
- # Your logic here...
127
- end
128
-
129
- private
130
-
131
- def messaging_enabled?
132
- context.guest.messaging_preference == true
133
- end
134
-
135
- def messaging_blocked?
136
- context.guest.communication_status == :blocked
137
- end
138
- end
139
- ```
140
-
141
- ## Callback Removal
142
-
143
- Remove unwanted callbacks dynamically:
144
-
145
- !!! warning "Important"
146
-
147
- Each `deregister` call removes one callback. Use multiple calls for batch removals.
148
-
149
- ```ruby
150
- class ProcessBooking < CMDx::Task
151
- # Symbol
152
- deregister :callback, :before_execution, :notify_guest
153
-
154
- # Class or Module (no instances)
155
- deregister :callback, :on_complete, BookingConfirmationCallback
156
- end
157
- ```
@@ -1,314 +0,0 @@
1
- # Configuration
2
-
3
- Configure CMDx to customize framework behavior, register components, and control execution flow through global defaults with task-level overrides.
4
-
5
- ## Configuration Hierarchy
6
-
7
- CMDx uses a straightforward two-tier configuration system:
8
-
9
- 1. **Global Configuration** — Framework-wide defaults
10
- 2. **Task Settings** — Class-level overrides using `settings`
11
-
12
- !!! warning "Important"
13
-
14
- Task settings take precedence over global config. Settings are inherited from parent classes and can be overridden in subclasses.
15
-
16
- ## Global Configuration
17
-
18
- Configure framework-wide defaults that apply to all tasks. These settings come with sensible defaults out of the box.
19
-
20
- ### Breakpoints
21
-
22
- Control when `execute!` raises a `CMDx::Fault` based on task status.
23
-
24
- ```ruby
25
- CMDx.configure do |config|
26
- config.task_breakpoints = "failed" # String or Array[String]
27
- end
28
- ```
29
-
30
- For workflows, configure which statuses halt the execution pipeline:
31
-
32
- ```ruby
33
- CMDx.configure do |config|
34
- config.workflow_breakpoints = ["skipped", "failed"]
35
- end
36
- ```
37
-
38
- ### Rollback
39
-
40
- Control when a `rollback` of task execution is called.
41
-
42
- ```ruby
43
- CMDx.configure do |config|
44
- config.rollback_on = ["failed"] # String or Array[String]
45
- end
46
- ```
47
-
48
- ### Backtraces
49
-
50
- Enable detailed backtraces for non-fault exceptions to improve debugging. Optionally clean up stack traces to remove framework noise.
51
-
52
- !!! note
53
-
54
- In Rails environments, `backtrace_cleaner` defaults to `Rails.backtrace_cleaner.clean`.
55
-
56
- ```ruby
57
- CMDx.configure do |config|
58
- # Truthy
59
- config.backtrace = true
60
-
61
- # Via callable (must respond to `call(backtrace)`)
62
- config.backtrace_cleaner = AdvanceCleaner.new
63
-
64
- # Via proc or lambda
65
- config.backtrace_cleaner = ->(backtrace) { backtrace[0..5] }
66
- end
67
- ```
68
-
69
- ### Exception Handlers
70
-
71
- Register handlers that run when non-fault exceptions occur.
72
-
73
- !!! tip
74
-
75
- Use exception handlers to send errors to your APM of choice.
76
-
77
- ```ruby
78
- CMDx.configure do |config|
79
- # Via callable (must respond to `call(task, exception)`)
80
- config.exception_handler = NewRelicReporter
81
-
82
- # Via proc or lambda
83
- config.exception_handler = proc do |task, exception|
84
- APMService.report(exception, extra_data: { task: task.name, id: task.id })
85
- end
86
- end
87
- ```
88
-
89
- ### Logging
90
-
91
- ```ruby
92
- CMDx.configure do |config|
93
- config.logger = CustomLogger.new($stdout)
94
- end
95
- ```
96
-
97
- ### Middlewares
98
-
99
- See the [Middlewares](middlewares.md#declarations) docs for task level configurations.
100
-
101
- ```ruby
102
- CMDx.configure do |config|
103
- # Via callable (must respond to `call(task, options)`)
104
- config.middlewares.register CMDx::Middlewares::Timeout
105
-
106
- # Via proc or lambda
107
- config.middlewares.register proc { |task, options|
108
- start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
109
- result = yield
110
- end_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
111
- Rails.logger.debug { "task completed in #{((end_time - start_time) * 1000).round(2)}ms" }
112
- result
113
- }
114
-
115
- # With options
116
- config.middlewares.register AuditTrailMiddleware, service_name: "document_processor"
117
-
118
- # Remove middleware
119
- config.middlewares.deregister CMDx::Middlewares::Timeout
120
- end
121
- ```
122
-
123
- !!! note
124
-
125
- Middlewares are executed in registration order. Each middleware wraps the next, creating an execution chain around task logic.
126
-
127
- ### Callbacks
128
-
129
- See the [Callbacks](callbacks.md#declarations) docs for task level configurations.
130
-
131
- ```ruby
132
- CMDx.configure do |config|
133
- # Via method
134
- config.callbacks.register :before_execution, :initialize_user_session
135
-
136
- # Via callable (must respond to `call(task)`)
137
- config.callbacks.register :on_success, LogUserActivity
138
-
139
- # Via proc or lambda
140
- config.callbacks.register :on_complete, proc { |task|
141
- execution_time = task.metadata[:runtime]
142
- Metrics.timer("task.execution_time", execution_time, tags: ["task:#{task.class.name.underscore}"])
143
- }
144
-
145
- # With options
146
- config.callbacks.register :on_failure, :send_alert_notification, if: :critical_task?
147
-
148
- # Remove callback
149
- config.callbacks.deregister :on_success, LogUserActivity
150
- end
151
- ```
152
-
153
- ### Coercions
154
-
155
- See the [Attributes - Coercions](attributes/coercions.md#declarations) docs for task level configurations.
156
-
157
- ```ruby
158
- CMDx.configure do |config|
159
- # Via callable (must respond to `call(value, options)`)
160
- config.coercions.register :currency, CurrencyCoercion
161
-
162
- # Via method (must match signature `def coordinates_coercion(value, options)`)
163
- config.coercions.register :coordinates, :coordinates_coercion
164
-
165
- # Via proc or lambda
166
- config.coercions.register :tag_list, proc { |value, options|
167
- delimiter = options[:delimiter] || ','
168
- max_tags = options[:max_tags] || 50
169
-
170
- tags = value.to_s.split(delimiter).map(&:strip).reject(&:empty?)
171
- tags.first(max_tags)
172
- }
173
-
174
- # Remove coercion
175
- config.coercions.deregister :currency
176
- end
177
- ```
178
-
179
- ### Validators
180
-
181
- See the [Attributes - Validations](attributes/validations.md#declarations) docs for task level configurations.
182
-
183
- ```ruby
184
- CMDx.configure do |config|
185
- # Via callable (must respond to `call(value, options)`)
186
- config.validators.register :username, UsernameValidator
187
-
188
- # Via method (must match signature `def url_validator(value, options)`)
189
- config.validators.register :url, :url_validator
190
-
191
- # Via proc or lambda
192
- config.validators.register :access_token, proc { |value, options|
193
- expected_prefix = options[:prefix] || "tok_"
194
- minimum_length = options[:min_length] || 40
195
-
196
- value.start_with?(expected_prefix) && value.length >= minimum_length
197
- }
198
-
199
- # Remove validator
200
- config.validators.deregister :username
201
- end
202
- ```
203
-
204
- ## Task Configuration
205
-
206
- ### Settings
207
-
208
- Override global configuration for specific tasks using `settings`:
209
-
210
- ```ruby
211
- class GenerateInvoice < CMDx::Task
212
- settings(
213
- # Global configuration overrides
214
- task_breakpoints: ["failed"], # Breakpoint override
215
- workflow_breakpoints: [], # Breakpoint override
216
- backtrace: true, # Toggle backtrace
217
- backtrace_cleaner: ->(bt) { bt[0..5] }, # Backtrace cleaner
218
- logger: CustomLogger.new($stdout), # Custom logger
219
-
220
- # Task configuration settings
221
- breakpoints: ["failed"], # Contextual pointer for :task_breakpoints and :workflow_breakpoints
222
- log_level: :info, # Log level override
223
- log_formatter: CMDx::LogFormatters::Json.new # Log formatter override
224
- tags: ["billing", "financial"], # Logging tags
225
- deprecated: true, # Task deprecations
226
- retries: 3, # Non-fault exception retries
227
- retry_on: [External::ApiError], # List of exceptions to retry on
228
- retry_jitter: 1, # Space between retry iteration, eg: current retry num + 1
229
- rollback_on: ["failed", "skipped"], # Rollback on override
230
- )
231
-
232
- def work
233
- # Your logic here...
234
- end
235
- end
236
- ```
237
-
238
- !!! warning "Important"
239
-
240
- Retries reuse the same context. By default, all `StandardError` exceptions (including faults) are retried unless you specify `retry_on` option for specific matches.
241
-
242
- ### Registrations
243
-
244
- Register or deregister middlewares, callbacks, coercions, and validators for specific tasks:
245
-
246
- ```ruby
247
- class SendCampaignEmail < CMDx::Task
248
- # Middlewares
249
- register :middleware, CMDx::Middlewares::Timeout
250
- deregister :middleware, AuditTrailMiddleware
251
-
252
- # Callbacks
253
- register :callback, :on_complete, proc { |task|
254
- runtime = task.metadata[:runtime]
255
- Analytics.track("email_campaign.sent", runtime, tags: ["task:#{task.class.name}"])
256
- }
257
- deregister :callback, :before_execution, :initialize_user_session
258
-
259
- # Coercions
260
- register :coercion, :currency, CurrencyCoercion
261
- deregister :coercion, :coordinates
262
-
263
- # Validators
264
- register :validator, :username, :username_validator
265
- deregister :validator, :url
266
-
267
- def work
268
- # Your logic here...
269
- end
270
- end
271
- ```
272
-
273
- ## Configuration Management
274
-
275
- ### Access
276
-
277
- ```ruby
278
- # Global configuration access
279
- CMDx.configuration.logger #=> <Logger instance>
280
- CMDx.configuration.task_breakpoints #=> ["failed"]
281
- CMDx.configuration.middlewares.registry #=> [<Middleware>, ...]
282
-
283
- # Task configuration access
284
- class ProcessUpload < CMDx::Task
285
- settings(tags: ["files", "storage"])
286
-
287
- def work
288
- self.class.settings[:logger] #=> Global configuration value
289
- self.class.settings[:tags] #=> Task configuration value => ["files", "storage"]
290
- end
291
- end
292
- ```
293
-
294
- ### Resetting
295
-
296
- !!! warning
297
-
298
- Resetting affects your entire application. Use this primarily in test environments.
299
-
300
- ```ruby
301
- # Reset to framework defaults
302
- CMDx.reset_configuration!
303
-
304
- # Verify reset
305
- CMDx.configuration.task_breakpoints #=> ["failed"] (default)
306
- CMDx.configuration.middlewares.registry #=> Empty registry
307
-
308
- # Commonly used in test setup (RSpec example)
309
- RSpec.configure do |config|
310
- config.before(:each) do
311
- CMDx.reset_configuration!
312
- end
313
- end
314
- ```
data/docs/deprecation.md DELETED
@@ -1,143 +0,0 @@
1
- # Task Deprecation
2
-
3
- Manage legacy tasks gracefully with built-in deprecation support. Choose how to handle deprecated tasks—log warnings for awareness, issue Ruby warnings for development, or prevent execution entirely.
4
-
5
- ## Modes
6
-
7
- ### Raise
8
-
9
- Prevent task execution completely. Perfect for tasks that must no longer run.
10
-
11
- !!! warning
12
-
13
- Use `:raise` mode carefully—it will break existing workflows immediately.
14
-
15
- ```ruby
16
- class ProcessObsoleteAPI < CMDx::Task
17
- settings(deprecated: :raise)
18
-
19
- def work
20
- # Will never execute...
21
- end
22
- end
23
-
24
- result = ProcessObsoleteAPI.execute
25
- #=> raises CMDx::DeprecationError: "ProcessObsoleteAPI usage prohibited"
26
- ```
27
-
28
- ### Log
29
-
30
- Allow execution while tracking deprecation in logs. Ideal for gradual migrations.
31
-
32
- ```ruby
33
- class ProcessLegacyFormat < CMDx::Task
34
- settings(deprecated: :log)
35
- settings(deprecated: true)
36
-
37
- def work
38
- # Executes but logs deprecation warning...
39
- end
40
- end
41
-
42
- result = ProcessLegacyFormat.execute
43
- result.successful? #=> true
44
-
45
- # Deprecation warning appears in logs:
46
- # WARN -- : DEPRECATED: ProcessLegacyFormat - migrate to replacement or discontinue use
47
- ```
48
-
49
- ### Warn
50
-
51
- Issue Ruby warnings visible during development and testing. Keeps production logs clean while alerting developers.
52
-
53
- ```ruby
54
- class ProcessOldData < CMDx::Task
55
- settings(deprecated: :warn)
56
-
57
- def work
58
- # Executes but emits Ruby warning...
59
- end
60
- end
61
-
62
- result = ProcessOldData.execute
63
- result.successful? #=> true
64
-
65
- # Ruby warning appears in stderr:
66
- # [ProcessOldData] DEPRECATED: migrate to a replacement or discontinue use
67
- ```
68
-
69
- ## Declarations
70
-
71
- ### Symbol or String
72
-
73
- ```ruby
74
- class OutdatedConnector < CMDx::Task
75
- # Symbol
76
- settings(deprecated: :raise)
77
-
78
- # String
79
- settings(deprecated: "warn")
80
- end
81
- ```
82
-
83
- ### Boolean or Nil
84
-
85
- ```ruby
86
- class OutdatedConnector < CMDx::Task
87
- # Deprecates with default :log mode
88
- settings(deprecated: true)
89
-
90
- # Skips deprecation
91
- settings(deprecated: false)
92
- settings(deprecated: nil)
93
- end
94
- ```
95
-
96
- ### Method
97
-
98
- ```ruby
99
- class OutdatedConnector < CMDx::Task
100
- # Symbol
101
- settings(deprecated: :deprecated?)
102
-
103
- def work
104
- # Your logic here...
105
- end
106
-
107
- private
108
-
109
- def deprecated?
110
- Time.now.year > 2024 ? :raise : false
111
- end
112
- end
113
- ```
114
-
115
- ### Proc or Lambda
116
-
117
- ```ruby
118
- class OutdatedConnector < CMDx::Task
119
- # Proc
120
- settings(deprecated: proc { Rails.env.development? ? :raise : :log })
121
-
122
- # Lambda
123
- settings(deprecated: -> { Current.tenant.legacy_mode? ? :warn : :raise })
124
- end
125
- ```
126
-
127
- ### Class or Module
128
-
129
- ```ruby
130
- class OutdatedTaskDeprecator
131
- def call(task)
132
- task.class.name.include?("Outdated")
133
- end
134
- end
135
-
136
- class OutdatedConnector < CMDx::Task
137
- # Class or Module
138
- settings(deprecated: OutdatedTaskDeprecator)
139
-
140
- # Instance
141
- settings(deprecated: OutdatedTaskDeprecator.new)
142
- end
143
- ```