Dynamic options Since 2.4.0
Dynamic options are additional must
-based options that can take values as arguments. Dynamic options are similar to custom helpers, but what sets them apart is their ability to work with arguments.
Servactory out of the box provides the following set of dynamic options:
consists_of
;format
;min
;max
;multiple_of
.
By default, only the consists_of
option is enabled. For the rest to work, you need to use ready-made sets in the configuration of option helpers for each of the existing attributes.
Ready-made options
Option consists_of
Since 2.6.0
- Kit:
Servactory::ToolKit::DynamicOptions::ConsistsOf
- Based on:
must
- Enabled by default: Yes
- Source code
Option format
- Kit:
Servactory::ToolKit::DynamicOptions::Format
- Based on:
must
- Enabled by default: No
- Source code
Supported formats
uuid
;email
;password
;duration
;date
;time
;datetime
;boolean
.
Customization
You can overwrite existing formats and add your own. To do this, use the formats
attribute in the use
method:
Servactory::ToolKit::DynamicOptions::Format.use(
formats: {
email: {
pattern: /@/,
validator: ->(value:) { value.present? }
}
}
)
Installation and usage
input_option_helpers([
Servactory::ToolKit::DynamicOptions::Min.use
])
internal_option_helpers([
Servactory::ToolKit::DynamicOptions::Min.use(:minimum)
])
output_option_helpers([
Servactory::ToolKit::DynamicOptions::Min.use
])
input :email,
type: String,
format: :email
internal :email,
type: String,
format: { is: :email }
output :data,
type: String,
format: {
is: :email,
message: lambda do |output:, value:, option_value:, **|
"Incorrect `email` format in `#{output.name}`"
end
}
Option min
- Kit:
Servactory::ToolKit::DynamicOptions::Min
- Based on:
must
- Enabled by default: No
- Source code
Installation and usage
input_option_helpers([
Servactory::ToolKit::DynamicOptions::Min.use
])
internal_option_helpers([
Servactory::ToolKit::DynamicOptions::Min.use(:minimum)
])
output_option_helpers([
Servactory::ToolKit::DynamicOptions::Min.use
])
input :data,
type: Integer,
min: 1
internal :data,
type: String,
minimum: { is: 1 }
output :data,
type: Array,
min: {
is: 1,
message: lambda do |output:, value:, option_value:, **|
"The size of the `#{output.name}` value must be greater than or " \
"equal to `#{option_value}` (got: `#{value}`)"
end
}
Option max
- Kit:
Servactory::ToolKit::DynamicOptions::Max
- Based on:
must
- Enabled by default: No
- Source code
Installation and usage
input_option_helpers([
Servactory::ToolKit::DynamicOptions::Max.use
])
internal_option_helpers([
Servactory::ToolKit::DynamicOptions::Max.use(:maximum)
])
output_option_helpers([
Servactory::ToolKit::DynamicOptions::Max.use
])
input :data,
type: Integer,
max: 10
internal :data,
type: String,
maximum: { is: 10 }
output :data,
type: Array,
max: {
is: 10,
message: lambda do |output:, value:, option_value:, **|
"The size of the `#{output.name}` value must be less than or " \
"equal to `#{option_value}` (got: `#{value}`)"
end
}
Option multiple_of
- Kit:
Servactory::ToolKit::DynamicOptions::MultipleOf
- Based on:
must
- Enabled by default: No
- Source code
Installation and usage
input_option_helpers([
Servactory::ToolKit::DynamicOptions::MultipleOf.use
])
internal_option_helpers([
Servactory::ToolKit::DynamicOptions::MultipleOf.use(:divisible_by)
])
output_option_helpers([
Servactory::ToolKit::DynamicOptions::MultipleOf.use
])
input :data,
type: Integer,
multiple_of: 2
internal :data,
type: Integer,
divisible_by: { is: 2 }
output :data,
type: Float,
multiple_of: {
is: 2,
message: lambda do |output:, value:, option_value:, **|
"Output `#{output.name}` has the value `#{value}`, " \
"which is not a multiple of `#{option_value}`"
end
}
Custom options
You can create your own dynamic options.
Use the prepared template provided below to implement your own dynamic option.
It is recommended to place the class file in the app/services/application_service/dynamic_options
directory of your project.
Template
module ApplicationService
module DynamicOptions
class MyOption < Servactory::ToolKit::DynamicOptions::Must
def self.use(option_name = :my_option, **options)
new(option_name).must(:be_the_best)
end
def condition_for_input_with(input:, value:, option:)
# There should be conditions here that are intended for the input attribute
end
def condition_for_internal_with(internal:, value:, option:)
# There should be conditions here that are intended for the internal attribute
end
def condition_for_output_with(output:, value:, option:)
# There should be conditions here that are intended for the output attribute
end
def message_for_input_with(service:, input:, value:, option_value:, **)
# There should be a message text here in case the condition is not met
end
def message_for_internal_with(service:, internal:, value:, option_value:, **)
# There should be a message text here in case the condition is not met
end
def message_for_output_with(service:, output:, value:, option_value:, **)
# There should be a message text here in case the condition is not met
end
end
end
end
Application
input_option_helpers([
ApplicationService::DynamicOptions::MyOption.use
])
internal_option_helpers([
ApplicationService::DynamicOptions::MyOption.use(:my_best_option)
])
output_option_helpers([
ApplicationService::DynamicOptions::MyOption.use(some: :data)
])