Module: Spikard::ProvideSupport

Included in:
App
Defined in:
lib/spikard/provide.rb

Overview

Dependency Injection support for Spikard applications

Provides methods for registering and managing dependencies that can be automatically injected into route handlers.

Examples:

Registering a value dependency

app.provide("database_url", "postgresql://localhost/mydb")

Registering a factory dependency

app.provide("db_pool", depends_on: ["database_url"]) do |database_url:|
  ConnectionPool.new(database_url)
end

Singleton dependency (shared across all requests)

app.provide("config", singleton: true) do
  Config.load_from_file("config.yml")
end

Using Provide wrapper

app.provide("db", Spikard::Provide.new(method("create_db"), cacheable: true))

Instance Method Summary collapse

Instance Method Details

#dependenciesHash

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Get all registered dependencies

Returns:

  • (Hash)

    Dictionary mapping dependency keys to their definitions



154
155
156
157
# File 'lib/spikard/provide.rb', line 154

def dependencies
  @dependencies ||= {}
  @dependencies.dup
end

#provide(key, value = nil, depends_on: [], singleton: false, cacheable: true) {|**deps| ... } ⇒ self

Register a dependency in the DI container

This method supports three patterns:

  1. **Value dependency**: Pass a value directly (e.g., string, number, object)

  2. **Factory dependency**: Pass a block that computes the value

  3. **Provide wrapper**: Pass a Spikard::Provide instance

rubocop:disable Metrics/MethodLength

Examples:

Value dependency

app.provide("app_name", "MyApp")
app.provide("port", 8080)

Factory with dependencies

app.provide("database", depends_on: ["config"]) do |config:|
  Database.connect(config["db_url"])
end

Singleton factory

app.provide("thread_pool", singleton: true) do
  ThreadPool.new(size: 10)
end

Non-cacheable factory (resolves every time)

app.provide("request_id", cacheable: false) do
  SecureRandom.uuid
end

Using Provide wrapper

app.provide("db", Spikard::Provide.new(method("create_db"), cacheable: true))

Parameters:

  • key (String, Symbol)

    Unique identifier for the dependency

  • value (Object, Provide, nil) (defaults to: nil)

    Static value, Provide instance, or nil

  • depends_on (Array<String, Symbol>) (defaults to: [])

    List of dependency keys this factory depends on

  • singleton (Boolean) (defaults to: false)

    Whether to cache the value globally (default: false)

  • cacheable (Boolean) (defaults to: true)

    Whether to cache the value per-request (default: true)

Yields:

  • Optional factory block that receives dependencies as keyword arguments

Yield Parameters:

  • **deps (Hash)

    Resolved dependencies as keyword arguments

Yield Returns:

  • (Object)

    The computed dependency value

Returns:

  • (self)

    Returns self for method chaining



111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/spikard/provide.rb', line 111

def provide(key, value = nil, depends_on: [], singleton: false, cacheable: true, &block)
  key_str = key.to_s
  @dependencies ||= {}

  # Handle Provide wrapper instances
  if value.is_a?(Provide)
    provider = value
    @dependencies[key_str] = {
      type: :factory,
      factory: provider.factory,
      depends_on: provider.depends_on,
      singleton: provider.singleton,
      cacheable: provider.cacheable
    }
  elsif block
    # Factory dependency (block form)
    @dependencies[key_str] = {
      type: :factory,
      factory: block,
      depends_on: Array(depends_on).map(&:to_s),
      singleton: singleton,
      cacheable: cacheable
    }
  else
    # Value dependency
    raise ArgumentError, 'Either provide a value or a block, not both' if value.nil?

    @dependencies[key_str] = {
      type: :value,
      value: value,
      singleton: true, # Values are always singleton
      cacheable: true
    }
  end

  self
end