What is an organizer service?
An organizer service composes other services (or methods) via
steps. If any step is not successful, the pipeline stops and that step's result is returned as the whole service's result.class AssertFileExists include ConvenientService::Standard::Config attr_reader :path def initialize(path:) @path = path end def result return failure("File does not exist at path `#{path}`") unless File.exist?(path) success end end class AssertFileNotEmpty include ConvenientService::Standard::Config attr_reader :path def initialize(path:) @path = path end def result return failure("File is empty at path `#{path}`") if File.empty?(path) success end end class ReadFileContent include ConvenientService::Standard::Config step AssertFileExists, in: :path step AssertFileNotEmpty, in: :path step :result, in: :path, out: :content attr_reader :path def initialize(path:) @path = path end def result success(content: File.read(path)) end endIf
AssertFileExistsfails, the pipeline stops there -AssertFileNotEmptyandstep :resultnever run.result = ReadFileContent.result(path: "/tmp/non_existent.txt") result.success? # => false result.original_service.class # => AssertFileExistsThe same applies to
AssertFileNotEmpty- when it fails,step :resultis skipped.File.write("/tmp/empty.txt", "") result = ReadFileContent.result(path: "/tmp/empty.txt") result.success? # => false result.original_service.class # => AssertFileNotEmptyWhen every step succeeds,
ReadFileContentreturns the finalstep :resultresult.File.write("/tmp/hello.txt", "Hello!") result = ReadFileContent.result(path: "/tmp/hello.txt") result.success? # => true result.data[:content] # => "Hello!"An organizer service is contrasted with a regular service, which implements
resultdirectly instead of composing steps.