Class: SenroUsecaser::Provider

Inherits:
Object
  • Object
show all
Defined in:
lib/senro_usecaser/provider.rb

Overview

Base class for dependency providers

Providers allow organizing dependency registrations across multiple files. Each provider is responsible for registering a group of related dependencies.

Examples:

Basic provider

class UserProvider < SenroUsecaser::Provider
  def register(container)
    container.register(:user_repository, UserRepository.new)
    container.register_singleton(:user_service) do |c|
      UserService.new(repo: c.resolve(:user_repository))
    end
  end
end

Provider with namespace

class AdminProvider < SenroUsecaser::Provider
  namespace :admin

  def register(container)
    container.register(:user_repository, AdminUserRepository.new)
  end
end

Provider with dependencies

class PersistenceProvider < SenroUsecaser::Provider
  depends_on CoreProvider

  def register(container)
    container.register(:database, Database.connect)
  end
end

Conditional provider

class DevelopmentProvider < SenroUsecaser::Provider
  enabled_if { SenroUsecaser.env.development? }
end

Class Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Class Attribute Details

.provider_namespace ⇒ Object (readonly)

@rbs! def self.provider_namespace: () -> (Symbol | String)?



107
108
109
# File 'lib/senro_usecaser/provider.rb', line 107

def provider_namespace
  @provider_namespace
end

Class Method Details

.call(container) ⇒ Object

Registers this provider's dependencies to the given container

: (Container) -> void



112
113
114
# File 'lib/senro_usecaser/provider.rb', line 112

def call(container)
  new.register_to(container)
end

.depends_on(*provider_classes) ⇒ Object

Declares dependencies on other providers

: (*singleton(Provider)) -> void

Examples:

class PersistenceProvider < SenroUsecaser::Provider
  depends_on CoreProvider
  depends_on ConfigProvider
end


55
56
57
58
59
# File 'lib/senro_usecaser/provider.rb', line 55

def depends_on(*provider_classes)
  provider_classes.each do |klass|
    provider_dependencies << klass unless provider_dependencies.include?(klass)
  end
end

.enabled? ⇒ Boolean

Returns whether this provider is enabled

: () -> bool

Returns:

  • (Boolean)


83
84
85
86
87
# File 'lib/senro_usecaser/provider.rb', line 83

def enabled?
  return true unless @enabled_condition

  @enabled_condition.call
end

.enabled_if(&block) ⇒ Object

Sets a condition for enabling this provider

: () { () -> boolish } -> void

Examples:

class DevelopmentProvider < SenroUsecaser::Provider
  enabled_if { Rails.env.development? }
end


76
77
78
# File 'lib/senro_usecaser/provider.rb', line 76

def enabled_if(&block)
  @enabled_condition = block
end

.namespace(name = nil) ⇒ Object

Sets the namespace for this provider's registrations

: ((Symbol | String)) -> void

Examples:

class AdminProvider < SenroUsecaser::Provider
  namespace :admin
end


97
98
99
100
101
102
103
# File 'lib/senro_usecaser/provider.rb', line 97

def namespace(name = nil)
  if name
    @provider_namespace = name
  else
    @provider_namespace
  end
end

.provider_dependencies ⇒ Object

Returns the list of provider dependencies

: () -> Array



64
65
66
# File 'lib/senro_usecaser/provider.rb', line 64

def provider_dependencies
  @provider_dependencies ||= [] #: Array[singleton(Provider)]
end

Instance Method Details

#after_boot(container) ⇒ Object

Called after all providers are registered. Override in subclasses.

: (Container) -> void

Examples:

def after_boot(container)
  container.resolve(:database).verify_connection!
end


200
# File 'lib/senro_usecaser/provider.rb', line 200

def after_boot(container); end

#before_register(container) ⇒ Object

Called before register. Override in subclasses.

: (Container) -> void

Examples:

def before_register(container)
  # Setup work
end


178
# File 'lib/senro_usecaser/provider.rb', line 178

def before_register(container); end

#effective_namespace ⇒ Object

Returns the effective namespace for this provider Uses explicitly declared namespace, or infers from module structure if configured

: () -> (Symbol | String)?



137
138
139
140
141
142
143
144
145
# File 'lib/senro_usecaser/provider.rb', line 137

def effective_namespace
  # Explicit namespace takes precedence
  return self.class.provider_namespace if self.class.provider_namespace

  # Infer from module structure if enabled
  return nil unless SenroUsecaser.configuration.infer_namespace_from_module

  infer_namespace_from_class
end

#infer_namespace_from_class ⇒ Object

Infers namespace from the class's module structure

: () -> String?

Examples:

Admin::UserProvider => "admin"
Admin::Reports::ReportProvider => "admin::reports"
CoreProvider => nil


155
156
157
158
159
160
161
162
163
164
165
166
167
168
# File 'lib/senro_usecaser/provider.rb', line 155

def infer_namespace_from_class
  class_name = self.class.name
  return nil unless class_name

  parts = class_name.split("::")
  return nil if parts.length <= 1

  # Remove the class name itself, keep only module parts
  module_parts = parts[0...-1] || [] #: Array[String]
  return nil if module_parts.empty?

  # Convert to lowercase namespace format (Admin::Reports => "admin::reports")
  module_parts.map { |part| part.gsub(/([a-z])([A-Z])/, '\1_\2').downcase }.join("::")
end

#register(container) ⇒ Object

Override this method to register dependencies

: (Container) -> void

Examples:

def register(container)
  container.register(:logger, Logger.new)
end

Raises:

  • (NotImplementedError)


188
189
190
# File 'lib/senro_usecaser/provider.rb', line 188

def register(container)
  raise NotImplementedError, "#{self.class.name}#register must be implemented"
end

#register_to(container) ⇒ Object

Registers dependencies to the container, wrapped in namespace if declared

: (Container) -> void



120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/senro_usecaser/provider.rb', line 120

def register_to(container)
  before_register(container)

  ns = effective_namespace
  if ns
    # Capture self to call provider's register method within namespace context
    provider = self
    container.namespace(ns) { provider.register(container) }
  else
    register(container)
  end
end

#shutdown(container) ⇒ Object

Called on application shutdown. Override in subclasses.

: (Container) -> void

Examples:

def shutdown(container)
  container.resolve(:database).disconnect
end


210
# File 'lib/senro_usecaser/provider.rb', line 210

def shutdown(container); end