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.
- checksums.yaml +4 -4
- data/.cursor/prompts/rspec.md +20 -0
- data/.cursor/prompts/yardoc.md +8 -0
- data/.rubocop.yml +5 -0
- data/CHANGELOG.md +101 -49
- data/README.md +2 -1
- data/docs/ai_prompts.md +10 -0
- data/docs/basics/call.md +11 -2
- data/docs/basics/chain.md +10 -1
- data/docs/basics/context.md +9 -0
- data/docs/basics/setup.md +9 -0
- data/docs/callbacks.md +14 -37
- data/docs/configuration.md +68 -27
- data/docs/getting_started.md +11 -0
- data/docs/internationalization.md +148 -0
- data/docs/interruptions/exceptions.md +10 -1
- data/docs/interruptions/faults.md +11 -2
- data/docs/interruptions/halt.md +9 -0
- data/docs/logging.md +14 -4
- data/docs/middlewares.md +53 -43
- data/docs/outcomes/result.md +9 -0
- data/docs/outcomes/states.md +9 -0
- data/docs/outcomes/statuses.md +9 -0
- data/docs/parameters/coercions.md +58 -38
- data/docs/parameters/defaults.md +10 -1
- data/docs/parameters/definitions.md +9 -0
- data/docs/parameters/namespacing.md +9 -0
- data/docs/parameters/validations.md +8 -67
- data/docs/testing.md +22 -13
- data/docs/tips_and_tricks.md +9 -0
- data/docs/workflows.md +14 -4
- data/lib/cmdx/.DS_Store +0 -0
- data/lib/cmdx/callback.rb +36 -56
- data/lib/cmdx/callback_registry.rb +82 -73
- data/lib/cmdx/chain.rb +65 -122
- data/lib/cmdx/chain_inspector.rb +22 -115
- data/lib/cmdx/chain_serializer.rb +17 -148
- data/lib/cmdx/coercion.rb +49 -0
- data/lib/cmdx/coercion_registry.rb +94 -0
- data/lib/cmdx/coercions/array.rb +18 -36
- data/lib/cmdx/coercions/big_decimal.rb +21 -33
- data/lib/cmdx/coercions/boolean.rb +21 -40
- data/lib/cmdx/coercions/complex.rb +18 -31
- data/lib/cmdx/coercions/date.rb +20 -39
- data/lib/cmdx/coercions/date_time.rb +22 -39
- data/lib/cmdx/coercions/float.rb +19 -32
- data/lib/cmdx/coercions/hash.rb +22 -41
- data/lib/cmdx/coercions/integer.rb +20 -33
- data/lib/cmdx/coercions/rational.rb +20 -32
- data/lib/cmdx/coercions/string.rb +23 -31
- data/lib/cmdx/coercions/time.rb +24 -40
- data/lib/cmdx/coercions/virtual.rb +14 -31
- data/lib/cmdx/configuration.rb +57 -171
- data/lib/cmdx/context.rb +22 -165
- data/lib/cmdx/core_ext/hash.rb +42 -67
- data/lib/cmdx/core_ext/module.rb +35 -79
- data/lib/cmdx/core_ext/object.rb +63 -98
- data/lib/cmdx/correlator.rb +40 -156
- data/lib/cmdx/error.rb +37 -202
- data/lib/cmdx/errors.rb +165 -202
- data/lib/cmdx/fault.rb +55 -158
- data/lib/cmdx/faults.rb +26 -137
- data/lib/cmdx/immutator.rb +22 -109
- data/lib/cmdx/lazy_struct.rb +103 -187
- data/lib/cmdx/log_formatters/json.rb +14 -40
- data/lib/cmdx/log_formatters/key_value.rb +14 -40
- data/lib/cmdx/log_formatters/line.rb +14 -48
- data/lib/cmdx/log_formatters/logstash.rb +14 -57
- data/lib/cmdx/log_formatters/pretty_json.rb +14 -50
- data/lib/cmdx/log_formatters/pretty_key_value.rb +13 -46
- data/lib/cmdx/log_formatters/pretty_line.rb +16 -54
- data/lib/cmdx/log_formatters/raw.rb +19 -49
- data/lib/cmdx/logger.rb +20 -82
- data/lib/cmdx/logger_ansi.rb +18 -75
- data/lib/cmdx/logger_serializer.rb +24 -114
- data/lib/cmdx/middleware.rb +38 -60
- data/lib/cmdx/middleware_registry.rb +81 -77
- data/lib/cmdx/middlewares/correlate.rb +41 -226
- data/lib/cmdx/middlewares/timeout.rb +46 -185
- data/lib/cmdx/parameter.rb +120 -198
- data/lib/cmdx/parameter_evaluator.rb +231 -0
- data/lib/cmdx/parameter_inspector.rb +25 -56
- data/lib/cmdx/parameter_registry.rb +59 -84
- data/lib/cmdx/parameter_serializer.rb +23 -74
- data/lib/cmdx/railtie.rb +24 -107
- data/lib/cmdx/result.rb +254 -260
- data/lib/cmdx/result_ansi.rb +19 -85
- data/lib/cmdx/result_inspector.rb +27 -68
- data/lib/cmdx/result_logger.rb +18 -81
- data/lib/cmdx/result_serializer.rb +28 -132
- data/lib/cmdx/rspec/matchers.rb +28 -0
- data/lib/cmdx/rspec/result_matchers/be_executed.rb +42 -0
- data/lib/cmdx/rspec/result_matchers/be_failed_task.rb +94 -0
- data/lib/cmdx/rspec/result_matchers/be_skipped_task.rb +94 -0
- data/lib/cmdx/rspec/result_matchers/be_state_matchers.rb +59 -0
- data/lib/cmdx/rspec/result_matchers/be_status_matchers.rb +57 -0
- data/lib/cmdx/rspec/result_matchers/be_successful_task.rb +87 -0
- data/lib/cmdx/rspec/result_matchers/have_bad_outcome.rb +51 -0
- data/lib/cmdx/rspec/result_matchers/have_caused_failure.rb +58 -0
- data/lib/cmdx/rspec/result_matchers/have_chain_index.rb +59 -0
- data/lib/cmdx/rspec/result_matchers/have_context.rb +86 -0
- data/lib/cmdx/rspec/result_matchers/have_empty_metadata.rb +54 -0
- data/lib/cmdx/rspec/result_matchers/have_good_outcome.rb +52 -0
- data/lib/cmdx/rspec/result_matchers/have_metadata.rb +114 -0
- data/lib/cmdx/rspec/result_matchers/have_preserved_context.rb +66 -0
- data/lib/cmdx/rspec/result_matchers/have_received_thrown_failure.rb +64 -0
- data/lib/cmdx/rspec/result_matchers/have_runtime.rb +78 -0
- data/lib/cmdx/rspec/result_matchers/have_thrown_failure.rb +76 -0
- data/lib/cmdx/rspec/task_matchers/be_well_formed_task.rb +62 -0
- data/lib/cmdx/rspec/task_matchers/have_callback.rb +85 -0
- data/lib/cmdx/rspec/task_matchers/have_cmd_setting.rb +68 -0
- data/lib/cmdx/rspec/task_matchers/have_executed_callbacks.rb +92 -0
- data/lib/cmdx/rspec/task_matchers/have_middleware.rb +46 -0
- data/lib/cmdx/rspec/task_matchers/have_parameter.rb +181 -0
- data/lib/cmdx/task.rb +213 -425
- data/lib/cmdx/task_deprecator.rb +55 -0
- data/lib/cmdx/task_processor.rb +245 -0
- data/lib/cmdx/task_serializer.rb +22 -70
- data/lib/cmdx/utils/ansi_color.rb +13 -89
- data/lib/cmdx/utils/log_timestamp.rb +13 -42
- data/lib/cmdx/utils/monotonic_runtime.rb +13 -63
- data/lib/cmdx/utils/name_affix.rb +21 -71
- data/lib/cmdx/validator.rb +48 -0
- data/lib/cmdx/validator_registry.rb +86 -0
- data/lib/cmdx/validators/exclusion.rb +55 -94
- data/lib/cmdx/validators/format.rb +31 -85
- data/lib/cmdx/validators/inclusion.rb +65 -110
- data/lib/cmdx/validators/length.rb +117 -133
- data/lib/cmdx/validators/numeric.rb +123 -130
- data/lib/cmdx/validators/presence.rb +38 -79
- data/lib/cmdx/version.rb +1 -7
- data/lib/cmdx/workflow.rb +46 -339
- data/lib/cmdx.rb +1 -1
- data/lib/generators/cmdx/install_generator.rb +14 -31
- data/lib/generators/cmdx/task_generator.rb +39 -55
- data/lib/generators/cmdx/templates/install.rb +61 -11
- data/lib/generators/cmdx/workflow_generator.rb +41 -66
- data/lib/locales/ar.yml +35 -0
- data/lib/locales/cs.yml +35 -0
- data/lib/locales/da.yml +35 -0
- data/lib/locales/de.yml +35 -0
- data/lib/locales/el.yml +35 -0
- data/lib/locales/en.yml +19 -20
- data/lib/locales/es.yml +19 -20
- data/lib/locales/fi.yml +35 -0
- data/lib/locales/fr.yml +35 -0
- data/lib/locales/he.yml +35 -0
- data/lib/locales/hi.yml +35 -0
- data/lib/locales/it.yml +35 -0
- data/lib/locales/ja.yml +35 -0
- data/lib/locales/ko.yml +35 -0
- data/lib/locales/nl.yml +35 -0
- data/lib/locales/no.yml +35 -0
- data/lib/locales/pl.yml +35 -0
- data/lib/locales/pt.yml +35 -0
- data/lib/locales/ru.yml +35 -0
- data/lib/locales/sv.yml +35 -0
- data/lib/locales/th.yml +35 -0
- data/lib/locales/tr.yml +35 -0
- data/lib/locales/vi.yml +35 -0
- data/lib/locales/zh.yml +35 -0
- metadata +57 -8
- data/lib/cmdx/parameter_validator.rb +0 -81
- data/lib/cmdx/parameter_value.rb +0 -244
- data/lib/cmdx/parameters_inspector.rb +0 -72
- data/lib/cmdx/parameters_serializer.rb +0 -115
- data/lib/cmdx/rspec/result_matchers.rb +0 -917
- data/lib/cmdx/rspec/task_matchers.rb +0 -570
- 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
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
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
|
-
#
|
37
|
-
# The
|
38
|
-
#
|
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
|
47
|
-
#
|
48
|
-
#
|
49
|
-
#
|
50
|
-
#
|
51
|
-
#
|
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
|
-
#
|
64
|
-
#
|
65
|
-
#
|
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
|
46
|
+
# @return [String] the class name with "Task" suffix
|
68
47
|
#
|
69
|
-
# @example Class name
|
70
|
-
# #
|
71
|
-
# #
|
48
|
+
# @example Class name without suffix
|
49
|
+
# # Given name: "User"
|
50
|
+
# class_name # => "UserTask"
|
72
51
|
#
|
73
|
-
#
|
74
|
-
# #
|
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
|
83
|
-
#
|
84
|
-
# This allows applications to define
|
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
|
-
# @
|
70
|
+
# @example With ApplicationTask defined
|
71
|
+
# parent_class_name # => ApplicationTask
|
87
72
|
#
|
88
|
-
# @example
|
89
|
-
# #
|
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
|
-
#
|
5
|
-
|
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
|
-
#
|
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
|
-
#
|
10
|
-
#
|
11
|
-
|
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
|
14
|
-
#
|
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
|
-
#
|
17
|
-
# https://github.com/drexed/cmdx/
|
18
|
-
|
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
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
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
|
-
#
|
45
|
-
# name. The
|
46
|
-
#
|
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
|
-
# @
|
56
|
-
#
|
57
|
-
#
|
58
|
-
#
|
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
|
-
#
|
61
|
-
#
|
62
|
-
# #
|
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
|
-
#
|
75
|
-
#
|
76
|
-
#
|
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
|
48
|
+
# @return [String] the class name with "Workflow" suffix
|
79
49
|
#
|
80
|
-
# @example Class name
|
81
|
-
# #
|
82
|
-
# #
|
50
|
+
# @example Class name without suffix
|
51
|
+
# # Given name: "User"
|
52
|
+
# class_name # => "UserWorkflow"
|
83
53
|
#
|
84
|
-
#
|
85
|
-
# #
|
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
|
-
#
|
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
|
-
#
|
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
|
-
# @
|
72
|
+
# @example With ApplicationWorkflow defined
|
73
|
+
# parent_class_name # => ApplicationWorkflow
|
98
74
|
#
|
99
|
-
# @example
|
100
|
-
# #
|
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
|
data/lib/locales/ar.yml
ADDED
@@ -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: "لا يمكن أن يكون فارغاً"
|
data/lib/locales/cs.yml
ADDED
@@ -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ý"
|
data/lib/locales/da.yml
ADDED
@@ -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"
|
data/lib/locales/de.yml
ADDED
@@ -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"
|
data/lib/locales/el.yml
ADDED
@@ -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"
|