Class: Servactory::ToolKit::DynamicOptions::Inclusion

Inherits:
Must
  • Object
show all
Defined in:
lib/servactory/tool_kit/dynamic_options/inclusion.rb

Overview

Validates that attribute value is included in a specified set.

## Purpose

Inclusion provides set membership validation for attributes. It ensures that the value is present within a predefined list of acceptable values. This is similar to ActiveModel’s inclusion validation and is useful for enum-like constraints.

## Usage

This option is **included by default** for inputs, internals, and outputs. No registration required.

Use in your service definition:

“‘ruby class CreateUserService < ApplicationService::Base

input :role, type: String, inclusion: { in: %w[admin user guest] }
input :status, type: Symbol, inclusion: { in: [:active, :inactive] }
input :level, type: Integer, inclusion: { in: [1, 2, 3, 4, 5] }

end “‘

## Simple Mode

Specify inclusion values directly:

“‘ruby class CreateUserService < ApplicationService::Base

input :role, type: String, inclusion: %w[admin user guest]
input :status, type: Symbol, inclusion: [:active, :inactive]
input :level, type: Integer, inclusion: 1..10

end “‘

## Advanced Mode

Specify inclusion with custom error message using a hash. Note: Advanced mode uses ‘:in` key (not `:is`).

With static message:

“‘ruby input :role, type: String, inclusion:

in: %w[admin user guest],
message: "Input `role` must be one of: admin, user, guest"

“‘

With dynamic lambda message:

“‘ruby input :role, type: String, inclusion:

in: %w[admin user guest],
message: lambda do |input:, value:, option_value:, **|
  "Input `#{input.name` has invalid value `#value`, allowed: #')"
end

} “‘

Lambda receives the following parameters:

  • For inputs: ‘input:, value:, option_value:, reason:, **`

  • For internals: ‘internal:, value:, option_value:, reason:, **`

  • For outputs: ‘output:, value:, option_value:, reason:, **`

## Validation Rules

  • Value must be present in the inclusion list

  • Supports arrays as inclusion sets

  • Optional inputs with nil value validate against default

  • Returns ‘:invalid_option` error if inclusion set is nil

## Important Notes

  • Use ‘inclusion: { in: […] }` syntax for specifying allowed values

  • Single values are automatically wrapped in an array

  • For optional inputs with nil value, validates default if present

  • Range objects ARE supported natively: ‘(1..10)`, `(1..)`, `(..100)`

  • Mixed syntax supported: ‘[1..5, 10, 15..20]` checks value against all elements

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Must

#equivalent_with, #initialize, #must, #must_content_message_with, #must_content_value_with, #must_content_with

Constructor Details

This class inherits a constructor from Servactory::ToolKit::DynamicOptions::Must

Class Method Details

.use(option_name = :inclusion) ⇒ Servactory::Maintenance::Attributes::OptionHelper

Creates an Inclusion validator instance.

Parameters:

  • option_name (Symbol) (defaults to: :inclusion)

    The option name (default: :inclusion)

Returns:



91
92
93
94
# File 'lib/servactory/tool_kit/dynamic_options/inclusion.rb', line 91

def self.use(option_name = :inclusion)
  instance = new(option_name, :in)
  instance.must(:be_inclusion)
end

Instance Method Details

#condition_for_input_with(input:, value:, option:) ⇒ Boolean, Array

Validates inclusion condition for input attribute.

Parameters:

  • input (Object)

    Input attribute object

  • value (Object)

    Value to validate

  • option (WorkOption)

    Inclusion configuration

Returns:

  • (Boolean, Array)

    true if valid, or [false, reason]



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/servactory/tool_kit/dynamic_options/inclusion.rb', line 102

def condition_for_input_with(input:, value:, option:) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
  return [false, :invalid_option] if option.value.nil?

  inclusion_values = normalize_inclusion_values(option.value)

  # Required inputs or optional with non-nil value.
  if input.required? || (input.optional? && !value.nil?) # rubocop:disable Style/IfUnlessModifier
    return value_in_inclusion?(inclusion_values, value)
  end

  # Optional with nil value but has default.
  if input.optional? && value.nil? && !input.default.nil?
    return value_in_inclusion?(inclusion_values, input.default)
  end

  true
end

#condition_for_internal_with(value:, option:) ⇒ Boolean, Array

Validates inclusion condition for internal attribute.

Parameters:

  • value (Object)

    Value to validate

  • option (WorkOption)

    Inclusion configuration

Returns:

  • (Boolean, Array)

    true if valid, or [false, reason]



125
126
127
128
129
130
# File 'lib/servactory/tool_kit/dynamic_options/inclusion.rb', line 125

def condition_for_internal_with(value:, option:, **)
  return [false, :invalid_option] if option.value.nil?

  inclusion_values = normalize_inclusion_values(option.value)
  value_in_inclusion?(inclusion_values, value)
end

#condition_for_output_with(value:, option:) ⇒ Boolean, Array

Validates inclusion condition for output attribute.

Parameters:

  • value (Object)

    Value to validate

  • option (WorkOption)

    Inclusion configuration

Returns:

  • (Boolean, Array)

    true if valid, or [false, reason]



137
138
139
140
141
142
# File 'lib/servactory/tool_kit/dynamic_options/inclusion.rb', line 137

def condition_for_output_with(value:, option:, **)
  return [false, :invalid_option] if option.value.nil?

  inclusion_values = normalize_inclusion_values(option.value)
  value_in_inclusion?(inclusion_values, value)
end

#message_for_input_with(service:, input:, value:, option_name:, option_value:, reason:) ⇒ String

Generates error message for input validation failure.

Parameters:

  • service (Object)

    Service context

  • input (Object)

    Input attribute

  • value (Object)

    Failed value

  • option_name (Symbol)

    Option name

  • option_value (Object)

    Allowed values

  • reason (Symbol)

    Failure reason

Returns:

  • (String)

    Localized error message



155
156
157
158
159
160
161
162
163
164
165
166
# File 'lib/servactory/tool_kit/dynamic_options/inclusion.rb', line 155

def message_for_input_with(service:, input:, value:, option_name:, option_value:, reason:, **)
  i18n_key = "inputs.validations.must.dynamic_options.inclusion"
  i18n_key += reason.present? ? ".#{reason}" : ".default"

  service.translate(
    i18n_key,
    input_name: input.name,
    value: value.inspect,
    input_inclusion: option_value.inspect,
    option_name:
  )
end

#message_for_internal_with(service:, internal:, value:, option_name:, option_value:, reason:) ⇒ String

Generates error message for internal validation failure.

Parameters:

  • service (Object)

    Service context

  • internal (Object)

    Internal attribute

  • value (Object)

    Failed value

  • option_name (Symbol)

    Option name

  • option_value (Object)

    Allowed values

  • reason (Symbol)

    Failure reason

Returns:

  • (String)

    Localized error message



177
178
179
180
181
182
183
184
185
186
187
188
# File 'lib/servactory/tool_kit/dynamic_options/inclusion.rb', line 177

def message_for_internal_with(service:, internal:, value:, option_name:, option_value:, reason:, **)
  i18n_key = "internals.validations.must.dynamic_options.inclusion"
  i18n_key += reason.present? ? ".#{reason}" : ".default"

  service.translate(
    i18n_key,
    internal_name: internal.name,
    value: value.inspect,
    internal_inclusion: option_value.inspect,
    option_name:
  )
end

#message_for_output_with(service:, output:, value:, option_name:, option_value:, reason:) ⇒ String

Generates error message for output validation failure.

Parameters:

  • service (Object)

    Service context

  • output (Object)

    Output attribute

  • value (Object)

    Failed value

  • option_name (Symbol)

    Option name

  • option_value (Object)

    Allowed values

  • reason (Symbol)

    Failure reason

Returns:

  • (String)

    Localized error message



199
200
201
202
203
204
205
206
207
208
209
210
# File 'lib/servactory/tool_kit/dynamic_options/inclusion.rb', line 199

def message_for_output_with(service:, output:, value:, option_name:, option_value:, reason:, **)
  i18n_key = "outputs.validations.must.dynamic_options.inclusion"
  i18n_key += reason.present? ? ".#{reason}" : ".default"

  service.translate(
    i18n_key,
    output_name: output.name,
    value: value.inspect,
    output_inclusion: option_value.inspect,
    option_name:
  )
end