/
registry.cr
104 lines (87 loc) · 3.33 KB
/
registry.cr
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
module Marten
module Apps
# The applications registry.
#
# The applications registry is responsible for managing all the application config classes of a given project.
class Registry
@@app_config_registry = [] of Config.class
# :nodoc:
def self.register_app_config(app_config_klass : Config.class)
@@app_config_registry << app_config_klass
end
def initialize
@app_configs_store = {} of String => Config
@unassigned_models = [] of DB::Model.class
end
# Returns an array of the available app configs.
def app_configs
@app_configs_store.values
end
# Returns the app config instance for the passed app label.
#
# Raises `Marten::Apps::Errors::AppNotFound` if the app config cannot be found.
def get(label : String)
@app_configs_store.fetch(label) do
raise Errors::AppNotFound.new("Label '#{label}' is not associated with any installed apps")
end
end
# :ditto:
def get(label : Symbol)
get(label.to_s)
end
# Returns the application config object contaning the passed class.
def get_containing(klass)
candidates = [] of Config.class
@@app_config_registry.each do |app_config_klass|
if klass._marten_app_location.starts_with?(app_config_klass._marten_app_location)
remaining = klass._marten_app_location[app_config_klass._marten_app_location.size..]
next unless remaining == "" || remaining[0] == '/'
candidates << app_config_klass
end
end
result = unless candidates.empty?
candidates.sort_by(&._marten_app_location.size).reverse!.first
end
if result.nil? || !@app_configs_store.has_key?(result.not_nil!.label)
raise Errors::AppNotFound.new(
"Class '#{klass}' is not part of an application defined in Marten.settings.installed_apps"
)
end
@app_configs_store[result.not_nil!.label]
end
def insert_main_app
populate([MainConfig])
end
# Returns the main application config, which corresponds to the standard `src/` folder.
def main
get(MainConfig::RESERVED_LABEL)
end
# Populate the app config registry from the list of the project installed apps.
def populate(installed_apps : Array(Config.class)) : Nil
installed_apps.each do |app|
if @app_configs_store.has_key?(app.label)
raise Errors::InvalidAppConfig.new("App labels must be unique, duplicate found: '#{app.label}'")
end
@app_configs_store[app.label] = app.new
end
@unassigned_models.each do |model|
config = model.app_config
config.register_model(model)
rescue Errors::AppNotFound
# Skip models that are associated with non-installed apps.
end
end
# Registers a specific model class to the registry of app configs.
#
# This model will be associated later on to the associated app config once all the app configs of the current
# project are populated and initialized.
def register_model(model : DB::Model.class)
@unassigned_models << model
end
# Triggers app config setups.
def setup
app_configs.each(&.setup)
end
end
end
end