cmdx 1.0.0 → 1.1.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 (169) hide show
  1. checksums.yaml +4 -4
  2. data/.cursor/prompts/rspec.md +20 -0
  3. data/.cursor/prompts/yardoc.md +8 -0
  4. data/.rubocop.yml +5 -0
  5. data/CHANGELOG.md +101 -49
  6. data/README.md +2 -1
  7. data/docs/ai_prompts.md +10 -0
  8. data/docs/basics/call.md +11 -2
  9. data/docs/basics/chain.md +10 -1
  10. data/docs/basics/context.md +9 -0
  11. data/docs/basics/setup.md +9 -0
  12. data/docs/callbacks.md +14 -37
  13. data/docs/configuration.md +68 -27
  14. data/docs/getting_started.md +11 -0
  15. data/docs/internationalization.md +148 -0
  16. data/docs/interruptions/exceptions.md +10 -1
  17. data/docs/interruptions/faults.md +11 -2
  18. data/docs/interruptions/halt.md +9 -0
  19. data/docs/logging.md +14 -4
  20. data/docs/middlewares.md +53 -43
  21. data/docs/outcomes/result.md +9 -0
  22. data/docs/outcomes/states.md +9 -0
  23. data/docs/outcomes/statuses.md +9 -0
  24. data/docs/parameters/coercions.md +58 -38
  25. data/docs/parameters/defaults.md +10 -1
  26. data/docs/parameters/definitions.md +9 -0
  27. data/docs/parameters/namespacing.md +9 -0
  28. data/docs/parameters/validations.md +8 -67
  29. data/docs/testing.md +22 -13
  30. data/docs/tips_and_tricks.md +9 -0
  31. data/docs/workflows.md +14 -4
  32. data/lib/cmdx/.DS_Store +0 -0
  33. data/lib/cmdx/callback.rb +36 -56
  34. data/lib/cmdx/callback_registry.rb +82 -73
  35. data/lib/cmdx/chain.rb +65 -122
  36. data/lib/cmdx/chain_inspector.rb +22 -115
  37. data/lib/cmdx/chain_serializer.rb +17 -148
  38. data/lib/cmdx/coercion.rb +49 -0
  39. data/lib/cmdx/coercion_registry.rb +94 -0
  40. data/lib/cmdx/coercions/array.rb +18 -36
  41. data/lib/cmdx/coercions/big_decimal.rb +21 -33
  42. data/lib/cmdx/coercions/boolean.rb +21 -40
  43. data/lib/cmdx/coercions/complex.rb +18 -31
  44. data/lib/cmdx/coercions/date.rb +20 -39
  45. data/lib/cmdx/coercions/date_time.rb +22 -39
  46. data/lib/cmdx/coercions/float.rb +19 -32
  47. data/lib/cmdx/coercions/hash.rb +22 -41
  48. data/lib/cmdx/coercions/integer.rb +20 -33
  49. data/lib/cmdx/coercions/rational.rb +20 -32
  50. data/lib/cmdx/coercions/string.rb +23 -31
  51. data/lib/cmdx/coercions/time.rb +24 -40
  52. data/lib/cmdx/coercions/virtual.rb +14 -31
  53. data/lib/cmdx/configuration.rb +57 -171
  54. data/lib/cmdx/context.rb +22 -165
  55. data/lib/cmdx/core_ext/hash.rb +42 -67
  56. data/lib/cmdx/core_ext/module.rb +35 -79
  57. data/lib/cmdx/core_ext/object.rb +63 -98
  58. data/lib/cmdx/correlator.rb +40 -156
  59. data/lib/cmdx/error.rb +37 -202
  60. data/lib/cmdx/errors.rb +165 -202
  61. data/lib/cmdx/fault.rb +55 -158
  62. data/lib/cmdx/faults.rb +26 -137
  63. data/lib/cmdx/immutator.rb +22 -109
  64. data/lib/cmdx/lazy_struct.rb +103 -187
  65. data/lib/cmdx/log_formatters/json.rb +14 -40
  66. data/lib/cmdx/log_formatters/key_value.rb +14 -40
  67. data/lib/cmdx/log_formatters/line.rb +14 -48
  68. data/lib/cmdx/log_formatters/logstash.rb +14 -57
  69. data/lib/cmdx/log_formatters/pretty_json.rb +14 -50
  70. data/lib/cmdx/log_formatters/pretty_key_value.rb +13 -46
  71. data/lib/cmdx/log_formatters/pretty_line.rb +16 -54
  72. data/lib/cmdx/log_formatters/raw.rb +19 -49
  73. data/lib/cmdx/logger.rb +20 -82
  74. data/lib/cmdx/logger_ansi.rb +18 -75
  75. data/lib/cmdx/logger_serializer.rb +24 -114
  76. data/lib/cmdx/middleware.rb +38 -60
  77. data/lib/cmdx/middleware_registry.rb +81 -77
  78. data/lib/cmdx/middlewares/correlate.rb +41 -226
  79. data/lib/cmdx/middlewares/timeout.rb +46 -185
  80. data/lib/cmdx/parameter.rb +120 -198
  81. data/lib/cmdx/parameter_evaluator.rb +231 -0
  82. data/lib/cmdx/parameter_inspector.rb +25 -56
  83. data/lib/cmdx/parameter_registry.rb +59 -84
  84. data/lib/cmdx/parameter_serializer.rb +23 -74
  85. data/lib/cmdx/railtie.rb +24 -107
  86. data/lib/cmdx/result.rb +254 -260
  87. data/lib/cmdx/result_ansi.rb +19 -85
  88. data/lib/cmdx/result_inspector.rb +27 -68
  89. data/lib/cmdx/result_logger.rb +18 -81
  90. data/lib/cmdx/result_serializer.rb +28 -132
  91. data/lib/cmdx/rspec/matchers.rb +28 -0
  92. data/lib/cmdx/rspec/result_matchers/be_executed.rb +42 -0
  93. data/lib/cmdx/rspec/result_matchers/be_failed_task.rb +94 -0
  94. data/lib/cmdx/rspec/result_matchers/be_skipped_task.rb +94 -0
  95. data/lib/cmdx/rspec/result_matchers/be_state_matchers.rb +59 -0
  96. data/lib/cmdx/rspec/result_matchers/be_status_matchers.rb +57 -0
  97. data/lib/cmdx/rspec/result_matchers/be_successful_task.rb +87 -0
  98. data/lib/cmdx/rspec/result_matchers/have_bad_outcome.rb +51 -0
  99. data/lib/cmdx/rspec/result_matchers/have_caused_failure.rb +58 -0
  100. data/lib/cmdx/rspec/result_matchers/have_chain_index.rb +59 -0
  101. data/lib/cmdx/rspec/result_matchers/have_context.rb +86 -0
  102. data/lib/cmdx/rspec/result_matchers/have_empty_metadata.rb +54 -0
  103. data/lib/cmdx/rspec/result_matchers/have_good_outcome.rb +52 -0
  104. data/lib/cmdx/rspec/result_matchers/have_metadata.rb +114 -0
  105. data/lib/cmdx/rspec/result_matchers/have_preserved_context.rb +66 -0
  106. data/lib/cmdx/rspec/result_matchers/have_received_thrown_failure.rb +64 -0
  107. data/lib/cmdx/rspec/result_matchers/have_runtime.rb +78 -0
  108. data/lib/cmdx/rspec/result_matchers/have_thrown_failure.rb +76 -0
  109. data/lib/cmdx/rspec/task_matchers/be_well_formed_task.rb +62 -0
  110. data/lib/cmdx/rspec/task_matchers/have_callback.rb +85 -0
  111. data/lib/cmdx/rspec/task_matchers/have_cmd_setting.rb +68 -0
  112. data/lib/cmdx/rspec/task_matchers/have_executed_callbacks.rb +92 -0
  113. data/lib/cmdx/rspec/task_matchers/have_middleware.rb +46 -0
  114. data/lib/cmdx/rspec/task_matchers/have_parameter.rb +181 -0
  115. data/lib/cmdx/task.rb +213 -425
  116. data/lib/cmdx/task_deprecator.rb +55 -0
  117. data/lib/cmdx/task_processor.rb +245 -0
  118. data/lib/cmdx/task_serializer.rb +22 -70
  119. data/lib/cmdx/utils/ansi_color.rb +13 -89
  120. data/lib/cmdx/utils/log_timestamp.rb +13 -42
  121. data/lib/cmdx/utils/monotonic_runtime.rb +13 -63
  122. data/lib/cmdx/utils/name_affix.rb +21 -71
  123. data/lib/cmdx/validator.rb +48 -0
  124. data/lib/cmdx/validator_registry.rb +86 -0
  125. data/lib/cmdx/validators/exclusion.rb +55 -94
  126. data/lib/cmdx/validators/format.rb +31 -85
  127. data/lib/cmdx/validators/inclusion.rb +65 -110
  128. data/lib/cmdx/validators/length.rb +117 -133
  129. data/lib/cmdx/validators/numeric.rb +123 -130
  130. data/lib/cmdx/validators/presence.rb +38 -79
  131. data/lib/cmdx/version.rb +1 -7
  132. data/lib/cmdx/workflow.rb +46 -339
  133. data/lib/cmdx.rb +1 -1
  134. data/lib/generators/cmdx/install_generator.rb +14 -31
  135. data/lib/generators/cmdx/task_generator.rb +39 -55
  136. data/lib/generators/cmdx/templates/install.rb +61 -11
  137. data/lib/generators/cmdx/workflow_generator.rb +41 -66
  138. data/lib/locales/ar.yml +35 -0
  139. data/lib/locales/cs.yml +35 -0
  140. data/lib/locales/da.yml +35 -0
  141. data/lib/locales/de.yml +35 -0
  142. data/lib/locales/el.yml +35 -0
  143. data/lib/locales/en.yml +19 -20
  144. data/lib/locales/es.yml +19 -20
  145. data/lib/locales/fi.yml +35 -0
  146. data/lib/locales/fr.yml +35 -0
  147. data/lib/locales/he.yml +35 -0
  148. data/lib/locales/hi.yml +35 -0
  149. data/lib/locales/it.yml +35 -0
  150. data/lib/locales/ja.yml +35 -0
  151. data/lib/locales/ko.yml +35 -0
  152. data/lib/locales/nl.yml +35 -0
  153. data/lib/locales/no.yml +35 -0
  154. data/lib/locales/pl.yml +35 -0
  155. data/lib/locales/pt.yml +35 -0
  156. data/lib/locales/ru.yml +35 -0
  157. data/lib/locales/sv.yml +35 -0
  158. data/lib/locales/th.yml +35 -0
  159. data/lib/locales/tr.yml +35 -0
  160. data/lib/locales/vi.yml +35 -0
  161. data/lib/locales/zh.yml +35 -0
  162. metadata +57 -8
  163. data/lib/cmdx/parameter_validator.rb +0 -81
  164. data/lib/cmdx/parameter_value.rb +0 -244
  165. data/lib/cmdx/parameters_inspector.rb +0 -72
  166. data/lib/cmdx/parameters_serializer.rb +0 -115
  167. data/lib/cmdx/rspec/result_matchers.rb +0 -917
  168. data/lib/cmdx/rspec/task_matchers.rb +0 -570
  169. data/lib/cmdx/validators/custom.rb +0 -102
@@ -0,0 +1,94 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CMDx
4
+ # Registry for managing type coercion definitions and execution within tasks.
5
+ #
6
+ # This registry handles the registration and execution of coercions that convert
7
+ # parameter values from one type to another, supporting both built-in types and
8
+ # custom coercion logic.
9
+ class CoercionRegistry
10
+
11
+ # The internal hash storing coercion definitions.
12
+ #
13
+ # @return [Hash] hash containing coercion type keys and coercion class/callable values
14
+ attr_reader :registry
15
+
16
+ # Initializes a new coercion registry with default type coercions.
17
+ #
18
+ # Sets up the registry with built-in coercions for standard Ruby types
19
+ # including primitives, numerics, dates, and collections.
20
+ #
21
+ # @return [CoercionRegistry] a new coercion registry instance
22
+ #
23
+ # @example Creating a new registry
24
+ # registry = CoercionRegistry.new
25
+ # registry.registry[:string] # => Coercions::String
26
+ def initialize
27
+ @registry = {
28
+ array: Coercions::Array,
29
+ big_decimal: Coercions::BigDecimal,
30
+ boolean: Coercions::Boolean,
31
+ complex: Coercions::Complex,
32
+ date: Coercions::Date,
33
+ datetime: Coercions::DateTime,
34
+ float: Coercions::Float,
35
+ hash: Coercions::Hash,
36
+ integer: Coercions::Integer,
37
+ rational: Coercions::Rational,
38
+ string: Coercions::String,
39
+ time: Coercions::Time,
40
+ virtual: Coercions::Virtual
41
+ }
42
+ end
43
+
44
+ # Registers a custom coercion for a specific type.
45
+ #
46
+ # @param type [Symbol] the type identifier for the coercion
47
+ # @param coercion [Object] the coercion callable (class, proc, symbol, or string)
48
+ #
49
+ # @return [CoercionRegistry] returns self for method chaining
50
+ #
51
+ # @example Registering a custom coercion class
52
+ # registry.register(:uuid, UUIDCoercion)
53
+ #
54
+ # @example Registering a proc coercion
55
+ # registry.register(:upcase, ->(value, options) { value.to_s.upcase })
56
+ #
57
+ # @example Chaining registrations
58
+ # registry.register(:custom1, MyCoercion).register(:custom2, AnotherCoercion)
59
+ def register(type, coercion)
60
+ registry[type] = coercion
61
+ self
62
+ end
63
+
64
+ # Executes a coercion for the specified type and value.
65
+ #
66
+ # @param task [Task] the task instance executing the coercion
67
+ # @param type [Symbol] the coercion type to execute
68
+ # @param value [Object] the value to be coerced
69
+ # @param options [Hash] additional options for the coercion
70
+ #
71
+ # @return [Object] the coerced value
72
+ #
73
+ # @raise [UnknownCoercionError] when the coercion type is not registered
74
+ #
75
+ # @example Coercing a string to integer
76
+ # registry.call(task, :integer, "42")
77
+ # # => 42
78
+ #
79
+ # @example Coercing with options
80
+ # registry.call(task, :array, "a,b,c", delimiter: ",")
81
+ # # => ["a", "b", "c"]
82
+ def call(task, type, value, options = {})
83
+ raise UnknownCoercionError, "unknown coercion #{type}" unless registry.key?(type)
84
+
85
+ case coercion = registry[type]
86
+ when Symbol, String, Proc
87
+ task.cmdx_try(coercion, value, options)
88
+ else
89
+ coercion.call(value, options)
90
+ end
91
+ end
92
+
93
+ end
94
+ end
@@ -2,47 +2,29 @@
2
2
 
3
3
  module CMDx
4
4
  module Coercions
5
- # Coerces values to Array type.
5
+ # Coercion class for converting values to arrays.
6
6
  #
7
- # The Array coercion converts parameter values to Array objects,
8
- # with special handling for JSON-formatted strings and general
9
- # array conversion using Ruby's Array() method.
10
- #
11
- # @example Basic array coercion
12
- # class ProcessOrderTask < CMDx::Task
13
- # optional :tags, type: :array, default: []
14
- # optional :item_ids, type: :array
15
- # end
16
- #
17
- # @example Coercion behavior
18
- # Coercions::Array.call([1, 2, 3]) # => [1, 2, 3]
19
- # Coercions::Array.call("hello") # => ["hello"]
20
- # Coercions::Array.call('["a","b"]') # => ["a", "b"] (JSON)
21
- # Coercions::Array.call('[1,2,3]') # => [1, 2, 3] (JSON)
22
- # Coercions::Array.call(nil) # => []
23
- # Coercions::Array.call(42) # => [42]
24
- #
25
- # @see ParameterValue Parameter value coercion
26
- # @see Parameter Parameter type definitions
27
- module Array
7
+ # This coercion handles conversion of various types to arrays, with special
8
+ # handling for JSON-formatted strings that start with "[".
9
+ class Array < Coercion
28
10
 
29
- module_function
30
-
31
- # Coerce a value to Array.
11
+ # Converts the given value to an array.
12
+ #
13
+ # @param value [Object] the value to convert to an array
14
+ # @param _options [Hash] optional configuration (currently unused)
15
+ #
16
+ # @return [Array] the converted array value
32
17
  #
33
- # If the value is a JSON-formatted string (starts with '['), it will
34
- # be parsed as JSON. Otherwise, it uses Ruby's Array() method for
35
- # general array conversion.
18
+ # @raise [JSON::ParserError] if value is a JSON string that cannot be parsed
19
+ # @raise [TypeError] if the value cannot be converted to an array
36
20
  #
37
- # @param value [Object] value to coerce to array
38
- # @param _options [Hash] coercion options (unused)
39
- # @return [Array] coerced array value
40
- # @raise [JSON::ParserError] if JSON parsing fails
21
+ # @example Converting a JSON string
22
+ # Coercions::Array.call('["a", "b", "c"]') #=> ["a", "b", "c"]
41
23
  #
42
- # @example
43
- # Coercions::Array.call("test") # => ["test"]
44
- # Coercions::Array.call('["a","b"]') # => ["a", "b"]
45
- # Coercions::Array.call([1, 2]) # => [1, 2]
24
+ # @example Converting other values
25
+ # Coercions::Array.call("hello") #=> ["hello"]
26
+ # Coercions::Array.call(123) #=> [123]
27
+ # Coercions::Array.call(nil) #=> []
46
28
  def call(value, _options = {})
47
29
  if value.is_a?(::String) && value.start_with?("[")
48
30
  JSON.parse(value)
@@ -2,45 +2,33 @@
2
2
 
3
3
  module CMDx
4
4
  module Coercions
5
- # Coerces values to BigDecimal type.
5
+ # Coercion class for converting values to BigDecimal.
6
6
  #
7
- # The BigDecimal coercion converts parameter values to BigDecimal objects
8
- # for high-precision decimal arithmetic. Supports configurable precision
9
- # and handles various numeric input formats.
10
- #
11
- # @example Basic BigDecimal coercion
12
- # class ProcessOrderTask < CMDx::Task
13
- # required :total_amount, type: :big_decimal
14
- # optional :tax_rate, type: :big_decimal, precision: 4
15
- # end
16
- #
17
- # @example Coercion behavior
18
- # Coercions::BigDecimal.call("123.45") # => #<BigDecimal:...,'0.12345E3',18(27)>
19
- # Coercions::BigDecimal.call(42) # => #<BigDecimal:...,'0.42E2',9(18)>
20
- # Coercions::BigDecimal.call("0.333333", precision: 6) # Custom precision
21
- #
22
- # @see ParameterValue Parameter value coercion
23
- # @see Parameter Parameter type definitions
24
- module BigDecimal
7
+ # This coercion handles conversion of various types to BigDecimal with
8
+ # configurable precision. It provides precise decimal arithmetic capabilities
9
+ # for financial calculations and other use cases requiring exact decimal representation.
10
+ class BigDecimal < Coercion
25
11
 
26
- # Default precision for BigDecimal calculations
27
- # @return [Integer] default precision value
28
12
  DEFAULT_PRECISION = 14
29
13
 
30
- module_function
31
-
32
- # Coerce a value to BigDecimal.
14
+ # Converts the given value to a BigDecimal.
15
+ #
16
+ # @param value [Object] the value to convert to a BigDecimal
17
+ # @param options [Hash] optional configuration
18
+ # @option options [Integer] :precision the precision for the BigDecimal (defaults to 14)
19
+ #
20
+ # @return [BigDecimal] the converted BigDecimal value
21
+ #
22
+ # @raise [CoercionError] if the value cannot be converted to a BigDecimal
23
+ #
24
+ # @example Converting a string
25
+ # Coercions::BigDecimal.call('123.45') #=> #<BigDecimal:...,'0.12345E3',18(27)>
33
26
  #
34
- # @param value [Object] value to coerce to BigDecimal
35
- # @param options [Hash] coercion options
36
- # @option options [Integer] :precision decimal precision (default: 14)
37
- # @return [BigDecimal] coerced BigDecimal value
38
- # @raise [CoercionError] if coercion fails
27
+ # @example Converting with custom precision
28
+ # Coercions::BigDecimal.call('123.456789', precision: 10) #=> #<BigDecimal:...,'0.123456789E3',18(27)>
39
29
  #
40
- # @example
41
- # Coercions::BigDecimal.call("123.45") # => BigDecimal with default precision
42
- # Coercions::BigDecimal.call("0.333", precision: 10) # => BigDecimal with custom precision
43
- # Coercions::BigDecimal.call(42.5) # => BigDecimal from float
30
+ # @example Converting an integer
31
+ # Coercions::BigDecimal.call(100) #=> #<BigDecimal:...,'0.1E3',9(18)>
44
32
  def call(value, options = {})
45
33
  BigDecimal(value, options[:precision] || DEFAULT_PRECISION)
46
34
  rescue ArgumentError, TypeError
@@ -2,53 +2,34 @@
2
2
 
3
3
  module CMDx
4
4
  module Coercions
5
- # Coerces values to Boolean type (true/false).
5
+ # Coercion class for converting values to booleans.
6
6
  #
7
- # The Boolean coercion converts parameter values to true or false
8
- # based on string pattern matching for common boolean representations.
9
- # It handles various textual representations of true and false values.
10
- #
11
- # @example Basic boolean coercion
12
- # class ProcessOrderTask < CMDx::Task
13
- # optional :send_email, type: :boolean, default: true
14
- # optional :is_urgent, type: :boolean, default: false
15
- # end
16
- #
17
- # @example Coercion behavior
18
- # Coercions::Boolean.call("true") # => true
19
- # Coercions::Boolean.call("yes") # => true
20
- # Coercions::Boolean.call("1") # => true
21
- # Coercions::Boolean.call("false") # => false
22
- # Coercions::Boolean.call("no") # => false
23
- # Coercions::Boolean.call("0") # => false
24
- # Coercions::Boolean.call("invalid") # => raises CoercionError
25
- #
26
- # @see ParameterValue Parameter value coercion
27
- # @see Parameter Parameter type definitions
28
- module Boolean
7
+ # This coercion handles conversion of various string representations to
8
+ # boolean values, supporting common true/false variations like "yes/no",
9
+ # "1/0", and "t/f".
10
+ class Boolean < Coercion
29
11
 
30
- # Pattern matching false-like values (case insensitive)
31
- # @return [Regexp] regex for falsey string values
32
12
  FALSEY = /^(false|f|no|n|0)$/i
33
-
34
- # Pattern matching true-like values (case insensitive)
35
- # @return [Regexp] regex for truthy string values
36
13
  TRUTHY = /^(true|t|yes|y|1)$/i
37
14
 
38
- module_function
39
-
40
- # Coerce a value to Boolean.
15
+ # Converts the given value to a boolean.
16
+ #
17
+ # @param value [Object] the value to convert to a boolean
18
+ # @param _options [Hash] optional configuration (currently unused)
19
+ #
20
+ # @return [Boolean] the converted boolean value
21
+ #
22
+ # @raise [CoercionError] if the value cannot be converted to a boolean
41
23
  #
42
- # @param value [Object] value to coerce to boolean
43
- # @param _options [Hash] coercion options (unused)
44
- # @return [Boolean] coerced boolean value (true or false)
45
- # @raise [CoercionError] if value cannot be coerced to boolean
24
+ # @example Converting truthy values
25
+ # Coercions::Boolean.call('true') #=> true
26
+ # Coercions::Boolean.call('yes') #=> true
27
+ # Coercions::Boolean.call('1') #=> true
46
28
  #
47
- # @example
48
- # Coercions::Boolean.call("yes") # => true
49
- # Coercions::Boolean.call("False") # => false
50
- # Coercions::Boolean.call("1") # => true
51
- # Coercions::Boolean.call("0") # => false
29
+ # @example Converting falsey values
30
+ # Coercions::Boolean.call('false') #=> false
31
+ # Coercions::Boolean.call('no') #=> false
32
+ # Coercions::Boolean.call('0') #=> false
52
33
  def call(value, _options = {})
53
34
  case value.to_s.downcase
54
35
  when FALSEY then false
@@ -2,41 +2,28 @@
2
2
 
3
3
  module CMDx
4
4
  module Coercions
5
- # Coerces values to Complex type.
5
+ # Coercion class for converting values to complex numbers.
6
6
  #
7
- # The Complex coercion converts parameter values to Complex number objects
8
- # using Ruby's built-in Complex() method, with proper error handling
9
- # for values that cannot be converted to complex numbers.
10
- #
11
- # @example Basic complex coercion
12
- # class MathTask < CMDx::Task
13
- # required :complex_number, type: :complex
14
- # optional :coefficient, type: :complex, default: Complex(1, 0)
15
- # end
16
- #
17
- # @example Coercion behavior
18
- # Coercions::Complex.call("1+2i") # => (1+2i)
19
- # Coercions::Complex.call("3-4i") # => (3-4i)
20
- # Coercions::Complex.call(5) # => (5+0i)
21
- # Coercions::Complex.call("invalid") # => raises CoercionError
22
- #
23
- # @see ParameterValue Parameter value coercion
24
- # @see Parameter Parameter type definitions
25
- module Complex
26
-
27
- module_function
7
+ # This coercion handles conversion of various types to complex numbers,
8
+ # including strings, integers, floats, and other numeric types.
9
+ class Complex < Coercion
28
10
 
29
- # Coerce a value to Complex.
11
+ # Converts the given value to a complex number.
12
+ #
13
+ # @param value [Object] the value to convert to a complex number
14
+ # @param _options [Hash] optional configuration (currently unused)
15
+ #
16
+ # @return [Complex] the converted complex number value
17
+ #
18
+ # @raise [CoercionError] if the value cannot be converted to a complex number
30
19
  #
31
- # @param value [Object] value to coerce to complex number
32
- # @param _options [Hash] coercion options (unused)
33
- # @return [Complex] coerced complex number value
34
- # @raise [CoercionError] if coercion fails
20
+ # @example Converting numeric values
21
+ # Coercions::Complex.call(5) #=> (5+0i)
22
+ # Coercions::Complex.call(3.14) #=> (3.14+0i)
35
23
  #
36
- # @example
37
- # Coercions::Complex.call("1+2i") # => (1+2i)
38
- # Coercions::Complex.call(42) # => (42+0i)
39
- # Coercions::Complex.call("3.5-2i") # => (3.5-2i)
24
+ # @example Converting string representations
25
+ # Coercions::Complex.call("2+3i") #=> (2+3i)
26
+ # Coercions::Complex.call("1-2i") #=> (1-2i)
40
27
  def call(value, _options = {})
41
28
  Complex(value)
42
29
  rescue ArgumentError, TypeError
@@ -2,54 +2,35 @@
2
2
 
3
3
  module CMDx
4
4
  module Coercions
5
- # Coerces values to Date type.
5
+ # Coercion class for converting values to Date objects.
6
6
  #
7
- # The Date coercion converts parameter values to Date objects
8
- # with support for date parsing, custom format strings, and
9
- # automatic handling of date-like objects.
10
- #
11
- # @example Basic date coercion
12
- # class ProcessOrderTask < CMDx::Task
13
- # required :order_date, type: :date
14
- # optional :delivery_date, type: :date, format: "%Y-%m-%d"
15
- # end
16
- #
17
- # @example Coercion behavior
18
- # Coercions::Date.call("2023-12-25") # => Date object
19
- # Coercions::Date.call("25/12/2023", format: "%d/%m/%Y") # Custom format
20
- # Coercions::Date.call(Time.now) # => Date (from Time)
21
- # Coercions::Date.call("invalid") # => raises CoercionError
22
- #
23
- # @see ParameterValue Parameter value coercion
24
- # @see Parameter Parameter type definitions
25
- module Date
7
+ # This coercion handles conversion of various types to Date objects, with support
8
+ # for custom date formats and automatic detection of date-like objects.
9
+ class Date < Coercion
26
10
 
27
- # Date-compatible class names that are passed through unchanged
28
- # @return [Array<String>] class names that represent date-like objects
29
11
  ANALOG_TYPES = %w[Date DateTime Time].freeze
30
12
 
31
- module_function
32
-
33
- # Coerce a value to Date.
13
+ # Converts the given value to a Date object.
14
+ #
15
+ # @param value [Object] the value to convert to a Date
16
+ # @param options [Hash] optional configuration
17
+ # @option options [String] :strptime custom date format for parsing
18
+ #
19
+ # @return [Date] the converted Date object
20
+ #
21
+ # @raise [CoercionError] if the value cannot be converted to a Date
34
22
  #
35
- # Handles multiple input formats:
36
- # - Date, DateTime, Time objects (returned as Date)
37
- # - String with custom format (parsed using strptime)
38
- # - String with standard format (parsed using Date.parse)
23
+ # @example Converting a string with default parsing
24
+ # Coercions::Date.call('2023-12-25') #=> #<Date: 2023-12-25>
39
25
  #
40
- # @param value [Object] value to coerce to date
41
- # @param options [Hash] coercion options
42
- # @option options [String] :format custom date format string
43
- # @return [Date] coerced date value
44
- # @raise [CoercionError] if coercion fails
26
+ # @example Converting with custom format
27
+ # Coercions::Date.call('25/12/2023', strptime: '%d/%m/%Y') #=> #<Date: 2023-12-25>
45
28
  #
46
- # @example
47
- # Coercions::Date.call("2023-12-25") # => Date
48
- # Coercions::Date.call("25/12/2023", format: "%d/%m/%Y") # => Date with custom format
49
- # Coercions::Date.call(Time.now) # => Date from Time
29
+ # @example Converting existing date-like objects
30
+ # Coercions::Date.call(DateTime.now) #=> #<Date: 2023-12-25>
50
31
  def call(value, options = {})
51
32
  return value if ANALOG_TYPES.include?(value.class.name)
52
- return ::Date.strptime(value, options[:format]) if options[:format]
33
+ return ::Date.strptime(value, options[:strptime]) if options[:strptime]
53
34
 
54
35
  ::Date.parse(value)
55
36
  rescue TypeError, ::Date::Error
@@ -2,54 +2,37 @@
2
2
 
3
3
  module CMDx
4
4
  module Coercions
5
- # Coerces values to DateTime type.
5
+ # Coercion class for converting values to DateTime objects.
6
6
  #
7
- # The DateTime coercion converts parameter values to DateTime objects
8
- # with support for datetime parsing, custom format strings, and
9
- # automatic handling of date/time-like objects.
10
- #
11
- # @example Basic datetime coercion
12
- # class ProcessOrderTask < CMDx::Task
13
- # required :order_datetime, type: :date_time
14
- # optional :delivery_datetime, type: :date_time, format: "%Y-%m-%d %H:%M:%S"
15
- # end
16
- #
17
- # @example Coercion behavior
18
- # Coercions::DateTime.call("2023-12-25T14:30:00") # => DateTime object
19
- # Coercions::DateTime.call("25/12/2023 2:30 PM", format: "%d/%m/%Y %l:%M %p") # Custom format
20
- # Coercions::DateTime.call(Time.now) # => DateTime (from Time)
21
- # Coercions::DateTime.call("invalid") # => raises CoercionError
22
- #
23
- # @see ParameterValue Parameter value coercion
24
- # @see Parameter Parameter type definitions
25
- module DateTime
7
+ # This coercion handles conversion of various types to DateTime objects,
8
+ # with support for custom date/time formats and automatic detection of
9
+ # analog types (Date, DateTime, Time).
10
+ class DateTime < Coercion
26
11
 
27
- # DateTime-compatible class names that are passed through unchanged
28
- # @return [Array<String>] class names that represent datetime-like objects
29
12
  ANALOG_TYPES = %w[Date DateTime Time].freeze
30
13
 
31
- module_function
32
-
33
- # Coerce a value to DateTime.
14
+ # Converts the given value to a DateTime object.
15
+ #
16
+ # @param value [Object] the value to convert to a DateTime
17
+ # @param options [Hash] optional configuration
18
+ # @option options [String] :strptime custom format string for parsing
19
+ #
20
+ # @return [DateTime] the converted DateTime object
21
+ #
22
+ # @raise [CoercionError] if the value cannot be converted to a DateTime
34
23
  #
35
- # Handles multiple input formats:
36
- # - Date, DateTime, Time objects (returned as-is)
37
- # - String with custom format (parsed using strptime)
38
- # - String with standard format (parsed using DateTime.parse)
24
+ # @example Converting a date string
25
+ # Coercions::DateTime.call('2023-12-25') #=> #<DateTime: 2023-12-25T00:00:00+00:00>
39
26
  #
40
- # @param value [Object] value to coerce to datetime
41
- # @param options [Hash] coercion options
42
- # @option options [String] :format custom datetime format string
43
- # @return [DateTime] coerced datetime value
44
- # @raise [CoercionError] if coercion fails
27
+ # @example Converting with a custom format
28
+ # Coercions::DateTime.call('25/12/2023', strptime: '%d/%m/%Y') #=> #<DateTime: 2023-12-25T00:00:00+00:00>
45
29
  #
46
- # @example
47
- # Coercions::DateTime.call("2023-12-25T14:30:00") # => DateTime
48
- # Coercions::DateTime.call("25/12/2023 14:30", format: "%d/%m/%Y %H:%M") # => DateTime with custom format
49
- # Coercions::DateTime.call(Time.now) # => DateTime from Time
30
+ # @example Passing through existing DateTime objects
31
+ # dt = DateTime.now
32
+ # Coercions::DateTime.call(dt) #=> dt (unchanged)
50
33
  def call(value, options = {})
51
34
  return value if ANALOG_TYPES.include?(value.class.name)
52
- return ::DateTime.strptime(value, options[:format]) if options[:format]
35
+ return ::DateTime.strptime(value, options[:strptime]) if options[:strptime]
53
36
 
54
37
  ::DateTime.parse(value)
55
38
  rescue TypeError, ::Date::Error
@@ -2,44 +2,31 @@
2
2
 
3
3
  module CMDx
4
4
  module Coercions
5
- # Coerces values to Float type.
5
+ # Coercion class for converting values to floats.
6
6
  #
7
- # The Float coercion converts parameter values to Float objects
8
- # using Ruby's built-in Float() method, with proper error handling
9
- # for values that cannot be converted to floating-point numbers.
10
- #
11
- # @example Basic float coercion
12
- # class ProcessOrderTask < CMDx::Task
13
- # required :price, type: :float
14
- # optional :discount_rate, type: :float, default: 0.0
15
- # end
16
- #
17
- # @example Coercion behavior
18
- # Coercions::Float.call("123.45") # => 123.45
19
- # Coercions::Float.call("1.5e2") # => 150.0 (scientific notation)
20
- # Coercions::Float.call(42) # => 42.0
21
- # Coercions::Float.call("invalid") # => raises CoercionError
22
- #
23
- # @see ParameterValue Parameter value coercion
24
- # @see Parameter Parameter type definitions
25
- module Float
26
-
27
- module_function
7
+ # This coercion handles conversion of various types to float values using
8
+ # Ruby's built-in Float() method.
9
+ class Float < Coercion
28
10
 
29
- # Coerce a value to Float.
11
+ # Converts the given value to a float.
12
+ #
13
+ # @param value [Object] the value to convert to a float
14
+ # @param _options [Hash] optional configuration (currently unused)
15
+ #
16
+ # @return [Float] the converted float value
17
+ #
18
+ # @raise [CoercionError] if the value cannot be converted to a float
30
19
  #
31
- # @param value [Object] value to coerce to float
32
- # @param _options [Hash] coercion options (unused)
33
- # @return [Float] coerced float value
34
- # @raise [CoercionError] if coercion fails
20
+ # @example Converting numeric strings
21
+ # Coercions::Float.call("3.14") #=> 3.14
22
+ # Coercions::Float.call("42") #=> 42.0
35
23
  #
36
- # @example
37
- # Coercions::Float.call("123.45") # => 123.45
38
- # Coercions::Float.call(42) # => 42.0
39
- # Coercions::Float.call("1e3") # => 1000.0
24
+ # @example Converting other numeric types
25
+ # Coercions::Float.call(42) #=> 42.0
26
+ # Coercions::Float.call(3.14) #=> 3.14
40
27
  def call(value, _options = {})
41
28
  Float(value)
42
- rescue ArgumentError, TypeError
29
+ rescue ArgumentError, RangeError, TypeError
43
30
  raise CoercionError, I18n.t(
44
31
  "cmdx.coercions.into_a",
45
32
  type: "float",