Servactory

website·Indexed 32 days ago

https://servactory.com

A framework for building services, featuring Datory for data mapping and serialization/deserialization, and Featury for feature flags and feature objects. It includes support for Rails generators, custom extensions, internationalization (I18n), and advanced operating modes for service execution.

Tokens
23.4K
Snippets
145
Records
188
Agent score
53%

What's inside Servactory

  1. Overview of Servactory Extensions

    Extensions allow developers to expand base service functionality using the Stroma hook system. They enable the definition of custom behavior that runs before or after specific service execution stages. Extensions are typically located in the app/services/application_service/extensions directory.
  2. Overview of Servactory Dynamic Options

    Dynamic options are must-based options that accept values as arguments for validating service attributes. They differ from custom helpers in that they specifically work with arguments.

    By default, consists_of, inclusion, and schema are enabled. Other dynamic options must be enabled via the option helpers configuration for each attribute.

  3. Retrieve metadata for a Featury object using the info method

    The info method allows you to obtain detailed information about a specific Featury object, including its associated feature flags, groups, and the structural tree of flags for that class.
    # Get the info object for a specific feature class
    info = User::OnboardingFeature.info
    
    # Access feature flags of the current class
    puts info.features
    
    # Access feature flag groups of the current class
    puts info.groups
    
    # Access the tree of feature flags from the current class
    puts info.tree
  4. Benefits of using Servactory for Ruby/Rails services

    Servactory addresses the inconsistency often found in Ruby service implementations by enforcing a consistent API and logic structure. This unified approach simplifies development, makes services easier to understand, and ensures consistent testing patterns, as services are tested like standard Ruby classes.
  5. Implement service customization using Stroma hooks

    The Stroma library core now manages modules, hooks, and extensions. It introduces a before and after hook system that allows for service customization and utilizes a hierarchical module settings storage to prevent shared state between parent and child classes.
  6. Define a feature object with Featury

    A feature object in Featury is used to manage one or more feature flags. It can include a prefix for flag naming, required or optional resources, and operational conditions.
    class User::OnboardingFeature < ApplicationFeature
      prefix :onboarding
      resource :user, type: User
      condition ->(resources:) { resources.user.onboarding_awaiting? }
      features :passage
    end
  7. Handle service call results using ApplicationService::Result

    Every service call using the .call method returns an ApplicationService::Result object. This object indicates whether the operation was successful or failed (expected problems triggered via fail! do not throw exceptions). On success, the result contains the output attributes. On failure, it contains an error attribute with the failure description.
    service_result = Users::Accept.call(user: User.first)
    
    if service_result.success?
      # Handle success
    else
      puts service_result.error
    end
  8. Test services with the redesigned RSpec Test Kit

    The RSpec Test Kit has been redesigned with a modular Registry DSL architecture. It now features a Fluent API for service mocking and supports cross-service exception handling.
  9. Verify service definitions with have_input matcher

    The have_input matcher allows you to verify the configuration of a service's input parameters, including their type, requirement status, default values, and allowed inclusions.
    # Verify type and requirement
    expect { perform }.to(have_input(:email).type(String).required)
    
    # Verify optional input with default
    expect { perform }.to(have_input(:middle_name).type(String).optional.default("<unknown>"))
    
    # Verify collection types
    expect { perform }.to(have_input(:ids).type(Array).required.consists_of(String))
    
    # Verify allowed values (inclusion)
    expect { perform }.to(have_input(:event_name).type(String).required.inclusion(%w[created rejected approved]))
  10. Use Servactory Rails generators for setup and creation

    Servactory 3.0 introduces and improves several Rails generators to streamline installation and component creation, supporting Rails versions 5.1 through 8.1 with custom path support and type normalization.
    # Install and setup Servactory
    rails generate servactory:install
    
    # Create a service with inputs and typing support
    rails generate servactory:service ServiceName
    
    # Create RSpec tests for a service
    rails generate servactory:rspec ServiceName
    
    # Create a new extension
    rails generate servactory:extension ExtensionName
  11. Prepare data for Datory serialization

    Datory can serialize data from various sources, including DTO instances or ActiveRecord models.
    # Using a DTO instance
    serial = SerialDto.new(attributes)
    
    # Using an ActiveRecord model
    serial = Serial.find(id)