Skip to content

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:

ruby
Servactory::ToolKit::DynamicOptions::Format.use(
  formats: {
    email: {
      pattern: /@/,
      validator: ->(value:) { value.present? }
    }
  }
)

Installation and usage

ruby
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
])
ruby
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

ruby
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
])
ruby
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

ruby
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
])
ruby
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

ruby
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
])
ruby
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

ruby
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

ruby
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)
])