hanami 2.1.1 → 2.2.0.beta1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +19 -0
- data/README.md +7 -7
- data/hanami.gemspec +6 -6
- data/lib/hanami/app.rb +5 -1
- data/lib/hanami/config/db.rb +33 -0
- data/lib/hanami/config.rb +36 -9
- data/lib/hanami/extensions/db/repo.rb +103 -0
- data/lib/hanami/extensions.rb +4 -0
- data/lib/hanami/helpers/form_helper/form_builder.rb +2 -4
- data/lib/hanami/provider_registrar.rb +26 -0
- data/lib/hanami/providers/assets.rb +2 -20
- data/lib/hanami/providers/db/adapter.rb +68 -0
- data/lib/hanami/providers/db/adapters.rb +44 -0
- data/lib/hanami/providers/db/config.rb +66 -0
- data/lib/hanami/providers/db/sql_adapter.rb +80 -0
- data/lib/hanami/providers/db.rb +203 -0
- data/lib/hanami/providers/db_logging.rb +22 -0
- data/lib/hanami/providers/rack.rb +1 -1
- data/lib/hanami/providers/relations.rb +31 -0
- data/lib/hanami/providers/routes.rb +1 -13
- data/lib/hanami/rake_tasks.rb +8 -7
- data/lib/hanami/slice.rb +84 -4
- data/lib/hanami/version.rb +1 -1
- data/lib/hanami.rb +3 -0
- data/spec/integration/container/provider_environment_spec.rb +52 -0
- data/spec/integration/db/auto_registration_spec.rb +39 -0
- data/spec/integration/db/db_inflector_spec.rb +57 -0
- data/spec/integration/db/db_slices_spec.rb +327 -0
- data/spec/integration/db/db_spec.rb +220 -0
- data/spec/integration/db/logging_spec.rb +238 -0
- data/spec/integration/db/provider_config_spec.rb +88 -0
- data/spec/integration/db/provider_spec.rb +35 -0
- data/spec/integration/db/repo_spec.rb +215 -0
- data/spec/integration/db/slices_importing_from_parent.rb +130 -0
- data/spec/integration/slices/slice_configuration_spec.rb +4 -4
- data/spec/support/app_integration.rb +3 -0
- data/spec/unit/hanami/config/db_spec.rb +38 -0
- data/spec/unit/hanami/config/router_spec.rb +1 -1
- data/spec/unit/hanami/helpers/form_helper_spec.rb +31 -0
- data/spec/unit/hanami/providers/db/config/default_config_spec.rb +107 -0
- data/spec/unit/hanami/providers/db/config_spec.rb +206 -0
- data/spec/unit/hanami/slice_spec.rb +32 -0
- data/spec/unit/hanami/version_spec.rb +1 -1
- metadata +61 -19
@@ -0,0 +1,80 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Hanami
|
4
|
+
module Providers
|
5
|
+
class DB < Dry::System::Provider::Source
|
6
|
+
# @api public
|
7
|
+
# @since 2.2.0
|
8
|
+
class SQLAdapter < Adapter
|
9
|
+
# @api public
|
10
|
+
# @since 2.2.0
|
11
|
+
setting :extensions, mutable: true
|
12
|
+
|
13
|
+
# @api public
|
14
|
+
# @since 2.2.0
|
15
|
+
def extension(*extensions)
|
16
|
+
self.extensions.concat(extensions)
|
17
|
+
end
|
18
|
+
|
19
|
+
# @api public
|
20
|
+
# @since 2.2.0
|
21
|
+
def extensions
|
22
|
+
config.extensions ||= []
|
23
|
+
end
|
24
|
+
|
25
|
+
# @api private
|
26
|
+
def configure_for_database(database_url)
|
27
|
+
return if skip_defaults?
|
28
|
+
|
29
|
+
configure_plugins
|
30
|
+
configure_extensions(database_url)
|
31
|
+
end
|
32
|
+
|
33
|
+
# @api private
|
34
|
+
private def configure_plugins
|
35
|
+
return if skip_defaults?(:plugins)
|
36
|
+
|
37
|
+
plugin relations: :instrumentation do |plugin|
|
38
|
+
plugin.notifications = target["notifications"]
|
39
|
+
end
|
40
|
+
|
41
|
+
plugin relations: :auto_restrictions
|
42
|
+
end
|
43
|
+
|
44
|
+
# @api private
|
45
|
+
private def configure_extensions(database_url)
|
46
|
+
return if skip_defaults?(:extensions)
|
47
|
+
|
48
|
+
# Extensions for all SQL databases
|
49
|
+
extension(
|
50
|
+
:caller_logging,
|
51
|
+
:error_sql,
|
52
|
+
:sql_comments
|
53
|
+
)
|
54
|
+
|
55
|
+
# Extensions for specific databases
|
56
|
+
if database_url.to_s.start_with?("postgresql://")
|
57
|
+
extension(
|
58
|
+
:pg_array,
|
59
|
+
:pg_enum,
|
60
|
+
:pg_json,
|
61
|
+
:pg_range
|
62
|
+
)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# @api private
|
67
|
+
def gateway_options
|
68
|
+
{extensions: config.extensions}
|
69
|
+
end
|
70
|
+
|
71
|
+
# @api public
|
72
|
+
# @since 2.2.0
|
73
|
+
def clear
|
74
|
+
config.extensions = nil
|
75
|
+
super
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,203 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "dry/configurable"
|
4
|
+
require "dry/core"
|
5
|
+
|
6
|
+
module Hanami
|
7
|
+
module Providers
|
8
|
+
# @api private
|
9
|
+
# @since 2.2.0
|
10
|
+
class DB < Dry::System::Provider::Source
|
11
|
+
extend Dry::Core::Cache
|
12
|
+
|
13
|
+
include Dry::Configurable(config_class: Providers::DB::Config)
|
14
|
+
|
15
|
+
setting :database_url
|
16
|
+
setting :adapter, default: :sql
|
17
|
+
setting :adapters, mutable: true, default: Adapters.new
|
18
|
+
setting :relations_path, default: "relations"
|
19
|
+
|
20
|
+
def initialize(...)
|
21
|
+
super(...)
|
22
|
+
|
23
|
+
@configured_for_database = false
|
24
|
+
end
|
25
|
+
|
26
|
+
def finalize_config
|
27
|
+
apply_parent_config and return if apply_parent_config?
|
28
|
+
|
29
|
+
configure_for_database
|
30
|
+
end
|
31
|
+
|
32
|
+
def prepare
|
33
|
+
prepare_and_import_parent_db and return if import_from_parent?
|
34
|
+
|
35
|
+
override_rom_inflector
|
36
|
+
|
37
|
+
finalize_config
|
38
|
+
|
39
|
+
require "hanami-db"
|
40
|
+
|
41
|
+
unless database_url
|
42
|
+
raise Hanami::ComponentLoadError, "A database_url is required to start :db."
|
43
|
+
end
|
44
|
+
|
45
|
+
# Avoid making spurious connections by reusing identically configured gateways across slices
|
46
|
+
gateway = fetch_or_store(database_url, config.gateway_cache_keys) {
|
47
|
+
ROM::Gateway.setup(
|
48
|
+
config.adapter,
|
49
|
+
database_url,
|
50
|
+
**config.gateway_options
|
51
|
+
)
|
52
|
+
}
|
53
|
+
|
54
|
+
@rom_config = ROM::Configuration.new(gateway)
|
55
|
+
|
56
|
+
config.each_plugin do |plugin_spec, config_block|
|
57
|
+
if config_block
|
58
|
+
@rom_config.plugin(config.adapter, plugin_spec) do |plugin_config|
|
59
|
+
instance_exec(plugin_config, &config_block)
|
60
|
+
end
|
61
|
+
else
|
62
|
+
@rom_config.plugin(config.adapter, plugin_spec)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
register "config", @rom_config
|
67
|
+
register "gateway", gateway
|
68
|
+
end
|
69
|
+
|
70
|
+
# @api private
|
71
|
+
def start
|
72
|
+
start_and_import_parent_db and return if import_from_parent?
|
73
|
+
|
74
|
+
# Set up DB logging for the whole app. We share the app's notifications bus across all
|
75
|
+
# slices, so we only need to configure the subsciprtion for DB logging just once.
|
76
|
+
target.app.start :db_logging
|
77
|
+
|
78
|
+
# Find and register relations
|
79
|
+
relations_path = target.source_path.join(config.relations_path)
|
80
|
+
relations_path.glob("*.rb").each do |relation_file|
|
81
|
+
relation_name = relation_file
|
82
|
+
.relative_path_from(relations_path)
|
83
|
+
.basename(relation_file.extname)
|
84
|
+
.to_s
|
85
|
+
|
86
|
+
relation_class = target.namespace
|
87
|
+
.const_get(:Relations) # TODO don't hardcode
|
88
|
+
.const_get(target.inflector.camelize(relation_name))
|
89
|
+
|
90
|
+
@rom_config.register_relation(relation_class)
|
91
|
+
end
|
92
|
+
|
93
|
+
# TODO: register mappers & commands
|
94
|
+
|
95
|
+
rom = ROM.container(@rom_config)
|
96
|
+
|
97
|
+
register "rom", rom
|
98
|
+
end
|
99
|
+
|
100
|
+
def stop
|
101
|
+
target["db.rom"].disconnect
|
102
|
+
end
|
103
|
+
|
104
|
+
# @api private
|
105
|
+
def database_url
|
106
|
+
return @database_url if instance_variable_defined?(:@database_url)
|
107
|
+
|
108
|
+
# For "main" slice, expect MAIN__DATABASE_URL
|
109
|
+
slice_url_var = "#{target.slice_name.name.gsub("/", "__").upcase}__DATABASE_URL"
|
110
|
+
chosen_url = config.database_url || ENV[slice_url_var] || ENV["DATABASE_URL"]
|
111
|
+
chosen_url &&= Hanami::DB::Testing.database_url(chosen_url) if Hanami.env?(:test)
|
112
|
+
|
113
|
+
@database_url = chosen_url
|
114
|
+
end
|
115
|
+
|
116
|
+
private
|
117
|
+
|
118
|
+
def parent_db_provider
|
119
|
+
return @parent_db_provider if instance_variable_defined?(:@parent_db_provider)
|
120
|
+
|
121
|
+
@parent_db_provider = target.parent && target.parent.container.providers[:db]
|
122
|
+
end
|
123
|
+
|
124
|
+
def apply_parent_config
|
125
|
+
parent_db_provider.source.finalize_config
|
126
|
+
|
127
|
+
self.class.settings.keys.each do |key|
|
128
|
+
# Preserve settings already configured locally
|
129
|
+
next if config.configured?(key)
|
130
|
+
|
131
|
+
# Skip adapter config, we handle this below
|
132
|
+
next if key == :adapters
|
133
|
+
|
134
|
+
config[key] = parent_db_provider.source.config[key]
|
135
|
+
end
|
136
|
+
|
137
|
+
parent_db_provider.source.config.adapters.each do |adapter_name, parent_adapter|
|
138
|
+
adapter = config.adapters[adapter_name]
|
139
|
+
|
140
|
+
adapter.class.settings.keys.each do |key|
|
141
|
+
next if adapter.config.configured?(key)
|
142
|
+
|
143
|
+
adapter.config[key] = parent_adapter.config[key]
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def apply_parent_config?
|
149
|
+
target.config.db.configure_from_parent && parent_db_provider
|
150
|
+
end
|
151
|
+
|
152
|
+
def configure_for_database
|
153
|
+
return if @configured_for_database
|
154
|
+
|
155
|
+
config.adapter(config.adapter_name).configure_for_database(database_url)
|
156
|
+
@configured_for_database = true
|
157
|
+
end
|
158
|
+
|
159
|
+
def import_from_parent?
|
160
|
+
target.config.db.import_from_parent && target.parent
|
161
|
+
end
|
162
|
+
|
163
|
+
def prepare_and_import_parent_db
|
164
|
+
return unless parent_db_provider
|
165
|
+
|
166
|
+
target.parent.prepare :db
|
167
|
+
@rom_config = target.parent["db.config"]
|
168
|
+
|
169
|
+
register "config", (@rom_config = target.parent["db.config"])
|
170
|
+
register "gateway", target.parent["db.gateway"]
|
171
|
+
end
|
172
|
+
|
173
|
+
def start_and_import_parent_db
|
174
|
+
return unless parent_db_provider
|
175
|
+
|
176
|
+
target.parent.start :db
|
177
|
+
|
178
|
+
register "rom", target.parent["db.rom"]
|
179
|
+
end
|
180
|
+
|
181
|
+
# ROM 5.3 doesn't have a configurable inflector.
|
182
|
+
#
|
183
|
+
# This is a problem in Hanami because using different
|
184
|
+
# inflection rules for ROM will lead to constant loading
|
185
|
+
# errors.
|
186
|
+
def override_rom_inflector
|
187
|
+
return if ROM::Inflector == Hanami.app["inflector"]
|
188
|
+
|
189
|
+
ROM.instance_eval {
|
190
|
+
remove_const :Inflector
|
191
|
+
const_set :Inflector, Hanami.app["inflector"]
|
192
|
+
}
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
Dry::System.register_provider_source(
|
197
|
+
:db,
|
198
|
+
source: DB,
|
199
|
+
group: :hanami,
|
200
|
+
provider_options: {namespace: true}
|
201
|
+
)
|
202
|
+
end
|
203
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Hanami
|
4
|
+
module Providers
|
5
|
+
# @api private
|
6
|
+
# @since 2.2.0
|
7
|
+
class DBLogging < Dry::System::Provider::Source
|
8
|
+
# @api private
|
9
|
+
# @since 2.2.0
|
10
|
+
def prepare
|
11
|
+
require "dry/monitor/sql/logger"
|
12
|
+
target["notifications"].register_event :sql
|
13
|
+
end
|
14
|
+
|
15
|
+
# @api private
|
16
|
+
# @since 2.2.0
|
17
|
+
def start
|
18
|
+
Dry::Monitor::SQL::Logger.new(target["logger"]).subscribe(target["notifications"])
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -37,7 +37,7 @@ module Hanami
|
|
37
37
|
clock: Dry::Monitor::Clock.new(unit: :microsecond)
|
38
38
|
)
|
39
39
|
|
40
|
-
rack_logger = Hanami::Web::RackLogger.new(target[:logger], env: target.env)
|
40
|
+
rack_logger = Hanami::Web::RackLogger.new(target[:logger], env: target.container.env)
|
41
41
|
rack_logger.attach(monitor_middleware)
|
42
42
|
|
43
43
|
register "monitor", monitor_middleware
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Hanami
|
4
|
+
module Providers
|
5
|
+
# @api private
|
6
|
+
# @since 2.2.0
|
7
|
+
class Relations < Dry::System::Provider::Source
|
8
|
+
def start
|
9
|
+
start_and_import_parent_relations and return if target.parent && target.config.db.import_from_parent
|
10
|
+
|
11
|
+
target.start :db
|
12
|
+
|
13
|
+
register_relations target["db.rom"]
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def register_relations(rom)
|
19
|
+
rom.relations.each do |name, _|
|
20
|
+
register name, rom.relations[name]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def start_and_import_parent_relations
|
25
|
+
target.parent.start :relations
|
26
|
+
|
27
|
+
register_relations target.parent["db.rom"]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -10,18 +10,6 @@ module Hanami
|
|
10
10
|
# @api private
|
11
11
|
# @since 2.0.0
|
12
12
|
class Routes < Dry::System::Provider::Source
|
13
|
-
# @api private
|
14
|
-
def self.for_slice(slice)
|
15
|
-
Class.new(self) do |klass|
|
16
|
-
klass.instance_variable_set(:@slice, slice)
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
# @api private
|
21
|
-
def self.slice
|
22
|
-
@slice || Hanami.app
|
23
|
-
end
|
24
|
-
|
25
13
|
# @api private
|
26
14
|
def prepare
|
27
15
|
require "hanami/slice/routes_helper"
|
@@ -33,7 +21,7 @@ module Hanami
|
|
33
21
|
# router during the process of booting. This ensures the router's resolver can run strict
|
34
22
|
# action key checks once when it runs on a fully booted slice.
|
35
23
|
register :routes do
|
36
|
-
Hanami::Slice::RoutesHelper.new(
|
24
|
+
Hanami::Slice::RoutesHelper.new(target.router)
|
37
25
|
end
|
38
26
|
end
|
39
27
|
end
|
data/lib/hanami/rake_tasks.rb
CHANGED
@@ -33,13 +33,14 @@ Hanami::CLI::RakeTasks.register_tasks do
|
|
33
33
|
#
|
34
34
|
# If you're not in control and your deployment requires these "standard"
|
35
35
|
# Rake tasks, they are here only to solve this specific problem.
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
36
|
+
|
37
|
+
if Hanami.bundled?("hanami-db")
|
38
|
+
namespace :db do
|
39
|
+
task :migrate do
|
40
|
+
Hanami::CLI::Commands::App::DB::Migrate.new.call
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
43
44
|
|
44
45
|
if Hanami.bundled?("hanami-assets")
|
45
46
|
namespace :assets do
|
data/lib/hanami/slice.rb
CHANGED
@@ -101,6 +101,16 @@ module Hanami
|
|
101
101
|
Hanami.app
|
102
102
|
end
|
103
103
|
|
104
|
+
# Returns true if the slice is Hanami.app
|
105
|
+
#
|
106
|
+
# @return [Boolean]
|
107
|
+
#
|
108
|
+
# @api public
|
109
|
+
# @since 2.2.0
|
110
|
+
def app?
|
111
|
+
eql?(app)
|
112
|
+
end
|
113
|
+
|
104
114
|
# Returns the slice's config.
|
105
115
|
#
|
106
116
|
# A slice's config is copied from the app config at time of first access.
|
@@ -203,6 +213,16 @@ module Hanami
|
|
203
213
|
config.root || app.root.join(SLICES_DIR, slice_name.to_s)
|
204
214
|
end
|
205
215
|
|
216
|
+
# Returns the slice's root component directory, accounting for App as a special case.
|
217
|
+
#
|
218
|
+
# @return [Pathname]
|
219
|
+
#
|
220
|
+
# @api public
|
221
|
+
# @since 2.2.0
|
222
|
+
def source_path
|
223
|
+
app? ? root.join(APP_DIR) : root
|
224
|
+
end
|
225
|
+
|
206
226
|
# Returns the slice's configured inflector.
|
207
227
|
#
|
208
228
|
# Unless explicitly re-configured for the slice, this will be the app's inflector.
|
@@ -507,6 +527,12 @@ module Hanami
|
|
507
527
|
container.register_provider(...)
|
508
528
|
end
|
509
529
|
|
530
|
+
# @api public
|
531
|
+
# @since 2.1.0
|
532
|
+
def configure_provider(*args, **kwargs, &block)
|
533
|
+
container.register_provider(*args, **kwargs, from: :hanami, &block)
|
534
|
+
end
|
535
|
+
|
510
536
|
# @overload start(provider_name)
|
511
537
|
# Starts a provider.
|
512
538
|
#
|
@@ -559,6 +585,13 @@ module Hanami
|
|
559
585
|
container.key?(...)
|
560
586
|
end
|
561
587
|
|
588
|
+
# Required for the slice to act as a provider target
|
589
|
+
# @api public
|
590
|
+
# @since 2.2.0
|
591
|
+
def registered?(...)
|
592
|
+
container.registered?(...)
|
593
|
+
end
|
594
|
+
|
562
595
|
# Returns an array of keys for all currently registered components in the container.
|
563
596
|
#
|
564
597
|
# For a prepared slice, this will be the set of components that have been previously resolved.
|
@@ -842,6 +875,7 @@ module Hanami
|
|
842
875
|
def prepare_container_base_config
|
843
876
|
container.config.name = slice_name.to_sym
|
844
877
|
container.config.root = root
|
878
|
+
container.config.provider_registrar = ProviderRegistrar.for_slice(self)
|
845
879
|
container.config.provider_dirs = [File.join("config", "providers")]
|
846
880
|
container.config.registrations_dir = File.join("config", "registrations")
|
847
881
|
|
@@ -893,12 +927,29 @@ module Hanami
|
|
893
927
|
# point we're still in the process of preparing.
|
894
928
|
if routes
|
895
929
|
require_relative "providers/routes"
|
896
|
-
register_provider(:routes, source: Providers::Routes
|
930
|
+
register_provider(:routes, source: Providers::Routes)
|
897
931
|
end
|
898
932
|
|
899
933
|
if assets_dir? && Hanami.bundled?("hanami-assets")
|
900
934
|
require_relative "providers/assets"
|
901
|
-
register_provider(:assets, source: Providers::Assets
|
935
|
+
register_provider(:assets, source: Providers::Assets)
|
936
|
+
end
|
937
|
+
|
938
|
+
if Hanami.bundled?("hanami-db")
|
939
|
+
# Explicit require here to ensure the provider source registers itself, to allow the user
|
940
|
+
# to configure it within their own concrete provider file.
|
941
|
+
require_relative "providers/db"
|
942
|
+
|
943
|
+
if register_db_provider?
|
944
|
+
# Only register providers if the user hasn't provided their own
|
945
|
+
if !container.providers[:db]
|
946
|
+
register_provider(:db, namespace: true, source: Providers::DB)
|
947
|
+
end
|
948
|
+
|
949
|
+
if !container.providers[:relations]
|
950
|
+
register_provider(:relations, namespace: true, source: Providers::Relations)
|
951
|
+
end
|
952
|
+
end
|
902
953
|
end
|
903
954
|
end
|
904
955
|
|
@@ -1028,8 +1079,37 @@ module Hanami
|
|
1028
1079
|
private_constant :ROUTER_NOT_FOUND_HANDLER
|
1029
1080
|
|
1030
1081
|
def assets_dir?
|
1031
|
-
|
1032
|
-
|
1082
|
+
source_path.join("assets").directory?
|
1083
|
+
end
|
1084
|
+
|
1085
|
+
def register_db_provider?
|
1086
|
+
concrete_db_provider? ||
|
1087
|
+
db_config_dir? ||
|
1088
|
+
relations_dir? ||
|
1089
|
+
db_source_dir? ||
|
1090
|
+
import_db_from_parent?
|
1091
|
+
end
|
1092
|
+
|
1093
|
+
def concrete_db_provider?
|
1094
|
+
root.join(CONFIG_DIR, "providers", "db.rb").exist?
|
1095
|
+
end
|
1096
|
+
|
1097
|
+
def db_config_dir?
|
1098
|
+
root.join("config", "db").directory?
|
1099
|
+
end
|
1100
|
+
|
1101
|
+
def relations_dir?
|
1102
|
+
source_path.join("relations").directory?
|
1103
|
+
end
|
1104
|
+
|
1105
|
+
def db_source_dir?
|
1106
|
+
source_path.join("db").directory?
|
1107
|
+
end
|
1108
|
+
|
1109
|
+
def import_db_from_parent?
|
1110
|
+
parent &&
|
1111
|
+
config.db.import_from_parent &&
|
1112
|
+
parent.container.providers[:db]
|
1033
1113
|
end
|
1034
1114
|
|
1035
1115
|
# rubocop:enable Metrics/AbcSize
|
data/lib/hanami/version.rb
CHANGED
data/lib/hanami.rb
CHANGED
@@ -17,6 +17,9 @@ module Hanami
|
|
17
17
|
# @since 2.0.0
|
18
18
|
def self.loader
|
19
19
|
@loader ||= Zeitwerk::Loader.for_gem.tap do |loader|
|
20
|
+
loader.inflector.inflect "db" => "DB"
|
21
|
+
loader.inflector.inflect "db_logging" => "DBLogging"
|
22
|
+
loader.inflector.inflect "sql_adapter" => "SQLAdapter"
|
20
23
|
loader.ignore(
|
21
24
|
"#{loader.dirs.first}/hanami/{constants,boot,errors,extensions/router/errors,prepare,rake_tasks,setup}.rb"
|
22
25
|
)
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe "Container / Provider environment", :app_integration do
|
4
|
+
let!(:app) {
|
5
|
+
module TestApp
|
6
|
+
class App < Hanami::App
|
7
|
+
class << self
|
8
|
+
attr_accessor :test_provider_target
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
before_prepare if respond_to?(:before_prepare)
|
14
|
+
|
15
|
+
Hanami.app.prepare
|
16
|
+
Hanami.app
|
17
|
+
}
|
18
|
+
|
19
|
+
context "app provider" do
|
20
|
+
before do
|
21
|
+
Hanami.app.register_provider :test_provider, namespace: true do
|
22
|
+
start do
|
23
|
+
Hanami.app.test_provider_target = target
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
it "exposes the app as the provider target" do
|
29
|
+
Hanami.app.start :test_provider
|
30
|
+
expect(Hanami.app.test_provider_target).to be Hanami.app
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context "slice provider" do
|
35
|
+
def before_prepare
|
36
|
+
Hanami.app.register_slice :main
|
37
|
+
end
|
38
|
+
|
39
|
+
before do
|
40
|
+
Main::Slice.register_provider :test_provider, namespace: true do
|
41
|
+
start do
|
42
|
+
Hanami.app.test_provider_target = target
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
it "exposes the slice as the provider target" do
|
48
|
+
Main::Slice.start :test_provider
|
49
|
+
expect(Hanami.app.test_provider_target).to be Main::Slice
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe "DB / auto-registration", :app_integration do
|
4
|
+
before do
|
5
|
+
@env = ENV.to_h
|
6
|
+
allow(Hanami::Env).to receive(:loaded?).and_return(false)
|
7
|
+
end
|
8
|
+
|
9
|
+
after do
|
10
|
+
ENV.replace(@env)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "does not auto-register files in entities/, structs/, or db/" do
|
14
|
+
with_tmp_directory(@dir = Dir.mktmpdir) do
|
15
|
+
write "config/app.rb", <<~RUBY
|
16
|
+
require "hanami"
|
17
|
+
|
18
|
+
module TestApp
|
19
|
+
class App < Hanami::App
|
20
|
+
end
|
21
|
+
end
|
22
|
+
RUBY
|
23
|
+
|
24
|
+
write "app/db/changesets/update_posts.rb", ""
|
25
|
+
write "app/entities/post.rb", ""
|
26
|
+
write "app/structs/post.rb", ""
|
27
|
+
|
28
|
+
ENV["DATABASE_URL"] = "sqlite::memory"
|
29
|
+
|
30
|
+
require "hanami/boot"
|
31
|
+
|
32
|
+
expect(Hanami.app.keys).not_to include(*[
|
33
|
+
"db.changesets.update_posts",
|
34
|
+
"entities.post",
|
35
|
+
"structs.post"
|
36
|
+
])
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|