dry-auto_inject

repository·main·Indexed 41 days ago

https://github.com/dry-rb/dry-auto_inject

A Ruby library for dependency injection that allows developers to decouple components by injecting dependencies rather than hardcoding them. It includes a Builder class for creating specialized Injector instances, a DependencyMap for managing registrations, and RuboCop cops to enforce dependency ordering and remove redundant aliases.

Tokens
1.2K
Snippets
5
Records
6
Agent score
49%

What's inside dry-auto_inject

  1. Avoid redundant dependency aliases in dry-auto_inject

    main

    When using dry-auto_inject, you do not need to provide a hash key if that key is identical to the last segment of the dependency path. dry-auto_inject automatically derives the dependency name from the last segment of the path. Using a redundant alias triggers a RuboCop offense via RuboCop::Cop::DryAutoInject::RedundantAlias.

    To fix this, remove the explicit alias and pass the path as a string (or a symbol representing the path) instead of a hash.

    # bad
    include Import[foo: 'some.path.foo']
    
    # good
    include Import['some.path.foo']
  2. Configure dependency order for Dry::AutoInject with RuboCop

    main

    The DryAutoInject/DependencyOrder RuboCop cop enforces a specific order for Import[...] dependencies. It ensures that non-aliased dependencies are emitted before aliased ones, and within those groups, dependencies are organized according to a configurable Order in your .rubocop.yml.

    Ordering Logic

    1. Non-aliased vs Aliased: Non-aliased dependencies are always placed first, followed by aliased dependencies.
    2. Pattern Matching: Within each section, dependencies are grouped by matching the Order patterns and then sorted alphabetically within those groups.
    3. Pattern Types:
      • '*' — A catch-all pattern (at most one allowed; if omitted, one is implicitly appended).
      • 'prefix.*' — A prefix wildcard (matches prefix and prefix.*).
      • '/regex/flags' — A regular expression matched against the dependency path.
      • otherwise — An exact path match.
    4. Priority: Specific patterns (exact matches, regex, or prefixes) take priority over the * catch-all, regardless of their position in the Order array.

    Configuration Example

    To use this cop, add it to your .rubocop.yml and define the Order key:

    DryAutoInject/DependencyOrder:
      Order:
        - 'web.*'
        - 'core.*'
        - '*'
    DryAutoInject/DependencyOrder:
      Order:
        - 'web.*'
        - 'core.*'
        - '*'
  3. Handle dependency name and duplication errors

    main

    When working with Dry::AutoInject::DependencyMap, you may encounter two specific error classes if dependency registration fails:

    • Dry::AutoInject::DependencyNameInvalid: Raised when a dependency identifier does not match the required naming pattern (it must end with a valid Ruby identifier matching /([a-z_][a-zA-Z_0-9]*)$/).
    • Dry::AutoInject::DuplicateDependencyError: Raised when attempting to register a dependency name that is already present in the map.
  4. Use the [] method to create a default injector

    main

    The [] method on a Dry::AutoInject::Builder instance is a shortcut to create an injector using the default strategy. It accepts a variable number of dependency names as arguments.

    Calling builder[*dependency_names] is equivalent to calling builder.default(*dependency_names).

    # Creates an injector using the default strategy for the specified dependencies
    injector = builder[:dependency_one, :dependency_two]
  5. Create an injector using the Builder class

    main

    The Dry::AutoInject::Builder is used to create specialized Injector instances based on different injection strategies. You initialize a Builder with a container (the dependency registry) and an optional set of strategies.

    Once initialized, you can create an injector by calling a method on the builder that matches the name of a registered strategy. For example, if a strategy named :hash is registered, calling builder.hash will return a new Injector configured with that strategy.

    # Assuming 'container' is your dependency container
    # and 'strategies' is a mapping of strategy names to strategy objects
    builder = Dry::AutoInject::Builder.new(container, strategies: strategies)
    
    # If 'hash' is a key in your strategies hash, this returns an Injector
    hash_injector = builder.hash
  6. Reference: DryAutoInject/DependencyOrder Order patterns

    main

    When configuring the Order array for the DryAutoInject/DependencyOrder cop, you can use the following pattern types to group your dependencies:

    - `'*'`              — catch-all (at most one; implicitly appended)
    - `'prefix.*'`       — prefix wildcard (matches `prefix` and `prefix.*`)
    - `'/regex/flags'`       — regex matched against the dep path
    - otherwise          — exact path match