Class: Dry::System::Component

Inherits:
Object
  • Object
show all
Defined in:
lib/dry/system/component.rb

Overview

Components are objects providing information about auto-registered files. They expose an API to query this information and use a configurable loader object to initialize class instances.

Components are created automatically through auto-registration and can be accessed through Container.auto_register! which yields them.

Constant Summary collapse

DEFAULT_OPTIONS =
{ separator: DEFAULT_SEPARATOR, namespace: nil }.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(identifier, path, options) ⇒ Component

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.

Returns a new instance of Component.



85
86
87
88
89
90
91
# File 'lib/dry/system/component.rb', line 85

def initialize(identifier, path, options)
  @identifier, @path = identifier, path
  @options = options
  @file = "#{path}.rb".freeze
  @loader = options.fetch(:loader)
  freeze
end

Instance Attribute Details

#fileObject (readonly)



33
34
35
# File 'lib/dry/system/component.rb', line 33

def file
  @file
end

#identifierObject (readonly)



25
26
27
# File 'lib/dry/system/component.rb', line 25

def identifier
  @identifier
end

#loaderObject (readonly)



41
42
43
# File 'lib/dry/system/component.rb', line 41

def loader
  @loader
end

#optionsObject (readonly)



37
38
39
# File 'lib/dry/system/component.rb', line 37

def options
  @options
end

#pathObject (readonly)



29
30
31
# File 'lib/dry/system/component.rb', line 29

def path
  @path
end

Class Method Details

.cacheObject

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.



80
81
82
# File 'lib/dry/system/component.rb', line 80

def self.cache
  @cache ||= Concurrent::Map.new
end

.ensure_valid_identifier(name, ns_name, sep) ⇒ Object

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.



69
70
71
72
73
74
75
76
77
# File 'lib/dry/system/component.rb', line 69

def self.ensure_valid_identifier(name, ns_name, sep)
  keys = name.to_s.scan(WORD_REGEX)

  if keys.uniq.size != keys.size
    raise InvalidComponentError, name, 'duplicated keys in the name'
  end

  keys.reject { |s| ns_name == s }.join(sep)
end

.ensure_valid_namespace(ns, sep) ⇒ Object

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.



62
63
64
65
66
# File 'lib/dry/system/component.rb', line 62

def self.ensure_valid_namespace(ns, sep)
  ns_name = ns.to_s
  raise InvalidNamespaceError, ns_name if ns && ns_name.include?(sep)
  ns_name
end

.new(*args) ⇒ Object

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.



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/dry/system/component.rb', line 44

def self.new(*args)
  cache.fetch_or_store(args.hash) do
    name, options = args
    options = DEFAULT_OPTIONS.merge(options || {})

    ns, sep = options.values_at(:namespace, :separator)

    ns_name = ensure_valid_namespace(ns, sep)
    identifier = ensure_valid_identifier(name, ns_name, sep)

    path = name.to_s.gsub(sep, PATH_SEPARATOR)
    loader = options.fetch(:loader, Loader).new(path)

    super(identifier, path, options.merge(loader: loader))
  end
end

Instance Method Details

#boot_file(path) ⇒ Object

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.



122
123
124
# File 'lib/dry/system/component.rb', line 122

def boot_file(path)
  path.join("#{root_key}.rb")
end

#bootable?(path) ⇒ Boolean

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.

Returns:

  • (Boolean)


117
118
119
# File 'lib/dry/system/component.rb', line 117

def bootable?(path)
  boot_file(path).exist?
end

#file_exists?(paths) ⇒ Boolean

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.

Returns:

  • (Boolean)


127
128
129
# File 'lib/dry/system/component.rb', line 127

def file_exists?(paths)
  paths.any? { |path| path.join(file).exist? }
end

#instance(*args) ⇒ Object

Returns components instance

Examples:

class MyApp < Dry::System::Container
  configure do |config|
    config.name = :my_app
    config.root = Pathname('/my/app')
  end

  auto_register!('lib/clients') do |component|
    # some custom initialization logic, ie:
    constant = component.loader.constant
    constant.create
  end
end

Returns:

  • (Object)

    component's class instance



112
113
114
# File 'lib/dry/system/component.rb', line 112

def instance(*args)
  loader.call(*args)
end

#namespaceObject

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.



151
152
153
# File 'lib/dry/system/component.rb', line 151

def namespace
  options[:namespace]
end

#namespaced(namespace) ⇒ Object

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.



139
140
141
142
143
# File 'lib/dry/system/component.rb', line 139

def namespaced(namespace)
  self.class.new(
    path, options.merge(loader: loader.class, namespace: namespace)
  )
end

#prepend(name) ⇒ Object

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.



132
133
134
135
136
# File 'lib/dry/system/component.rb', line 132

def prepend(name)
  self.class.new(
    [name, identifier].join(separator), options.merge(loader: loader.class)
  )
end

#root_keyObject

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.



156
157
158
# File 'lib/dry/system/component.rb', line 156

def root_key
  namespaces.first
end

#separatorObject

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.



146
147
148
# File 'lib/dry/system/component.rb', line 146

def separator
  options[:separator]
end