Skip to content

Using options in attributes

Option type input internal output

Validation option. Checks that the passed value matches the specified type (class) using is_a?.

Required. May contain one or more classes.

ruby
class NotificationsService::Create < ApplicationService::Base
  input :user, type: User
  input :need_to_notify, type: [TrueClass, FalseClass]

  # ...
end
ruby
class NotificationsService::Create < ApplicationService::Base
  # ...

  internal :inviter, type: User

  # ...
end
ruby
class NotificationsService::Create < ApplicationService::Base
  # ...

  output :notification, type: Notification

  # ...
end

Option required input

Validation option. Checks that the passed value is not empty using present?.

Defaults to true.

ruby
class UsersService::Create < ApplicationService::Base
  input :first_name,
        type: String

  input :middle_name,
        type: String,
        required: false

  input :last_name,
        type: String

  # ...
end

Option default input

Non-validation option. Assigns a value if none was passed to the service.

ruby
class UsersService::Create < ApplicationService::Base
  # ...

  input :middle_name,
        type: String,
        required: false,
        default: "<unknown>"

  # ...
end

Option as input

Non-validation option. Specifies an alias for the attribute within the service. The original name becomes unavailable inside the service.

ruby
class NotificationsService::Create < ApplicationService::Base
  input :user,
        as: :recipient,
        type: User

  # ...

  def create!
    outputs.notification =
      Notification.create!(recipient: inputs.recipient)
  end
end

Option inclusion input internal (^2.2.0) output (^2.2.0)

INFO

Since version 2.12.0 this option is dynamic.

Dynamic validation option. Checks that the passed value is in the specified array using include?.

ruby
class EventsService::Send < ApplicationService::Base
  input :event_name,
        type: String,
        inclusion: %w[created rejected approved]

  # ...
end
ruby
class EventsService::Send < ApplicationService::Base
  # ...

  internal :event_name,
           type: String,
           inclusion: %w[created rejected approved]

  # ...
end
ruby
class EventsService::Send < ApplicationService::Base
  # ...

  output :event_name,
         type: String,
         inclusion: %w[created rejected approved]

  # ...
end

Option consists_of input (^2.0.0) internal (^2.0.0) output (^2.0.0)

INFO

Since version 2.6.0 this option is dynamic.

Dynamic validation option. Checks that each value in the collection matches the specified type (class), including nested values, using is_a?.

Works only with Array and Set types. Add custom types via collection_mode_class_names configuration.

Optional. Defaults to String.

ruby
input :ids,
      type: Array,
      consists_of: String
ruby
internal :ids,
         type: Array,
         consists_of: String
ruby
output :ids,
       type: Array,
       consists_of: String

Option schema input (^2.0.0) internal (^2.0.0) output (^2.0.0)

INFO

Since version 2.12.0 this option is dynamic.

Dynamic validation option. Requires a hash value describing the attribute's value structure.

Works only with Hash type. Add custom types via hash_mode_class_names configuration.

Optional. If unspecified, validation is skipped. No default value.

ruby
input :payload,
      type: Hash,
      schema: {
        request_id: { type: String, required: true },
        user: {
          type: Hash,
          required: true,
          first_name: { type: String, required: true },
          middle_name: { type: String, required: false, default: "<unknown>" },
          last_name: { type: String, required: true },
          pass: {
            type: Hash,
            required: true,
            series: { type: String, required: true },
            number: { type: String, required: true }
          }
        }
      }
ruby
internal :payload,
         type: Hash,
         schema: {
           request_id: { type: String, required: true },
           user: {
             type: Hash,
             required: true,
             first_name: { type: String, required: true },
             middle_name: { type: String, required: false, default: "<unknown>" },
             last_name: { type: String, required: true },
             pass: {
               type: Hash,
               required: true,
               series: { type: String, required: true },
               number: { type: String, required: true }
             }
           }
         }
ruby
output :payload,
       type: Hash,
       schema: {
         request_id: { type: String, required: true },
         user: {
           type: Hash,
           required: true,
           first_name: { type: String, required: true },
           middle_name: { type: String, required: false, default: "<unknown>" },
           last_name: { type: String, required: true },
           pass: {
             type: Hash,
             required: true,
             series: { type: String, required: true },
             number: { type: String, required: true }
           }
         }
       }

Describe each expected hash key in this format:

ruby
{
  request_id: { type: String, required: true }
}

Allowed options: required type, required and optional default, prepare. The default and prepare options are only available within input.

If type specifies Hash, describe nesting in the same format.

Option must input internal (^2.2.0) output (^2.2.0)

Validation option. Create custom validations.

ruby
class PaymentsService::Create < ApplicationService::Base
  input :invoice_numbers,
        type: Array,
        consists_of: String,
        must: {
          be_6_characters: {
            is: ->(value:, input:) { value.all? { |id| id.size == 6 } }
          }
        }

  # ...
end
ruby
class EventsService::Send < ApplicationService::Base
  # ...

  internal :invoice_numbers,
           type: Array,
           consists_of: String,
           must: {
             be_6_characters: {
               is: ->(value:, internal:) { value.all? { |id| id.size == 6 } }
             }
           }

  # ...
end
ruby
class EventsService::Send < ApplicationService::Base
  # ...

  output :invoice_numbers,
         type: Array,
         consists_of: String,
         must: {
           be_6_characters: {
             is: ->(value:, output:) { value.all? { |id| id.size == 6 } }
           }
         }

  # ...
end

Option format input (^2.4.0) internal (^2.4.0) output (^2.4.0)

Dynamic validation option (not part of main options). See more.

Option max input (^2.4.0) internal (^2.4.0) output (^2.4.0)

Dynamic validation option (not part of main options). See more.

Option min input (^2.4.0) internal (^2.4.0) output (^2.4.0)

Dynamic validation option (not part of main options). See more.

Option prepare input

Non-validation option. Prepares the passed value.

WARNING

Use prepare carefully for simple preparatory actions only. Complex logic is better applied via make actions.

ruby
class PaymentsService::Create < ApplicationService::Base
  input :amount_cents,
        as: :amount,
        type: Integer,
        prepare: ->(value:) { Money.from_cents(value, :USD) }

  # ...

  def create!
    outputs.payment = Payment.create!(amount: inputs.amount)
  end
end