cmdx 1.0.1 → 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 (157) 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 +2 -0
  5. data/CHANGELOG.md +17 -2
  6. data/README.md +1 -1
  7. data/docs/basics/call.md +2 -2
  8. data/docs/basics/chain.md +1 -1
  9. data/docs/callbacks.md +3 -36
  10. data/docs/configuration.md +58 -12
  11. data/docs/interruptions/exceptions.md +1 -1
  12. data/docs/interruptions/faults.md +2 -2
  13. data/docs/logging.md +4 -4
  14. data/docs/middlewares.md +43 -43
  15. data/docs/parameters/coercions.md +49 -38
  16. data/docs/parameters/defaults.md +1 -1
  17. data/docs/parameters/validations.md +0 -39
  18. data/docs/testing.md +11 -12
  19. data/docs/workflows.md +4 -4
  20. data/lib/cmdx/.DS_Store +0 -0
  21. data/lib/cmdx/callback.rb +36 -56
  22. data/lib/cmdx/callback_registry.rb +82 -73
  23. data/lib/cmdx/chain.rb +65 -122
  24. data/lib/cmdx/chain_inspector.rb +22 -115
  25. data/lib/cmdx/chain_serializer.rb +17 -148
  26. data/lib/cmdx/coercion.rb +49 -0
  27. data/lib/cmdx/coercion_registry.rb +94 -0
  28. data/lib/cmdx/coercions/array.rb +18 -36
  29. data/lib/cmdx/coercions/big_decimal.rb +21 -33
  30. data/lib/cmdx/coercions/boolean.rb +21 -40
  31. data/lib/cmdx/coercions/complex.rb +18 -31
  32. data/lib/cmdx/coercions/date.rb +20 -39
  33. data/lib/cmdx/coercions/date_time.rb +22 -39
  34. data/lib/cmdx/coercions/float.rb +19 -32
  35. data/lib/cmdx/coercions/hash.rb +22 -41
  36. data/lib/cmdx/coercions/integer.rb +20 -33
  37. data/lib/cmdx/coercions/rational.rb +20 -32
  38. data/lib/cmdx/coercions/string.rb +23 -31
  39. data/lib/cmdx/coercions/time.rb +24 -40
  40. data/lib/cmdx/coercions/virtual.rb +14 -31
  41. data/lib/cmdx/configuration.rb +57 -171
  42. data/lib/cmdx/context.rb +22 -165
  43. data/lib/cmdx/core_ext/hash.rb +42 -67
  44. data/lib/cmdx/core_ext/module.rb +35 -79
  45. data/lib/cmdx/core_ext/object.rb +63 -98
  46. data/lib/cmdx/correlator.rb +40 -156
  47. data/lib/cmdx/error.rb +37 -202
  48. data/lib/cmdx/errors.rb +165 -202
  49. data/lib/cmdx/fault.rb +55 -158
  50. data/lib/cmdx/faults.rb +26 -137
  51. data/lib/cmdx/immutator.rb +22 -109
  52. data/lib/cmdx/lazy_struct.rb +103 -187
  53. data/lib/cmdx/log_formatters/json.rb +14 -40
  54. data/lib/cmdx/log_formatters/key_value.rb +14 -40
  55. data/lib/cmdx/log_formatters/line.rb +14 -48
  56. data/lib/cmdx/log_formatters/logstash.rb +14 -57
  57. data/lib/cmdx/log_formatters/pretty_json.rb +14 -50
  58. data/lib/cmdx/log_formatters/pretty_key_value.rb +13 -46
  59. data/lib/cmdx/log_formatters/pretty_line.rb +16 -54
  60. data/lib/cmdx/log_formatters/raw.rb +19 -49
  61. data/lib/cmdx/logger.rb +20 -82
  62. data/lib/cmdx/logger_ansi.rb +18 -75
  63. data/lib/cmdx/logger_serializer.rb +24 -114
  64. data/lib/cmdx/middleware.rb +38 -60
  65. data/lib/cmdx/middleware_registry.rb +81 -77
  66. data/lib/cmdx/middlewares/correlate.rb +41 -226
  67. data/lib/cmdx/middlewares/timeout.rb +46 -185
  68. data/lib/cmdx/parameter.rb +120 -198
  69. data/lib/cmdx/parameter_evaluator.rb +231 -0
  70. data/lib/cmdx/parameter_inspector.rb +25 -56
  71. data/lib/cmdx/parameter_registry.rb +59 -84
  72. data/lib/cmdx/parameter_serializer.rb +23 -74
  73. data/lib/cmdx/railtie.rb +24 -107
  74. data/lib/cmdx/result.rb +254 -260
  75. data/lib/cmdx/result_ansi.rb +19 -85
  76. data/lib/cmdx/result_inspector.rb +27 -68
  77. data/lib/cmdx/result_logger.rb +18 -81
  78. data/lib/cmdx/result_serializer.rb +28 -132
  79. data/lib/cmdx/rspec/matchers.rb +28 -0
  80. data/lib/cmdx/rspec/result_matchers/be_executed.rb +42 -0
  81. data/lib/cmdx/rspec/result_matchers/be_failed_task.rb +94 -0
  82. data/lib/cmdx/rspec/result_matchers/be_skipped_task.rb +94 -0
  83. data/lib/cmdx/rspec/result_matchers/be_state_matchers.rb +59 -0
  84. data/lib/cmdx/rspec/result_matchers/be_status_matchers.rb +57 -0
  85. data/lib/cmdx/rspec/result_matchers/be_successful_task.rb +87 -0
  86. data/lib/cmdx/rspec/result_matchers/have_bad_outcome.rb +51 -0
  87. data/lib/cmdx/rspec/result_matchers/have_caused_failure.rb +58 -0
  88. data/lib/cmdx/rspec/result_matchers/have_chain_index.rb +59 -0
  89. data/lib/cmdx/rspec/result_matchers/have_context.rb +86 -0
  90. data/lib/cmdx/rspec/result_matchers/have_empty_metadata.rb +54 -0
  91. data/lib/cmdx/rspec/result_matchers/have_good_outcome.rb +52 -0
  92. data/lib/cmdx/rspec/result_matchers/have_metadata.rb +114 -0
  93. data/lib/cmdx/rspec/result_matchers/have_preserved_context.rb +66 -0
  94. data/lib/cmdx/rspec/result_matchers/have_received_thrown_failure.rb +64 -0
  95. data/lib/cmdx/rspec/result_matchers/have_runtime.rb +78 -0
  96. data/lib/cmdx/rspec/result_matchers/have_thrown_failure.rb +76 -0
  97. data/lib/cmdx/rspec/task_matchers/be_well_formed_task.rb +62 -0
  98. data/lib/cmdx/rspec/task_matchers/have_callback.rb +85 -0
  99. data/lib/cmdx/rspec/task_matchers/have_cmd_setting.rb +68 -0
  100. data/lib/cmdx/rspec/task_matchers/have_executed_callbacks.rb +92 -0
  101. data/lib/cmdx/rspec/task_matchers/have_middleware.rb +46 -0
  102. data/lib/cmdx/rspec/task_matchers/have_parameter.rb +181 -0
  103. data/lib/cmdx/task.rb +213 -425
  104. data/lib/cmdx/task_deprecator.rb +55 -0
  105. data/lib/cmdx/task_processor.rb +245 -0
  106. data/lib/cmdx/task_serializer.rb +22 -70
  107. data/lib/cmdx/utils/ansi_color.rb +13 -89
  108. data/lib/cmdx/utils/log_timestamp.rb +13 -42
  109. data/lib/cmdx/utils/monotonic_runtime.rb +13 -63
  110. data/lib/cmdx/utils/name_affix.rb +21 -71
  111. data/lib/cmdx/validator.rb +48 -0
  112. data/lib/cmdx/validator_registry.rb +86 -0
  113. data/lib/cmdx/validators/exclusion.rb +55 -94
  114. data/lib/cmdx/validators/format.rb +31 -85
  115. data/lib/cmdx/validators/inclusion.rb +65 -110
  116. data/lib/cmdx/validators/length.rb +117 -133
  117. data/lib/cmdx/validators/numeric.rb +123 -130
  118. data/lib/cmdx/validators/presence.rb +38 -79
  119. data/lib/cmdx/version.rb +1 -7
  120. data/lib/cmdx/workflow.rb +46 -339
  121. data/lib/cmdx.rb +1 -1
  122. data/lib/generators/cmdx/install_generator.rb +14 -31
  123. data/lib/generators/cmdx/task_generator.rb +39 -55
  124. data/lib/generators/cmdx/templates/install.rb +24 -6
  125. data/lib/generators/cmdx/workflow_generator.rb +41 -66
  126. data/lib/locales/ar.yml +0 -1
  127. data/lib/locales/cs.yml +0 -1
  128. data/lib/locales/da.yml +0 -1
  129. data/lib/locales/de.yml +0 -1
  130. data/lib/locales/el.yml +0 -1
  131. data/lib/locales/en.yml +0 -1
  132. data/lib/locales/es.yml +0 -1
  133. data/lib/locales/fi.yml +0 -1
  134. data/lib/locales/fr.yml +0 -1
  135. data/lib/locales/he.yml +0 -1
  136. data/lib/locales/hi.yml +0 -1
  137. data/lib/locales/it.yml +0 -1
  138. data/lib/locales/ja.yml +0 -1
  139. data/lib/locales/ko.yml +0 -1
  140. data/lib/locales/nl.yml +0 -1
  141. data/lib/locales/no.yml +0 -1
  142. data/lib/locales/pl.yml +0 -1
  143. data/lib/locales/pt.yml +0 -1
  144. data/lib/locales/ru.yml +0 -1
  145. data/lib/locales/sv.yml +0 -1
  146. data/lib/locales/th.yml +0 -1
  147. data/lib/locales/tr.yml +0 -1
  148. data/lib/locales/vi.yml +0 -1
  149. data/lib/locales/zh.yml +0 -1
  150. metadata +34 -8
  151. data/lib/cmdx/parameter_validator.rb +0 -81
  152. data/lib/cmdx/parameter_value.rb +0 -244
  153. data/lib/cmdx/parameters_inspector.rb +0 -72
  154. data/lib/cmdx/parameters_serializer.rb +0 -115
  155. data/lib/cmdx/rspec/result_matchers.rb +0 -917
  156. data/lib/cmdx/rspec/task_matchers.rb +0 -570
  157. data/lib/cmdx/validators/custom.rb +0 -102
@@ -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",
@@ -2,47 +2,33 @@
2
2
 
3
3
  module CMDx
4
4
  module Coercions
5
- # Coerces values to Hash type.
5
+ # Coercion class for converting values to hashes.
6
6
  #
7
- # The Hash coercion converts parameter values to Hash objects
8
- # with support for various input formats including JSON strings,
9
- # arrays (converted to hash), and Rails parameters.
10
- #
11
- # @example Basic hash coercion
12
- # class ProcessOrderTask < CMDx::Task
13
- # optional :metadata, type: :hash, default: {}
14
- # optional :options, type: :hash
15
- # end
16
- #
17
- # @example Coercion behavior
18
- # Coercions::Hash.call({a: 1}) # => {a: 1}
19
- # Coercions::Hash.call('{"a":1,"b":2}') # => {"a"=>1, "b"=>2} (JSON)
20
- # Coercions::Hash.call([:a, 1, :b, 2]) # => {:a=>1, :b=>2} (Array)
21
- # Coercions::Hash.call("invalid") # => raises CoercionError
22
- #
23
- # @see ParameterValue Parameter value coercion
24
- # @see Parameter Parameter type definitions
25
- module Hash
26
-
27
- extend self
7
+ # This coercion handles conversion of various types to hashes, with special
8
+ # handling for JSON-formatted strings that start with "{" and array-to-hash
9
+ # conversion using array splatting.
10
+ class Hash < Coercion
28
11
 
29
- # Coerce a value to Hash.
12
+ # Converts the given value to a hash.
30
13
  #
31
- # Supports multiple input formats:
32
- # - Hash objects (returned as-is)
33
- # - ActionController::Parameters (returned as-is)
34
- # - JSON strings starting with '{' (parsed as JSON)
35
- # - Arrays (converted using Hash[*array])
14
+ # @param value [Object] the value to convert to a hash
15
+ # @param _options [Hash] optional configuration (currently unused)
36
16
  #
37
- # @param value [Object] value to coerce to hash
38
- # @param _options [Hash] coercion options (unused)
39
- # @return [Hash] coerced hash value
40
- # @raise [CoercionError] if coercion fails
17
+ # @return [Hash] the converted hash value
41
18
  #
42
- # @example
43
- # Coercions::Hash.call({key: "value"}) # => {key: "value"}
44
- # Coercions::Hash.call('{"a": 1}') # => {"a" => 1}
45
- # Coercions::Hash.call([:a, 1, :b, 2]) # => {:a => 1, :b => 2}
19
+ # @raise [CoercionError] if the value cannot be converted to a hash
20
+ # @raise [JSON::ParserError] if value is a JSON string that cannot be parsed
21
+ # @raise [ArgumentError] if array cannot be converted to hash pairs
22
+ # @raise [TypeError] if the value type is not supported
23
+ #
24
+ # @example Converting a JSON string
25
+ # Coercions::Hash.call('{"a": 1, "b": 2}') #=> {"a" => 1, "b" => 2}
26
+ #
27
+ # @example Converting an array to hash
28
+ # Coercions::Hash.call(["a", 1, "b", 2]) #=> {"a" => 1, "b" => 2}
29
+ #
30
+ # @example Passing through existing hashes
31
+ # Coercions::Hash.call({"key" => "value"}) #=> {"key" => "value"}
46
32
  def call(value, _options = {})
47
33
  case value.class.name
48
34
  when "Hash", "ActionController::Parameters"
@@ -60,11 +46,6 @@ module CMDx
60
46
 
61
47
  private
62
48
 
63
- # Raise a standardized coercion error.
64
- #
65
- # @return [void]
66
- # @raise [CoercionError] always raises coercion error
67
- # @api private
68
49
  def raise_coercion_error!
69
50
  raise CoercionError, I18n.t(
70
51
  "cmdx.coercions.into_a",
@@ -2,45 +2,32 @@
2
2
 
3
3
  module CMDx
4
4
  module Coercions
5
- # Coerces values to Integer type.
5
+ # Coercion class for converting values to integers.
6
6
  #
7
- # The Integer coercion converts parameter values to Integer objects
8
- # using Ruby's built-in Integer() method, with proper error handling
9
- # for values that cannot be converted.
10
- #
11
- # @example Basic integer coercion
12
- # class ProcessOrderTask < CMDx::Task
13
- # required :order_id, type: :integer
14
- # optional :quantity, type: :integer, default: 1
15
- # end
16
- #
17
- # @example Coercion behavior
18
- # Coercions::Integer.call("123") # => 123
19
- # Coercions::Integer.call("0x10") # => 16 (hex)
20
- # Coercions::Integer.call("0b1010") # => 10 (binary)
21
- # Coercions::Integer.call(45.7) # => 45 (truncated)
22
- # Coercions::Integer.call("invalid") # => raises CoercionError
23
- #
24
- # @see ParameterValue Parameter value coercion
25
- # @see Parameter Parameter type definitions
26
- module Integer
27
-
28
- module_function
7
+ # This coercion handles conversion of various types to integers using Ruby's
8
+ # built-in Integer() method, which provides strict type conversion.
9
+ class Integer < Coercion
29
10
 
30
- # Coerce a value to Integer.
11
+ # Converts the given value to an integer.
12
+ #
13
+ # @param value [Object] the value to convert to an integer
14
+ # @param _options [Hash] optional configuration (currently unused)
15
+ #
16
+ # @return [Integer] the converted integer value
17
+ #
18
+ # @raise [CoercionError] if the value cannot be converted to an integer
31
19
  #
32
- # @param value [Object] value to coerce to integer
33
- # @param _options [Hash] coercion options (unused)
34
- # @return [Integer] coerced integer value
35
- # @raise [CoercionError] if coercion fails
20
+ # @example Converting numeric strings
21
+ # Coercions::Integer.call("123") #=> 123
22
+ # Coercions::Integer.call("-456") #=> -456
36
23
  #
37
- # @example
38
- # Coercions::Integer.call("123") # => 123
39
- # Coercions::Integer.call(45.9) # => 45
40
- # Coercions::Integer.call("0xFF") # => 255
24
+ # @example Converting other numeric types
25
+ # Coercions::Integer.call(123.45) #=> 123
26
+ # Coercions::Integer.call(Time.now) #=> 1672574400 (timestamp)
27
+ # Coercions::Integer.call(Complex(42, 0)) #=> 42
41
28
  def call(value, _options = {})
42
29
  Integer(value)
43
- rescue ArgumentError, TypeError
30
+ rescue ArgumentError, FloatDomainError, RangeError, TypeError # rubocop:disable Lint/ShadowedException
44
31
  raise CoercionError, I18n.t(
45
32
  "cmdx.coercions.into_an",
46
33
  type: "integer",
@@ -2,44 +2,32 @@
2
2
 
3
3
  module CMDx
4
4
  module Coercions
5
- # Coerces values to Rational type.
5
+ # Coercion class for converting values to rational numbers.
6
6
  #
7
- # The Rational coercion converts parameter values to Rational number objects
8
- # using Ruby's built-in Rational() method, with proper error handling
9
- # for values that cannot be converted to rational numbers.
10
- #
11
- # @example Basic rational coercion
12
- # class MathTask < CMDx::Task
13
- # required :fraction, type: :rational
14
- # optional :ratio, type: :rational, default: Rational(1, 2)
15
- # end
16
- #
17
- # @example Coercion behavior
18
- # Coercions::Rational.call("1/2") # => (1/2)
19
- # Coercions::Rational.call("3/4") # => (3/4)
20
- # Coercions::Rational.call(0.5) # => (1/2)
21
- # Coercions::Rational.call("invalid") # => raises CoercionError
22
- #
23
- # @see ParameterValue Parameter value coercion
24
- # @see Parameter Parameter type definitions
25
- module Rational
26
-
27
- module_function
7
+ # This coercion handles conversion of various types to rational numbers,
8
+ # using Ruby's built-in Rational() method for type conversion.
9
+ class Rational < Coercion
28
10
 
29
- # Coerce a value to Rational.
11
+ # Converts the given value to a rational number.
12
+ #
13
+ # @param value [Object] the value to convert to a rational number
14
+ # @param _options [Hash] optional configuration (currently unused)
15
+ #
16
+ # @return [Rational] the converted rational value
17
+ #
18
+ # @raise [CoercionError] if the value cannot be converted to a rational number
19
+ #
20
+ # @example Converting a string fraction
21
+ # Coercions::Rational.call('1/2') #=> (1/2)
30
22
  #
31
- # @param value [Object] value to coerce to rational number
32
- # @param _options [Hash] coercion options (unused)
33
- # @return [Rational] coerced rational number value
34
- # @raise [CoercionError] if coercion fails
23
+ # @example Converting an integer
24
+ # Coercions::Rational.call(5) #=> (5/1)
35
25
  #
36
- # @example
37
- # Coercions::Rational.call("1/2") # => (1/2)
38
- # Coercions::Rational.call(0.75) # => (3/4)
39
- # Coercions::Rational.call("3.5") # => (7/2)
26
+ # @example Converting a float
27
+ # Coercions::Rational.call(0.25) #=> (1/4)
40
28
  def call(value, _options = {})
41
29
  Rational(value)
42
- rescue ArgumentError, TypeError
30
+ rescue ArgumentError, FloatDomainError, RangeError, TypeError, ZeroDivisionError # rubocop:disable Lint/ShadowedException
43
31
  raise CoercionError, I18n.t(
44
32
  "cmdx.coercions.into_a",
45
33
  type: "rational",
@@ -2,41 +2,33 @@
2
2
 
3
3
  module CMDx
4
4
  module Coercions
5
- # Coerces values to String type.
5
+ # Coercion class for converting values to strings.
6
6
  #
7
- # The String coercion converts parameter values to String objects
8
- # using Ruby's built-in String() method, which handles various
9
- # input types safely.
10
- #
11
- # @example Basic string coercion
12
- # class ProcessOrderTask < CMDx::Task
13
- # required :order_id, type: :string
14
- # optional :notes, type: :string
15
- # end
16
- #
17
- # @example Coercion behavior
18
- # Coercions::String.call(123) # => "123"
19
- # Coercions::String.call(:symbol) # => "symbol"
20
- # Coercions::String.call(true) # => "true"
21
- # Coercions::String.call(nil) # => ""
22
- # Coercions::String.call([1, 2]) # => "12" (array to_s)
23
- #
24
- # @see ParameterValue Parameter value coercion
25
- # @see Parameter Parameter type definitions
26
- module String
27
-
28
- module_function
7
+ # This coercion handles conversion of various types to strings using Ruby's
8
+ # built-in String() method, which provides consistent string conversion
9
+ # behavior across different object types.
10
+ class String < Coercion
29
11
 
30
- # Coerce a value to String.
12
+ # Converts the given value to a string.
13
+ #
14
+ # @param value [Object] the value to convert to a string
15
+ # @param _options [Hash] optional configuration (currently unused)
16
+ #
17
+ # @return [String] the converted string value
18
+ #
19
+ # @raise [TypeError] if the value cannot be converted to a string
20
+ #
21
+ # @example Converting numbers
22
+ # Coercions::String.call(123) #=> "123"
23
+ # Coercions::String.call(45.67) #=> "45.67"
31
24
  #
32
- # @param value [Object] value to coerce to string
33
- # @param _options [Hash] coercion options (unused)
34
- # @return [String] coerced string value
35
- # @raise [CoercionError] if coercion fails
25
+ # @example Converting symbols and nil
26
+ # Coercions::String.call(:symbol) #=> "symbol"
27
+ # Coercions::String.call(nil) #=> ""
36
28
  #
37
- # @example
38
- # Coercions::String.call(123) # => "123"
39
- # Coercions::String.call(:test) # => "test"
29
+ # @example Converting boolean values
30
+ # Coercions::String.call(true) #=> "true"
31
+ # Coercions::String.call(false) #=> "false"
40
32
  def call(value, _options = {})
41
33
  String(value)
42
34
  end