Class: Serviced::Service
- Inherits:
-
Object
- Object
- Serviced::Service
- Includes:
- ResultHelpers, Typed
- Defined in:
- lib/serviced/service.rb
Overview
Base class for service objects.
A service declares its inputs as typed attributes (see Typed), which are coerced on assignment and read-only afterwards. Inputs can be validated with the full ActiveModel validation DSL. Calling a service always returns a Result.
class CreatePatient < Serviced::Service
attribute :name, :string
attribute :age, :integer
attribute :active, :boolean, default: true
attribute :clinic # untyped: accepts any object
validates :name, presence: true
validates :age, numericality: { greater_than: 0 }
def call
patient = Patient.create!(name:, age:, active:)
success(patient)
rescue ActiveRecord::RecordInvalid => e
failure(:not_created, e., error: e)
end
end
result = CreatePatient.call(name: "Ada", age: 36)
result.success? # => true
result.value # => #<Patient ...>
Invalid inputs short-circuit to failure(:invalid) without running #call,
exposing the ActiveModel::Errors object through result.error.
Class Method Summary collapse
-
.call(attributes = {}) ⇒ Serviced::Result
Builds the service, validates it, and runs #call.
Instance Method Summary collapse
-
#call ⇒ Serviced::Result
The business logic.
Methods included from Typed
Class Method Details
.call(attributes = {}) ⇒ Serviced::Result
Builds the service, validates it, and runs #call.
Unknown keys are ignored so a service can be dropped into a Flow without matching the exact shape of the flow context.
47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/serviced/service.rb', line 47 def call(attributes = {}) service = new(attributes) return service.__send__(:invalid_result) if service.invalid? result = service.call unless result.is_a?(Result) raise ResultTypeError, "#{self}#call must return a Serviced::Result, got #{result.class}" end result end |
Instance Method Details
#call ⇒ Serviced::Result
The business logic. Subclasses must implement it and return a
Result (use the success / failure helpers).
63 64 65 |
# File 'lib/serviced/service.rb', line 63 def call raise NotImplementedError, "#{self.class} must implement #call" end |