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
@@ -1,28 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Cmdx
4
- ##
5
- # Rails generator for creating CMDx task classes.
4
+ # Rails generator for creating CMDx task files.
6
5
  #
7
- # This generator creates individual task files that encapsulate specific
8
- # business logic operations. Tasks inherit from CMDx::Task and provide
9
- # parameter validation, callbacks, result tracking, and error handling
10
- # capabilities for focused business operations.
11
- #
12
- # The generator handles name normalization, ensuring "Task" suffix
13
- # and proper file naming conventions. Generated tasks inherit from
14
- # ApplicationTask when available, falling back to CMDx::Task.
15
- #
16
- # @example Generate a task
17
- # rails generate cmdx:task SendEmail
18
- # rails generate cmdx:task ProcessPayment
19
- # rails generate cmdx:task ProcessPaymentTask # "Task" suffix preserved
20
- #
21
- # @example Generated file location
22
- # app/cmds/send_email_task.rb
23
- # app/cmds/process_payment_task.rb
24
- #
25
- # @since 1.0.0
6
+ # This generator creates task files in the app/cmds directory with proper
7
+ # class naming conventions and inheritance. It ensures task names end with
8
+ # "Task" suffix and creates files in the correct location within the Rails
9
+ # application structure.
26
10
  class TaskGenerator < Rails::Generators::NamedBase
27
11
 
28
12
  source_root File.expand_path("templates", __dir__)
@@ -30,25 +14,21 @@ module Cmdx
30
14
 
31
15
  desc "Creates a task with the given NAME"
32
16
 
33
- ##
34
- # Copies the task template to the application commands directory.
17
+ # Creates the task file from the template.
35
18
  #
36
- # Creates a new task file in `app/cmds/` with the normalized name.
37
- # The generator automatically handles:
38
- # - Removing "Task" suffix from file naming
39
- # - Converting to snake_case for file naming
40
- # - Adding "_task" suffix to the filename
41
- # - Setting up proper class inheritance
19
+ # Generates a new task file in the app/cmds directory based on the provided
20
+ # name. The file name is normalized to ensure it ends with "_task.rb" and
21
+ # is placed in the appropriate subdirectory structure.
42
22
  #
43
23
  # @return [void]
44
- # @raise [Thor::Error] if the destination file cannot be created
45
24
  #
46
- # @example Generated task structure
47
- # class SendEmailTask < ApplicationTask
48
- # def call
49
- # # Task business logic
50
- # end
51
- # end
25
+ # @example Generate a user task
26
+ # rails generate cmdx:task user
27
+ # # => Creates app/cmds/user_task.rb
28
+ #
29
+ # @example Generate a nested task
30
+ # rails generate cmdx:task admin/users
31
+ # # => Creates app/cmds/admin/users_task.rb
52
32
  def copy_files
53
33
  name = file_name.sub(/_?task$/i, "")
54
34
  path = File.join("app/cmds", class_path, "#{name}_task.rb")
@@ -57,37 +37,41 @@ module Cmdx
57
37
 
58
38
  private
59
39
 
60
- ##
61
- # Normalizes the class name by ensuring "Task" suffix.
40
+ # Ensures the class name ends with "Task" suffix.
62
41
  #
63
- # Ensures consistent class naming by adding "Task" suffix if not
64
- # already present, allowing users to specify either "SendEmail"
65
- # or "SendEmailTask".
42
+ # Takes the provided class name and appends "Task" if it doesn't already
43
+ # end with that suffix, ensuring consistent naming conventions across
44
+ # all generated task classes.
66
45
  #
67
- # @return [String] the normalized class name with "Task" suffix
46
+ # @return [String] the class name with "Task" suffix
68
47
  #
69
- # @example Class name normalization
70
- # # Input: "SendEmail"
71
- # # Output: "SendEmailTask"
48
+ # @example Class name without suffix
49
+ # # Given name: "User"
50
+ # class_name # => "UserTask"
72
51
  #
73
- # # Input: "SendEmailTask"
74
- # # Output: "SendEmailTask"
52
+ # @example Class name with suffix
53
+ # # Given name: "UserTask"
54
+ # class_name # => "UserTask"
75
55
  def class_name
76
56
  @class_name ||= super.end_with?("Task") ? super : "#{super}Task"
77
57
  end
78
58
 
79
- ##
80
59
  # Determines the parent class for the generated task.
81
60
  #
82
- # Attempts to use ApplicationTask as the parent class if available,
83
- # falling back to CMDx::Task if ApplicationTask is not defined.
84
- # This allows applications to define custom base task behavior.
61
+ # Attempts to use ApplicationTask as the parent class if it exists in the
62
+ # application, otherwise falls back to CMDx::Task as the base class.
63
+ # This allows applications to define their own base task class with
64
+ # common functionality.
65
+ #
66
+ # @return [Class] the parent class for the generated task
67
+ #
68
+ # @raise [StandardError] if neither ApplicationTask nor CMDx::Task are available
85
69
  #
86
- # @return [String] the parent class name to inherit from
70
+ # @example With ApplicationTask defined
71
+ # parent_class_name # => ApplicationTask
87
72
  #
88
- # @example Parent class resolution
89
- # # If ApplicationTask exists: "ApplicationTask"
90
- # # If ApplicationTask missing: "CMDx::Task"
73
+ # @example Without ApplicationTask
74
+ # parent_class_name # => CMDx::Task
91
75
  def parent_class_name
92
76
  ApplicationTask
93
77
  rescue StandardError
@@ -1,19 +1,69 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  CMDx.configure do |config|
4
- # Halt execution and raise fault on these result statuses when using `call!`
5
- config.task_halt = CMDx::Result::FAILED
4
+ # Task halt configuration - controls when call! raises faults
5
+ # See https://github.com/drexed/cmdx/blob/main/docs/outcomes/statuses.md for more details
6
+ #
7
+ # Available statuses: "success", "skipped", "failed"
8
+ # If set to an empty array, task will never halt
9
+ config.task_halt = %w[failed]
6
10
 
7
- # Global timeout for individual tasks (nil = no timeout)
11
+ # Workflow halt configuration - controls when workflows stop execution
12
+ # When a task returns these statuses, subsequent workflow tasks won't execute
13
+ # See https://github.com/drexed/cmdx/blob/main/docs/workflow.md for more details
14
+ #
15
+ # Available statuses: "success", "skipped", "failed"
16
+ # If set to an empty array, workflow will never halt
17
+ config.workflow_halt = %w[failed]
8
18
 
9
- # Stop workflow execution when tasks return these statuses
10
- # Note: Skipped tasks continue processing by default
11
- config.workflow_halt = CMDx::Result::FAILED
19
+ # Logger configuration - choose from multiple formatters
20
+ # See https://github.com/drexed/cmdx/blob/main/docs/logging.md for more details
21
+ #
22
+ # Available formatters:
23
+ # - CMDx::LogFormatters::Line
24
+ # - CMDx::LogFormatters::PrettyLine
25
+ # - CMDx::LogFormatters::Json
26
+ # - CMDx::LogFormatters::PrettyJson
27
+ # - CMDx::LogFormatters::KeyValue
28
+ # - CMDx::LogFormatters::PrettyKeyValue
29
+ # - CMDx::LogFormatters::Logstash
30
+ # - CMDx::LogFormatters::Raw
31
+ config.logger = Logger.new($stdout, formatter: CMDx::LogFormatters::Line.new)
12
32
 
13
- # Global timeout for entire workflow execution (nil = no timeout)
14
- # Tip: Account for all tasks when setting this value
33
+ # Global middlewares - automatically applied to all tasks
34
+ # See https://github.com/drexed/cmdx/blob/main/docs/middlewares.md for more details
35
+ #
36
+ # config.middlewares.use CMDx::Middlewares::Correlate
37
+ # config.middlewares.use CMDx::Middlewares::Timeout, seconds: 30
38
+ # config.middlewares.use CustomAuthMiddleware, if: :admin?
39
+ # config.middlewares.use CustomPerfMiddleware.new(threshold: 5.0)
15
40
 
16
- # Logger with formatter - see available formatters at:
17
- # https://github.com/drexed/cmdx/tree/main/lib/cmdx/log_formatters
18
- config.logger = Logger.new($stdout, formatter: CMDx::LogFormatters::Line.new)
41
+ # Global callbacks - automatically applied to all tasks
42
+ # See https://github.com/drexed/cmdx/blob/main/docs/callbacks.md for more details
43
+ #
44
+ # config.callbacks.register :before_execution, :log_task_start
45
+ # config.callbacks.register :after_execution, TrackTaskCompletion
46
+ # config.callbacks.register :on_success, NotificationCallback.new(via: [:email, :slack])
47
+ # config.callbacks.register :on_failure, :alert_support, if: :critical?
48
+ # config.callbacks.register :on_complete, proc { |task, type|
49
+ # Metrics.increment("task.#{task.class.name.underscore}.completed")
50
+ # }
51
+
52
+ # Global coercions - custom parameter type conversions
53
+ # See https://github.com/drexed/cmdx/blob/main/docs/parameters/coercions.md for more details
54
+ #
55
+ # config.coercions.register :money, MoneyCoercion
56
+ # config.coercions.register :tags, TagsCoercion.new
57
+ # config.coercions.register :slug, proc { |value|
58
+ # value.to_s.downcase.gsub(/[^a-z0-9]+/, '-').gsub(/-+/, '-').strip('-')
59
+ # }
60
+
61
+ # Global validators - parameter validation logic
62
+ # See https://github.com/drexed/cmdx/blob/main/docs/parameters/validations.md for more details
63
+ #
64
+ # config.validators.register :email, EmailValidator
65
+ # config.validators.register :phone, PhoneValidator.new
66
+ # config.validators.register :phone, proc { |value, options|
67
+ # PhoneValidator.validate(value, options)
68
+ # }
19
69
  end
@@ -1,36 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Cmdx
4
- ##
5
- # Rails generator for creating CMDx workflow task classes.
4
+ # Rails generator for creating CMDx workflow files.
6
5
  #
7
- # This generator creates workflow task files that coordinate multiple
8
- # individual tasks in a structured workflow. Workflow tasks inherit
9
- # from CMDx::Workflow and provide orchestration capabilities for
10
- # complex business processes.
11
- #
12
- # The generator handles name normalization, ensuring proper file naming
13
- # conventions and class names. Generated workflow tasks inherit from
14
- # ApplicationWorkflow when available, falling back to CMDx::Workflow.
15
- #
16
- # @example Generate a workflow task
17
- # rails generate cmdx:workflow OrderProcessing
18
- # rails generate cmdx:workflow PaymentWorkflow # "Workflow" suffix preserved
19
- #
20
- # @example Generated file location
21
- # app/cmds/order_processing_workflow.rb
22
- # app/cmds/payment_workflow.rb
23
- #
24
- # @example Generated class structure
25
- # class OrderProcessingWorkflow < ApplicationWorkflow
26
- # def call
27
- # # Workflow orchestration logic
28
- # end
29
- # end
30
- #
31
- # @see CMDx::Workflow Base workflow class
32
- # @see Rails::Generators::NamedBase Rails generator base class
33
- # @since 1.0.0
6
+ # This generator creates workflow files in the app/cmds directory with proper
7
+ # class naming conventions and inheritance. It ensures workflow names end with
8
+ # "Workflow" suffix and creates files in the correct location within the Rails
9
+ # application structure.
34
10
  class WorkflowGenerator < Rails::Generators::NamedBase
35
11
 
36
12
  source_root File.expand_path("templates", __dir__)
@@ -38,28 +14,23 @@ module Cmdx
38
14
 
39
15
  desc "Creates a workflow with the given NAME"
40
16
 
41
- ##
42
- # Copies the workflow task template to the application commands directory.
17
+ # Creates the workflow file from the template.
43
18
  #
44
- # Creates a new workflow task file in `app/cmds/` with the normalized
45
- # name. The generator automatically handles:
46
- # - Removing "workflow" suffix from the provided name for filename
47
- # - Converting to snake_case for file naming
48
- # - Adding "_workflow" suffix to the filename
49
- # - Setting up proper class inheritance
50
- # - Ensuring class names end with "Workflow"
19
+ # Generates a new workflow file in the app/cmds directory based on the provided
20
+ # name. The file name is normalized to ensure it ends with "_workflow.rb" and
21
+ # is placed in the appropriate subdirectory structure.
51
22
  #
52
23
  # @return [void]
53
- # @raise [Thor::Error] if the destination file cannot be created
54
24
  #
55
- # @example File generation
56
- # # Input: rails generate cmdx:workflow OrderProcessing
57
- # # Creates: app/cmds/order_processing_workflow.rb
58
- # # Class: OrderProcessingWorkflow
25
+ # @raise [Thor::Error] if the destination file cannot be created or already exists without force
26
+ #
27
+ # @example Generate a user workflow
28
+ # rails generate cmdx:workflow user
29
+ # # => Creates app/cmds/user_workflow.rb
59
30
  #
60
- # # Input: rails generate cmdx:workflow PaymentWorkflow
61
- # # Creates: app/cmds/payment_workflow.rb
62
- # # Class: PaymentWorkflow
31
+ # @example Generate a nested workflow
32
+ # rails generate cmdx:workflow admin/users
33
+ # # => Creates app/cmds/admin/users_workflow.rb
63
34
  def copy_files
64
35
  name = file_name.sub(/_?workflow$/i, "")
65
36
  path = File.join("app/cmds", class_path, "#{name}_workflow.rb")
@@ -68,37 +39,41 @@ module Cmdx
68
39
 
69
40
  private
70
41
 
71
- ##
72
- # Normalizes the class name by ensuring it ends with "Workflow".
42
+ # Ensures the class name ends with "Workflow" suffix.
73
43
  #
74
- # Ensures consistent class naming by appending "Workflow" suffix
75
- # to the provided generator name if it doesn't already end with it,
76
- # allowing users to specify either "OrderProcessing" or "OrderProcessingWorkflow".
44
+ # Takes the provided class name and appends "Workflow" if it doesn't already
45
+ # end with that suffix, ensuring consistent naming conventions across
46
+ # all generated workflow classes.
77
47
  #
78
- # @return [String] the normalized class name with "Workflow" suffix
48
+ # @return [String] the class name with "Workflow" suffix
79
49
  #
80
- # @example Class name normalization
81
- # # Input: "OrderProcessing"
82
- # # Output: "OrderProcessingWorkflow"
50
+ # @example Class name without suffix
51
+ # # Given name: "User"
52
+ # class_name # => "UserWorkflow"
83
53
  #
84
- # # Input: "PaymentWorkflow"
85
- # # Output: "PaymentWorkflow"
54
+ # @example Class name with suffix
55
+ # # Given name: "UserWorkflow"
56
+ # class_name # => "UserWorkflow"
86
57
  def class_name
87
58
  @class_name ||= super.end_with?("Workflow") ? super : "#{super}Workflow"
88
59
  end
89
60
 
90
- ##
91
- # Determines the parent class for the generated workflow task.
61
+ # Determines the parent class for the generated workflow.
62
+ #
63
+ # Attempts to use ApplicationWorkflow as the parent class if it exists in the
64
+ # application, otherwise falls back to CMDx::Workflow as the base class.
65
+ # This allows applications to define their own base workflow class with
66
+ # common functionality.
67
+ #
68
+ # @return [Class] the parent class for the generated workflow
92
69
  #
93
- # Attempts to use ApplicationWorkflow as the parent class if available,
94
- # falling back to CMDx::Workflow if ApplicationWorkflow is not defined.
95
- # This allows applications to define custom base workflow behavior.
70
+ # @raise [StandardError] if neither ApplicationWorkflow nor CMDx::Workflow are available
96
71
  #
97
- # @return [String] the parent class name to inherit from
72
+ # @example With ApplicationWorkflow defined
73
+ # parent_class_name # => ApplicationWorkflow
98
74
  #
99
- # @example Parent class resolution
100
- # # If ApplicationWorkflow exists: "ApplicationWorkflow"
101
- # # If ApplicationWorkflow missing: "CMDx::Workflow"
75
+ # @example Without ApplicationWorkflow
76
+ # parent_class_name # => CMDx::Workflow
102
77
  def parent_class_name
103
78
  ApplicationWorkflow
104
79
  rescue StandardError
@@ -0,0 +1,35 @@
1
+ ar:
2
+ cmdx:
3
+ coercions:
4
+ into_a: "لا يمكن تحويل إلى %{type}"
5
+ into_an: "لا يمكن تحويل إلى %{type}"
6
+ into_any: "لا يمكن تحويل إلى أي من: %{values}"
7
+ unknown: "نوع التحويل %{type} غير معروف"
8
+ faults:
9
+ unspecified: "لم يتم تحديد سبب"
10
+ parameters:
11
+ required: "معامل مطلوب"
12
+ undefined: "يفوض لطريقة غير معرفة %{source}"
13
+ validators:
14
+ exclusion:
15
+ of: "يجب ألا يكون أحد: %{values}"
16
+ within: "يجب ألا يكون بين %{min} و %{max}"
17
+ format: "له تنسيق غير صالح"
18
+ inclusion:
19
+ of: "يجب أن يكون أحد: %{values}"
20
+ within: "يجب أن يكون بين %{min} و %{max}"
21
+ length:
22
+ is: "يجب أن يكون الطول %{is}"
23
+ is_not: "يجب ألا يكون الطول %{is_not}"
24
+ min: "يجب أن يكون الطول على الأقل %{min}"
25
+ max: "يجب أن يكون الطول على الأكثر %{max}"
26
+ not_within: "يجب ألا يكون الطول بين %{min} و %{max}"
27
+ within: "يجب أن يكون الطول بين %{min} و %{max}"
28
+ numeric:
29
+ is: "يجب أن يكون %{is}"
30
+ is_not: "يجب ألا يكون %{is_not}"
31
+ min: "يجب أن يكون على الأقل %{min}"
32
+ max: "يجب أن يكون على الأكثر %{max}"
33
+ not_within: "يجب ألا يكون بين %{min} و %{max}"
34
+ within: "يجب أن يكون بين %{min} و %{max}"
35
+ presence: "لا يمكن أن يكون فارغاً"
@@ -0,0 +1,35 @@
1
+ cs:
2
+ cmdx:
3
+ coercions:
4
+ into_a: "nelze převést na %{type}"
5
+ into_an: "nelze převést na %{type}"
6
+ into_any: "nelze převést na jeden z: %{values}"
7
+ unknown: "neznámý typ převodu %{type}"
8
+ faults:
9
+ unspecified: "nebyl uveden důvod"
10
+ parameters:
11
+ required: "je povinný parametr"
12
+ undefined: "deleguje na nedefinovanou metodu %{source}"
13
+ validators:
14
+ exclusion:
15
+ of: "nesmí být jeden z: %{values}"
16
+ within: "nesmí být mezi %{min} a %{max}"
17
+ format: "má neplatný formát"
18
+ inclusion:
19
+ of: "musí být jeden z: %{values}"
20
+ within: "musí být mezi %{min} a %{max}"
21
+ length:
22
+ is: "délka musí být %{is}"
23
+ is_not: "délka nesmí být %{is_not}"
24
+ min: "délka musí být alespoň %{min}"
25
+ max: "délka může být nejvýše %{max}"
26
+ not_within: "délka nesmí být mezi %{min} a %{max}"
27
+ within: "délka musí být mezi %{min} a %{max}"
28
+ numeric:
29
+ is: "musí být %{is}"
30
+ is_not: "nesmí být %{is_not}"
31
+ min: "musí být alespoň %{min}"
32
+ max: "může být nejvýše %{max}"
33
+ not_within: "nesmí být mezi %{min} a %{max}"
34
+ within: "musí být mezi %{min} a %{max}"
35
+ presence: "nemůže být prázdný"
@@ -0,0 +1,35 @@
1
+ da:
2
+ cmdx:
3
+ coercions:
4
+ into_a: "kunne ikke konvertere til en %{type}"
5
+ into_an: "kunne ikke konvertere til en %{type}"
6
+ into_any: "kunne ikke konvertere til en af: %{values}"
7
+ unknown: "ukendt %{type} konverteringstype"
8
+ faults:
9
+ unspecified: "ingen grund angivet"
10
+ parameters:
11
+ required: "er en påkrævet parameter"
12
+ undefined: "delegerer til udefineret metode %{source}"
13
+ validators:
14
+ exclusion:
15
+ of: "må ikke være en af: %{values}"
16
+ within: "må ikke være mellem %{min} og %{max}"
17
+ format: "har et ugyldigt format"
18
+ inclusion:
19
+ of: "skal være en af: %{values}"
20
+ within: "skal være mellem %{min} og %{max}"
21
+ length:
22
+ is: "længde skal være %{is}"
23
+ is_not: "længde må ikke være %{is_not}"
24
+ min: "længde skal være mindst %{min}"
25
+ max: "længde må være højst %{max}"
26
+ not_within: "længde må ikke være mellem %{min} og %{max}"
27
+ within: "længde skal være mellem %{min} og %{max}"
28
+ numeric:
29
+ is: "skal være %{is}"
30
+ is_not: "må ikke være %{is_not}"
31
+ min: "skal være mindst %{min}"
32
+ max: "må være højst %{max}"
33
+ not_within: "må ikke være mellem %{min} og %{max}"
34
+ within: "skal være mellem %{min} og %{max}"
35
+ presence: "kan ikke være tom"
@@ -0,0 +1,35 @@
1
+ de:
2
+ cmdx:
3
+ coercions:
4
+ into_a: "konnte nicht in einen %{type} konvertiert werden"
5
+ into_an: "konnte nicht in einen %{type} konvertiert werden"
6
+ into_any: "konnte nicht in einen von: %{values} konvertiert werden"
7
+ unknown: "unbekannter %{type} Konvertierungstyp"
8
+ faults:
9
+ unspecified: "kein Grund angegeben"
10
+ parameters:
11
+ required: "ist ein erforderlicher Parameter"
12
+ undefined: "delegiert an undefinierte Methode %{source}"
13
+ validators:
14
+ exclusion:
15
+ of: "darf nicht einer von: %{values} sein"
16
+ within: "darf nicht zwischen %{min} und %{max} liegen"
17
+ format: "hat ein ungültiges Format"
18
+ inclusion:
19
+ of: "muss einer von: %{values} sein"
20
+ within: "muss zwischen %{min} und %{max} liegen"
21
+ length:
22
+ is: "Länge muss %{is} sein"
23
+ is_not: "Länge darf nicht %{is_not} sein"
24
+ min: "Länge muss mindestens %{min} sein"
25
+ max: "Länge darf höchstens %{max} sein"
26
+ not_within: "Länge darf nicht zwischen %{min} und %{max} liegen"
27
+ within: "Länge muss zwischen %{min} und %{max} liegen"
28
+ numeric:
29
+ is: "muss %{is} sein"
30
+ is_not: "darf nicht %{is_not} sein"
31
+ min: "muss mindestens %{min} sein"
32
+ max: "darf höchstens %{max} sein"
33
+ not_within: "darf nicht zwischen %{min} und %{max} liegen"
34
+ within: "muss zwischen %{min} und %{max} liegen"
35
+ presence: "kann nicht leer sein"
@@ -0,0 +1,35 @@
1
+ el:
2
+ cmdx:
3
+ coercions:
4
+ into_a: "δεν ήταν δυνατή η μετατροπή σε %{type}"
5
+ into_an: "δεν ήταν δυνατή η μετατροπή σε %{type}"
6
+ into_any: "δεν ήταν δυνατή η μετατροπή σε κανένα από: %{values}"
7
+ unknown: "άγνωστος τύπος μετατροπής %{type}"
8
+ faults:
9
+ unspecified: "δεν δόθηκε λόγος"
10
+ parameters:
11
+ required: "είναι υποχρεωτική παράμετρος"
12
+ undefined: "αναθέτει σε μη ορισμένη μέθοδο %{source}"
13
+ validators:
14
+ exclusion:
15
+ of: "δεν πρέπει να είναι ένα από: %{values}"
16
+ within: "δεν πρέπει να είναι μεταξύ %{min} και %{max}"
17
+ format: "έχει μη έγκυρη μορφή"
18
+ inclusion:
19
+ of: "πρέπει να είναι ένα από: %{values}"
20
+ within: "πρέπει να είναι μεταξύ %{min} και %{max}"
21
+ length:
22
+ is: "το μήκος πρέπει να είναι %{is}"
23
+ is_not: "το μήκος δεν πρέπει να είναι %{is_not}"
24
+ min: "το μήκος πρέπει να είναι τουλάχιστον %{min}"
25
+ max: "το μήκος πρέπει να είναι το πολύ %{max}"
26
+ not_within: "το μήκος δεν πρέπει να είναι μεταξύ %{min} και %{max}"
27
+ within: "το μήκος πρέπει να είναι μεταξύ %{min} και %{max}"
28
+ numeric:
29
+ is: "πρέπει να είναι %{is}"
30
+ is_not: "δεν πρέπει να είναι %{is_not}"
31
+ min: "πρέπει να είναι τουλάχιστον %{min}"
32
+ max: "πρέπει να είναι το πολύ %{max}"
33
+ not_within: "δεν πρέπει να είναι μεταξύ %{min} και %{max}"
34
+ within: "πρέπει να είναι μεταξύ %{min} και %{max}"
35
+ presence: "δεν μπορεί να είναι κενό"
data/lib/locales/en.yml CHANGED
@@ -6,31 +6,30 @@ en:
6
6
  into_any: "could not coerce into one of: %{values}"
7
7
  unknown: "unknown %{type} coercion type"
8
8
  faults:
9
- unspecified: no reason given
9
+ unspecified: "no reason given"
10
10
  parameters:
11
- required: is a required parameter
12
- undefined: delegates to undefined method %{source}
11
+ required: "is a required parameter"
12
+ undefined: "delegates to undefined method %{source}"
13
13
  validators:
14
- custom: is not valid
15
14
  exclusion:
16
15
  of: "must not be one of: %{values}"
17
- within: must not be within %{min} and %{max}
18
- format: is an invalid format
16
+ within: "must not be within %{min} and %{max}"
17
+ format: "is an invalid format"
19
18
  inclusion:
20
19
  of: "must be one of: %{values}"
21
- within: must be within %{min} and %{max}
20
+ within: "must be within %{min} and %{max}"
22
21
  length:
23
- is: length must be %{is}
24
- is_not: length must not be %{is_not}
25
- min: length must be at least %{min}
26
- max: length must be at most %{max}
27
- not_within: length must not be within %{min} and %{max}
28
- within: length must be within %{min} and %{max}
22
+ is: "length must be %{is}"
23
+ is_not: "length must not be %{is_not}"
24
+ min: "length must be at least %{min}"
25
+ max: "length must be at most %{max}"
26
+ not_within: "length must not be within %{min} and %{max}"
27
+ within: "length must be within %{min} and %{max}"
29
28
  numeric:
30
- is: must be %{is}
31
- is_not: must not be %{is_not}
32
- min: must be at least %{min}
33
- max: must be at most %{max}
34
- not_within: must not be within %{min} and %{max}
35
- within: must be within %{min} and %{max}
36
- presence: cannot be empty
29
+ is: "must be %{is}"
30
+ is_not: "must not be %{is_not}"
31
+ min: "must be at least %{min}"
32
+ max: "must be at most %{max}"
33
+ not_within: "must not be within %{min} and %{max}"
34
+ within: "must be within %{min} and %{max}"
35
+ presence: "cannot be empty"
data/lib/locales/es.yml CHANGED
@@ -6,31 +6,30 @@ es:
6
6
  into_any: "no podía coacciona el valor a un: %{values}"
7
7
  unknown: "%{type} tipo de coacciona desconocido"
8
8
  faults:
9
- unspecified: ninguna razón dada
9
+ unspecified: "ninguna razón dada"
10
10
  parameters:
11
- required: es un parámetro requerido
12
- undefined: delegado al método indefinido %{source}
11
+ required: "es un parámetro requerido"
12
+ undefined: "delegado al método indefinido %{source}"
13
13
  validators:
14
- custom: no es válida
15
14
  exclusion:
16
15
  of: "no debe ser uno de: %{values}"
17
- within: no debe estar dentro %{min} y %{max}
18
- format: es un formato inválido
16
+ within: "no debe estar dentro %{min} y %{max}"
17
+ format: "es un formato inválido"
19
18
  inclusion:
20
19
  of: "debe ser uno de: %{values}"
21
- within: debe estar dentro %{min} y %{max}
20
+ within: "debe estar dentro %{min} y %{max}"
22
21
  length:
23
- is: tiene una longitud que debe ser %{is}
24
- is_not: tiene una longitud no debe ser %{is}
25
- min: tiene una longitud que debe ser menos de %{min}
26
- max: tiene una longitud que debe ser mas de %{max}
27
- not_within: tiene una longitud que no debe estar dentro %{min} y %{max}
28
- within: tiene una longitud que debe estar dentro %{min} y %{max}
22
+ is: "tiene una longitud que debe ser %{is}"
23
+ is_not: "tiene una longitud no debe ser %{is}"
24
+ min: "tiene una longitud que debe ser menos de %{min}"
25
+ max: "tiene una longitud que debe ser mas de %{max}"
26
+ not_within: "tiene una longitud que no debe estar dentro %{min} y %{max}"
27
+ within: "tiene una longitud que debe estar dentro %{min} y %{max}"
29
28
  numeric:
30
- is: debe ser %{is}
31
- is_not: no debe ser %{is}
32
- min: debe ser %{min} como minimo
33
- max: debe ser %{max} como máximo
34
- not_within: no debe estar dentro %{min} y %{max}
35
- within: debe estar dentro %{min} y %{max}
36
- presence: no puede estar vacío
29
+ is: "debe ser %{is}"
30
+ is_not: "no debe ser %{is}"
31
+ min: "debe ser %{min} como minimo"
32
+ max: "debe ser %{max} como máximo"
33
+ not_within: "no debe estar dentro %{min} y %{max}"
34
+ within: "debe estar dentro %{min} y %{max}"
35
+ presence: "no puede estar vacío"