hanami 2.2.0.beta2 → 2.2.0.rc1
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 +12 -0
- data/hanami.gemspec +2 -2
- data/lib/hanami/extensions/operation.rb +48 -0
- data/lib/hanami/extensions.rb +4 -0
- data/lib/hanami/providers/db/adapters.rb +19 -3
- data/lib/hanami/providers/db/config.rb +4 -22
- data/lib/hanami/providers/db/gateway.rb +20 -3
- data/lib/hanami/providers/db/sql_adapter.rb +3 -3
- data/lib/hanami/providers/db.rb +27 -5
- data/lib/hanami/version.rb +1 -1
- data/spec/integration/db/db_slices_spec.rb +66 -0
- data/spec/integration/db/gateways_spec.rb +42 -1
- data/spec/integration/operations/extension_spec.rb +59 -0
- data/spec/unit/hanami/providers/db/config/gateway_spec.rb +73 -0
- data/spec/unit/hanami/providers/db/config_spec.rb +0 -13
- data/spec/unit/hanami/version_spec.rb +1 -1
- metadata +12 -7
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e2c1e373ac344bb557876a8160a6a1064aca7abc8a8ae03f2efc417b9e271b0b
|
|
4
|
+
data.tar.gz: 89b950b1257b13dd23ab872a145799f7652237989e442892e00ea2ae2f582d15
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4ca50cfde3f5372b0df28e73c00642d44752464860fc879dfd8f4dd2dc9a8e64e4043e79a77b6f1028a6bb894bfd4532257ed62a1f590f8fce01bafdc5c972b0
|
|
7
|
+
data.tar.gz: cb094b9aaddb125c6a859c78c29cc9e885541f6cd89a739455313700cbc365c7ff46d3a8e8c1bf02805d4c5317a746aa2884787cb01b3618df0e5bd189b52859
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
The web, with simplicity.
|
|
4
4
|
|
|
5
|
+
## v2.2.0.rc1 - 2024-10-29
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- [Adam Lassek] Add `#connection_options` to db gateways. These are a hash of options that will be passed to the lower-level driver when the gateway connects. For SQL databases, this means [Sequel's connection options](https://sequel.jeremyevans.net/rdoc/files/doc/opening_databases_rdoc.html) (#1450)
|
|
10
|
+
- [Adam Lassek] Automatically configure `Dry::Operation` subclasses within Hanami apps for `transaction` support using the app's ROM container. (#1456)
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- [Tim Riley] Apply config from matching gateways in parent slices (#1459)
|
|
15
|
+
- [Tim Riley] Remove `config.any_adapter` from DB provider (#1459)
|
|
16
|
+
|
|
5
17
|
## v2.2.0.beta2 - 2024-09-26
|
|
6
18
|
|
|
7
19
|
### Added
|
data/hanami.gemspec
CHANGED
|
@@ -38,8 +38,8 @@ Gem::Specification.new do |spec|
|
|
|
38
38
|
spec.add_dependency "dry-monitor", "~> 1.0", ">= 1.0.1", "< 2"
|
|
39
39
|
spec.add_dependency "dry-system", "= 1.1.0.beta2"
|
|
40
40
|
spec.add_dependency "dry-logger", "~> 1.0", "< 2"
|
|
41
|
-
spec.add_dependency "hanami-cli", "= 2.2.0.
|
|
42
|
-
spec.add_dependency "hanami-utils", "~> 2.2.
|
|
41
|
+
spec.add_dependency "hanami-cli", "= 2.2.0.rc1"
|
|
42
|
+
spec.add_dependency "hanami-utils", "~> 2.2.rc"
|
|
43
43
|
spec.add_dependency "zeitwerk", "~> 2.6"
|
|
44
44
|
|
|
45
45
|
spec.add_development_dependency "rspec", "~> 3.8"
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "dry/operation"
|
|
4
|
+
require "dry/operation/extensions/rom"
|
|
5
|
+
|
|
6
|
+
module Hanami
|
|
7
|
+
module Extensions
|
|
8
|
+
# Integrated behavior for `Dry::Operation` classes within Hanami apps.
|
|
9
|
+
#
|
|
10
|
+
# @see https://github.com/dry-rb/dry-operation
|
|
11
|
+
#
|
|
12
|
+
# @api public
|
|
13
|
+
# @since 2.2.0
|
|
14
|
+
module Operation
|
|
15
|
+
# @api private
|
|
16
|
+
# @since 2.2.0
|
|
17
|
+
def self.included(operation_class)
|
|
18
|
+
super
|
|
19
|
+
|
|
20
|
+
operation_class.extend(Hanami::SliceConfigurable)
|
|
21
|
+
operation_class.extend(ClassMethods)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# @api private
|
|
25
|
+
# @since 2.2.0
|
|
26
|
+
module ClassMethods
|
|
27
|
+
# @api private
|
|
28
|
+
# @since 2.2.0
|
|
29
|
+
def configure_for_slice(slice)
|
|
30
|
+
include slice.namespace::Deps["db.rom"]
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# @api private
|
|
34
|
+
# @since 2.2.0
|
|
35
|
+
def inherited(subclass)
|
|
36
|
+
super
|
|
37
|
+
|
|
38
|
+
return unless subclass.superclass == self
|
|
39
|
+
return unless Hanami.bundled?("hanami-db")
|
|
40
|
+
|
|
41
|
+
subclass.include Dry::Operation::Extensions::ROM
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
Dry::Operation.include(Hanami::Extensions::Operation)
|
data/lib/hanami/extensions.rb
CHANGED
|
@@ -30,9 +30,7 @@ module Hanami
|
|
|
30
30
|
# @api private
|
|
31
31
|
# @since 2.2.0
|
|
32
32
|
def initialize
|
|
33
|
-
@adapters =
|
|
34
|
-
hsh[key] = self.class.new_adapter(key)
|
|
35
|
-
end
|
|
33
|
+
@adapters = {}
|
|
36
34
|
end
|
|
37
35
|
|
|
38
36
|
# @api private
|
|
@@ -44,6 +42,24 @@ module Hanami
|
|
|
44
42
|
@adapters[key] = val.dup
|
|
45
43
|
end
|
|
46
44
|
end
|
|
45
|
+
|
|
46
|
+
# @api private
|
|
47
|
+
# @since 2.2.0
|
|
48
|
+
def adapter(key)
|
|
49
|
+
adapters[key] ||= new(key)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# @api private
|
|
53
|
+
# @since 2.2.0
|
|
54
|
+
def find(key)
|
|
55
|
+
adapters.fetch(key) { new(key) }
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# @api private
|
|
59
|
+
# @since 2.2.0
|
|
60
|
+
def new(key)
|
|
61
|
+
self.class.new_adapter(key)
|
|
62
|
+
end
|
|
47
63
|
end
|
|
48
64
|
end
|
|
49
65
|
end
|
|
@@ -20,24 +20,8 @@ module Hanami
|
|
|
20
20
|
|
|
21
21
|
# @api public
|
|
22
22
|
# @since 2.2.0
|
|
23
|
-
def
|
|
24
|
-
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
# @api public
|
|
28
|
-
# @since 2.2.0
|
|
29
|
-
def adapter(name = Undefined)
|
|
30
|
-
return adapter_name if name.eql?(Undefined)
|
|
31
|
-
|
|
32
|
-
adapter = (adapters[name] ||= Adapter.new)
|
|
33
|
-
yield adapter if block_given?
|
|
34
|
-
adapter
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
# @api public
|
|
38
|
-
# @since 2.2.0
|
|
39
|
-
def any_adapter
|
|
40
|
-
adapter = (adapters[nil] ||= Adapter.new)
|
|
23
|
+
def adapter(name)
|
|
24
|
+
adapter = adapters.adapter(name)
|
|
41
25
|
yield adapter if block_given?
|
|
42
26
|
adapter
|
|
43
27
|
end
|
|
@@ -46,12 +30,10 @@ module Hanami
|
|
|
46
30
|
def each_plugin
|
|
47
31
|
return to_enum(__method__) unless block_given?
|
|
48
32
|
|
|
49
|
-
universal_plugins = adapters[nil].plugins
|
|
50
|
-
|
|
51
33
|
gateways.values.group_by(&:adapter_name).each do |adapter_name, adapter_gateways|
|
|
52
|
-
per_adapter_plugins = adapter_gateways.map { _1.adapter.plugins }.flatten(1)
|
|
34
|
+
per_adapter_plugins = adapter_gateways.map { _1.adapter.plugins }.flatten(1).uniq
|
|
53
35
|
|
|
54
|
-
|
|
36
|
+
per_adapter_plugins.each do |plugin_spec, config_block|
|
|
55
37
|
yield adapter_name, plugin_spec, config_block
|
|
56
38
|
end
|
|
57
39
|
end
|
|
@@ -15,6 +15,7 @@ module Hanami
|
|
|
15
15
|
setting :database_url
|
|
16
16
|
setting :adapter_name, default: :sql
|
|
17
17
|
setting :adapter, mutable: true
|
|
18
|
+
setting :connection_options, default: {}
|
|
18
19
|
|
|
19
20
|
# @api public
|
|
20
21
|
# @since 2.2.0
|
|
@@ -34,13 +35,29 @@ module Hanami
|
|
|
34
35
|
end
|
|
35
36
|
end
|
|
36
37
|
|
|
38
|
+
# @api public
|
|
39
|
+
# @since 2.2.0
|
|
40
|
+
def connection_options(**options)
|
|
41
|
+
if options.any?
|
|
42
|
+
config.connection_options.merge!(options)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
config.connection_options
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# @api public
|
|
49
|
+
# @since 2.2.0
|
|
50
|
+
def options
|
|
51
|
+
{**connection_options, **config.adapter.gateway_options}
|
|
52
|
+
end
|
|
53
|
+
|
|
37
54
|
# @api private
|
|
38
55
|
def configure_adapter(default_adapters)
|
|
39
|
-
default_adapter = default_adapters
|
|
56
|
+
default_adapter = default_adapters.find(config.adapter_name)
|
|
40
57
|
config.adapter ||= default_adapter.dup
|
|
41
58
|
|
|
42
59
|
config.adapter.configure_from_adapter(default_adapter)
|
|
43
|
-
|
|
60
|
+
|
|
44
61
|
config.adapter.configure_for_database(config.database_url)
|
|
45
62
|
|
|
46
63
|
self
|
|
@@ -48,7 +65,7 @@ module Hanami
|
|
|
48
65
|
|
|
49
66
|
# @api private
|
|
50
67
|
def cache_keys
|
|
51
|
-
[config.database_url, config.adapter.gateway_cache_keys]
|
|
68
|
+
[config.database_url, config.connection_options, config.adapter.gateway_cache_keys]
|
|
52
69
|
end
|
|
53
70
|
|
|
54
71
|
private
|
|
@@ -13,7 +13,7 @@ module Hanami
|
|
|
13
13
|
# @api public
|
|
14
14
|
# @since 2.2.0
|
|
15
15
|
def extension(*extensions)
|
|
16
|
-
self.extensions.concat(extensions)
|
|
16
|
+
self.extensions.concat(extensions).uniq!
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
# @api public
|
|
@@ -73,7 +73,7 @@ module Hanami
|
|
|
73
73
|
)
|
|
74
74
|
|
|
75
75
|
# Extensions for specific databases
|
|
76
|
-
if database_url.to_s.start_with?(%r{postgres(ql)*://})
|
|
76
|
+
if database_url.to_s.start_with?(%r{postgres(ql)*://})
|
|
77
77
|
extension(
|
|
78
78
|
:pg_array,
|
|
79
79
|
:pg_enum,
|
|
@@ -85,7 +85,7 @@ module Hanami
|
|
|
85
85
|
|
|
86
86
|
# @api private
|
|
87
87
|
def gateway_options
|
|
88
|
-
{extensions:
|
|
88
|
+
{extensions: extensions}
|
|
89
89
|
end
|
|
90
90
|
|
|
91
91
|
# @api public
|
data/lib/hanami/providers/db.rb
CHANGED
|
@@ -113,7 +113,7 @@ module Hanami
|
|
|
113
113
|
# Preserve settings already configured locally
|
|
114
114
|
next if config.configured?(key)
|
|
115
115
|
|
|
116
|
-
#
|
|
116
|
+
# Skip gateway config, we handle this in #configure_gateways
|
|
117
117
|
next if key == :gateways
|
|
118
118
|
|
|
119
119
|
# Skip adapter config, we handle this below
|
|
@@ -123,12 +123,12 @@ module Hanami
|
|
|
123
123
|
end
|
|
124
124
|
|
|
125
125
|
parent_db_provider.source.config.adapters.each do |adapter_name, parent_adapter|
|
|
126
|
-
adapter = config.
|
|
126
|
+
adapter = config.adapter(adapter_name)
|
|
127
127
|
|
|
128
128
|
adapter.class.settings.keys.each do |key|
|
|
129
129
|
next if adapter.config.configured?(key)
|
|
130
130
|
|
|
131
|
-
adapter.config[key] = parent_adapter.config[key]
|
|
131
|
+
adapter.config[key] = parent_adapter.config[key].dup
|
|
132
132
|
end
|
|
133
133
|
end
|
|
134
134
|
end
|
|
@@ -196,18 +196,40 @@ module Hanami
|
|
|
196
196
|
|
|
197
197
|
ensure_database_gem(gw_config.database_url)
|
|
198
198
|
|
|
199
|
+
apply_parent_gateway_config(key, gw_config) if apply_parent_config?
|
|
200
|
+
|
|
199
201
|
gw_config.configure_adapter(config.adapters)
|
|
200
202
|
end
|
|
201
203
|
end
|
|
202
204
|
|
|
205
|
+
def apply_parent_gateway_config(key, gw_config)
|
|
206
|
+
parent_gw_config = parent_db_provider.source.config.gateways[key]
|
|
207
|
+
|
|
208
|
+
# Only copy config from a parent gateway with the same name _and_ database URL
|
|
209
|
+
return unless parent_gw_config&.database_url == gw_config.database_url
|
|
210
|
+
|
|
211
|
+
# Copy config from matching parent gateway
|
|
212
|
+
(gw_config.class.settings.keys - [:adapter]).each do |key|
|
|
213
|
+
next if gw_config.config.configured?(key)
|
|
214
|
+
|
|
215
|
+
gw_config.config[key] = parent_gw_config.config[key].dup
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
# If there is an adapter configured within this slice, prefer that, and do not copy the
|
|
219
|
+
# adapter from the parent gateway
|
|
220
|
+
unless config.adapters[gw_config.adapter_name] || gw_config.configured?(:adapter)
|
|
221
|
+
gw_config.adapter = parent_gw_config.adapter.dup
|
|
222
|
+
end
|
|
223
|
+
end
|
|
224
|
+
|
|
203
225
|
def prepare_gateways
|
|
204
226
|
config.gateways.transform_values { |gw_config|
|
|
205
227
|
# Avoid spurious connections by reusing identically configured gateways across slices
|
|
206
|
-
|
|
228
|
+
fetch_or_store(gw_config.cache_keys) {
|
|
207
229
|
ROM::Gateway.setup(
|
|
208
230
|
gw_config.adapter_name,
|
|
209
231
|
gw_config.database_url,
|
|
210
|
-
**gw_config.
|
|
232
|
+
**gw_config.options
|
|
211
233
|
)
|
|
212
234
|
}
|
|
213
235
|
}
|
data/lib/hanami/version.rb
CHANGED
|
@@ -17,6 +17,7 @@ RSpec.describe "DB / Slices", :app_integration do
|
|
|
17
17
|
|
|
18
18
|
module TestApp
|
|
19
19
|
class App < Hanami::App
|
|
20
|
+
config.logger.stream = File::NULL
|
|
20
21
|
end
|
|
21
22
|
end
|
|
22
23
|
RUBY
|
|
@@ -32,6 +33,67 @@ RSpec.describe "DB / Slices", :app_integration do
|
|
|
32
33
|
end
|
|
33
34
|
end
|
|
34
35
|
|
|
36
|
+
specify "slices using a parent gateway with connection options share a gateway/connection" do
|
|
37
|
+
with_tmp_directory(@dir = Dir.mktmpdir) do
|
|
38
|
+
write "config/app.rb", <<~RUBY
|
|
39
|
+
require "hanami"
|
|
40
|
+
|
|
41
|
+
module TestApp
|
|
42
|
+
class App < Hanami::App
|
|
43
|
+
config.logger.stream = File::NULL
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
RUBY
|
|
47
|
+
|
|
48
|
+
write "config/providers/db.rb", <<~RUBY
|
|
49
|
+
Hanami.app.configure_provider :db do
|
|
50
|
+
config.gateway :default do |gw|
|
|
51
|
+
gw.connection_options timeout: 10_000
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
config.gateway :extra do |gw|
|
|
55
|
+
gw.connection_options timeout: 20_000
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
RUBY
|
|
59
|
+
|
|
60
|
+
write "slices/main/config/providers/db.rb", <<~RUBY
|
|
61
|
+
Main::Slice.configure_provider :db do
|
|
62
|
+
config.gateway :bonus do |gw|
|
|
63
|
+
gw.connection_options timeout: 5_000
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
RUBY
|
|
67
|
+
|
|
68
|
+
write "db/.keep", ""
|
|
69
|
+
write "slices/admin/relations/.keep", ""
|
|
70
|
+
write "slices/main/relations/.keep", ""
|
|
71
|
+
|
|
72
|
+
ENV["DATABASE_URL"] = "sqlite://" + Pathname(@dir).realpath.join("app.sqlite").to_s
|
|
73
|
+
ENV["DATABASE_URL__EXTRA"] = "sqlite://" + Pathname(@dir).realpath.join("extra.sqlite").to_s
|
|
74
|
+
ENV["DATABASE_URL__BONUS"] = "sqlite://" + Pathname(@dir).realpath.join("bonus.sqlite").to_s
|
|
75
|
+
|
|
76
|
+
# "extra" gateway in admin slice, same URL as app
|
|
77
|
+
ENV["ADMIN__DATABASE_URL__EXTRA"] = ENV["DATABASE_URL__EXTRA"]
|
|
78
|
+
# "extra" gatway in main slice, different URL
|
|
79
|
+
ENV["MAIN__DATABASE_URL__EXTRA"] = "sqlite://" + Pathname(@dir).realpath.join("extra-main.sqlite").to_s
|
|
80
|
+
# "bonus" gateway in admin slice, same URL as app
|
|
81
|
+
ENV["ADMIN__DATABASE_URL__BONUS"] = ENV["DATABASE_URL__BONUS"]
|
|
82
|
+
# "bonus" gateway in main slice, same URL as app; different connection options in provider
|
|
83
|
+
ENV["MAIN__DATABASE_URL__BONUS"] = ENV["DATABASE_URL__BONUS"]
|
|
84
|
+
|
|
85
|
+
require "hanami/prepare"
|
|
86
|
+
|
|
87
|
+
expect(Admin::Slice["db.gateway"]).to be Hanami.app["db.gateway"]
|
|
88
|
+
|
|
89
|
+
expect(Admin::Slice["db.gateways.extra"]).to be Hanami.app["db.gateways.extra"]
|
|
90
|
+
expect(Main::Slice["db.gateways.extra"]).not_to be Hanami.app["db.gateways.extra"]
|
|
91
|
+
|
|
92
|
+
expect(Admin::Slice["db.gateways.bonus"]).to be Hanami.app["db.gateways.bonus"]
|
|
93
|
+
expect(Main::Slice["db.gateways.bonus"]).not_to be Hanami.app["db.gateways.bonus"]
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
35
97
|
specify "slices using the same database_url but different extensions have distinct gateways/connections" do
|
|
36
98
|
with_tmp_directory(@dir = Dir.mktmpdir) do
|
|
37
99
|
write "config/app.rb", <<~RUBY
|
|
@@ -39,6 +101,7 @@ RSpec.describe "DB / Slices", :app_integration do
|
|
|
39
101
|
|
|
40
102
|
module TestApp
|
|
41
103
|
class App < Hanami::App
|
|
104
|
+
config.logger.stream = File::NULL
|
|
42
105
|
end
|
|
43
106
|
end
|
|
44
107
|
RUBY
|
|
@@ -80,6 +143,7 @@ RSpec.describe "DB / Slices", :app_integration do
|
|
|
80
143
|
|
|
81
144
|
module TestApp
|
|
82
145
|
class App < Hanami::App
|
|
146
|
+
config.logger.stream = File::NULL
|
|
83
147
|
end
|
|
84
148
|
end
|
|
85
149
|
RUBY
|
|
@@ -213,6 +277,7 @@ RSpec.describe "DB / Slices", :app_integration do
|
|
|
213
277
|
|
|
214
278
|
module TestApp
|
|
215
279
|
class App < Hanami::App
|
|
280
|
+
config.logger.stream = File::NULL
|
|
216
281
|
end
|
|
217
282
|
end
|
|
218
283
|
RUBY
|
|
@@ -253,6 +318,7 @@ RSpec.describe "DB / Slices", :app_integration do
|
|
|
253
318
|
|
|
254
319
|
module TestApp
|
|
255
320
|
class App < Hanami::App
|
|
321
|
+
config.logger.stream = File::NULL
|
|
256
322
|
end
|
|
257
323
|
end
|
|
258
324
|
RUBY
|
|
@@ -81,7 +81,48 @@ RSpec.describe "DB / Gateways", :app_integration do
|
|
|
81
81
|
end
|
|
82
82
|
end
|
|
83
83
|
|
|
84
|
+
it "configures connection options on their respective gateways" do
|
|
85
|
+
with_tmp_directory(@dir = Dir.mktmpdir) do
|
|
86
|
+
write "config/app.rb", <<~RUBY
|
|
87
|
+
require "hanami"
|
|
88
|
+
|
|
89
|
+
module TestApp
|
|
90
|
+
class App < Hanami::App
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
RUBY
|
|
94
|
+
|
|
95
|
+
write "db/.keep", ""
|
|
96
|
+
|
|
97
|
+
write "config/providers/db.rb", <<~RUBY
|
|
98
|
+
Hanami.app.configure_provider :db do
|
|
99
|
+
config.gateway :default do |gw|
|
|
100
|
+
gw.connection_options timeout: 10_000
|
|
84
101
|
|
|
102
|
+
gw.adapter :sql do |a|
|
|
103
|
+
a.skip_defaults :extensions
|
|
104
|
+
a.extension :error_sql
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
config.gateway :extra do |gw|
|
|
109
|
+
gw.connection_options readonly: true
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
RUBY
|
|
113
|
+
|
|
114
|
+
ENV["DATABASE_URL"] = "sqlite::memory"
|
|
115
|
+
ENV["DATABASE_URL__EXTRA"] = "sqlite::memory"
|
|
116
|
+
|
|
117
|
+
require "hanami/prepare"
|
|
118
|
+
|
|
119
|
+
default = Hanami.app["db.gateways.default"]
|
|
120
|
+
extra = Hanami.app["db.gateways.extra"]
|
|
121
|
+
|
|
122
|
+
expect(default.options).to eq({timeout: 10_000, extensions: [:error_sql]})
|
|
123
|
+
expect(extra.options).to eq({readonly: true, extensions: %i[caller_logging error_sql sql_comments]})
|
|
124
|
+
end
|
|
125
|
+
end
|
|
85
126
|
|
|
86
127
|
it "exposes all database URLs as #database_urls on the provider source (for CLI commands)" do
|
|
87
128
|
with_tmp_directory(@dir = Dir.mktmpdir) do
|
|
@@ -155,7 +196,7 @@ RSpec.describe "DB / Gateways", :app_integration do
|
|
|
155
196
|
end
|
|
156
197
|
end
|
|
157
198
|
|
|
158
|
-
it "combines ROM plugins from
|
|
199
|
+
it "combines ROM plugins from both default adapter and gateway-configured adapters" do
|
|
159
200
|
with_tmp_directory(@dir = Dir.mktmpdir) do
|
|
160
201
|
write "config/app.rb", <<~RUBY
|
|
161
202
|
require "hanami"
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "dry/operation"
|
|
4
|
+
|
|
5
|
+
RSpec.describe "Operation / Extensions", :app_integration do
|
|
6
|
+
before do
|
|
7
|
+
@env = ENV.to_h
|
|
8
|
+
allow(Hanami::Env).to receive(:loaded?).and_return(false)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
after { ENV.replace(@env) }
|
|
12
|
+
|
|
13
|
+
specify "Transaction interface is made available automatically" do
|
|
14
|
+
with_tmp_directory(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/operation.rb", <<~RUBY
|
|
25
|
+
module TestApp
|
|
26
|
+
class Operation < Dry::Operation
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
RUBY
|
|
30
|
+
|
|
31
|
+
write "slices/main/operation.rb", <<~RUBY
|
|
32
|
+
module Main
|
|
33
|
+
class Operation < Dry::Operation
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
RUBY
|
|
37
|
+
|
|
38
|
+
write "db/.keep", ""
|
|
39
|
+
write "app/relations/.keep", ""
|
|
40
|
+
|
|
41
|
+
write "slices/main/db/.keep", ""
|
|
42
|
+
write "slices/main/relations/.keep", ""
|
|
43
|
+
|
|
44
|
+
ENV["DATABASE_URL"] = "sqlite::memory"
|
|
45
|
+
ENV["MAIN__DATABASE_URL"] = "sqlite::memory"
|
|
46
|
+
|
|
47
|
+
require "hanami/prepare"
|
|
48
|
+
|
|
49
|
+
app = TestApp::Operation.new
|
|
50
|
+
main = Main::Operation.new
|
|
51
|
+
|
|
52
|
+
expect(app).to respond_to(:transaction)
|
|
53
|
+
|
|
54
|
+
expect(app.rom).to be TestApp::App["db.rom"]
|
|
55
|
+
expect(app.rom).not_to be Main::Slice["db.rom"]
|
|
56
|
+
expect(main.rom).to be Main::Slice["db.rom"]
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "dry/system"
|
|
4
|
+
require "hanami/providers/db"
|
|
5
|
+
|
|
6
|
+
RSpec.describe "Hanami::Providers::DB / Config / Gateway config", :app_integration do
|
|
7
|
+
subject(:config) { provider.source.config }
|
|
8
|
+
|
|
9
|
+
let(:provider) {
|
|
10
|
+
Hanami.app.prepare
|
|
11
|
+
Hanami.app.configure_provider(:db)
|
|
12
|
+
Hanami.app.container.providers[:db]
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
before do
|
|
16
|
+
module TestApp
|
|
17
|
+
class App < Hanami::App
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
describe "sql adapter" do
|
|
23
|
+
before do
|
|
24
|
+
config.adapter(:sql).configure_for_database("sqlite::memory")
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
describe "connection_options" do
|
|
28
|
+
let(:default) { config.gateway(:default) }
|
|
29
|
+
|
|
30
|
+
it "merges kwargs into connection_options configuration" do
|
|
31
|
+
expect { default.connection_options(timeout: 10_000) }
|
|
32
|
+
.to change { default.connection_options }.from({}).to({timeout: 10_000})
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it "sets options per-gateway" do
|
|
36
|
+
other = config.gateway(:other)
|
|
37
|
+
expect { default.connection_options(timeout: 10_000) }
|
|
38
|
+
.to_not change { other.connection_options }
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it "is reflected in Gateway#cache_keys" do
|
|
42
|
+
default.adapter(:sql) {}
|
|
43
|
+
expect { default.connection_options(timeout: 10_000) }
|
|
44
|
+
.to change { default.cache_keys }
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
describe "options" do
|
|
49
|
+
it "combines connection_options with adapter.gateway_options" do
|
|
50
|
+
config.gateway :default do |gw|
|
|
51
|
+
gw.connection_options foo: "bar"
|
|
52
|
+
|
|
53
|
+
gw.adapter :sql do |a|
|
|
54
|
+
a.skip_defaults
|
|
55
|
+
a.extension :baz, :quux
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
expect(config.gateway(:default).options)
|
|
60
|
+
.to include(foo: "bar", extensions: [:baz, :quux])
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it "ignores conflicting keys from connection_options" do
|
|
64
|
+
config.gateway :default do |gw|
|
|
65
|
+
gw.connection_options extensions: "foo"
|
|
66
|
+
gw.adapter(:sql) { _1.skip_defaults }
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
expect(config.gateway(:default).options).to eq({extensions: []})
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
@@ -32,19 +32,6 @@ RSpec.describe "Hanami::Providers::DB.config", :app_integration do
|
|
|
32
32
|
end
|
|
33
33
|
end
|
|
34
34
|
|
|
35
|
-
describe "#any_adapter" do
|
|
36
|
-
it "adds an adapter keyed without a name" do
|
|
37
|
-
expect { config.any_adapter }
|
|
38
|
-
.to change { config.adapters.to_h }
|
|
39
|
-
.to hash_including(nil)
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
it "yields the adapter for configuration" do
|
|
43
|
-
expect { |b| config.any_adapter(&b) }
|
|
44
|
-
.to yield_with_args(an_instance_of(Hanami::Providers::DB::Adapter))
|
|
45
|
-
end
|
|
46
|
-
end
|
|
47
|
-
|
|
48
35
|
describe "adapters" do
|
|
49
36
|
subject(:adapter) { config.adapter(:yaml) }
|
|
50
37
|
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: hanami
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.2.0.
|
|
4
|
+
version: 2.2.0.rc1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Luca Guidi
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2024-
|
|
11
|
+
date: 2024-10-29 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -168,28 +168,28 @@ dependencies:
|
|
|
168
168
|
requirements:
|
|
169
169
|
- - '='
|
|
170
170
|
- !ruby/object:Gem::Version
|
|
171
|
-
version: 2.2.0.
|
|
171
|
+
version: 2.2.0.rc1
|
|
172
172
|
type: :runtime
|
|
173
173
|
prerelease: false
|
|
174
174
|
version_requirements: !ruby/object:Gem::Requirement
|
|
175
175
|
requirements:
|
|
176
176
|
- - '='
|
|
177
177
|
- !ruby/object:Gem::Version
|
|
178
|
-
version: 2.2.0.
|
|
178
|
+
version: 2.2.0.rc1
|
|
179
179
|
- !ruby/object:Gem::Dependency
|
|
180
180
|
name: hanami-utils
|
|
181
181
|
requirement: !ruby/object:Gem::Requirement
|
|
182
182
|
requirements:
|
|
183
183
|
- - "~>"
|
|
184
184
|
- !ruby/object:Gem::Version
|
|
185
|
-
version: 2.2.
|
|
185
|
+
version: 2.2.rc
|
|
186
186
|
type: :runtime
|
|
187
187
|
prerelease: false
|
|
188
188
|
version_requirements: !ruby/object:Gem::Requirement
|
|
189
189
|
requirements:
|
|
190
190
|
- - "~>"
|
|
191
191
|
- !ruby/object:Gem::Version
|
|
192
|
-
version: 2.2.
|
|
192
|
+
version: 2.2.rc
|
|
193
193
|
- !ruby/object:Gem::Dependency
|
|
194
194
|
name: zeitwerk
|
|
195
195
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -280,6 +280,7 @@ files:
|
|
|
280
280
|
- lib/hanami/extensions/action.rb
|
|
281
281
|
- lib/hanami/extensions/action/slice_configured_action.rb
|
|
282
282
|
- lib/hanami/extensions/db/repo.rb
|
|
283
|
+
- lib/hanami/extensions/operation.rb
|
|
283
284
|
- lib/hanami/extensions/router/errors.rb
|
|
284
285
|
- lib/hanami/extensions/view.rb
|
|
285
286
|
- lib/hanami/extensions/view/context.rb
|
|
@@ -376,6 +377,7 @@ files:
|
|
|
376
377
|
- spec/integration/logging/exception_logging_spec.rb
|
|
377
378
|
- spec/integration/logging/notifications_spec.rb
|
|
378
379
|
- spec/integration/logging/request_logging_spec.rb
|
|
380
|
+
- spec/integration/operations/extension_spec.rb
|
|
379
381
|
- spec/integration/rack_app/body_parser_spec.rb
|
|
380
382
|
- spec/integration/rack_app/method_override_spec.rb
|
|
381
383
|
- spec/integration/rack_app/middleware_spec.rb
|
|
@@ -455,6 +457,7 @@ files:
|
|
|
455
457
|
- spec/unit/hanami/helpers/form_helper_spec.rb
|
|
456
458
|
- spec/unit/hanami/port_spec.rb
|
|
457
459
|
- spec/unit/hanami/providers/db/config/default_config_spec.rb
|
|
460
|
+
- spec/unit/hanami/providers/db/config/gateway_spec.rb
|
|
458
461
|
- spec/unit/hanami/providers/db/config_spec.rb
|
|
459
462
|
- spec/unit/hanami/router/errors/not_allowed_error_spec.rb
|
|
460
463
|
- spec/unit/hanami/router/errors/not_found_error_spec.rb
|
|
@@ -486,7 +489,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
486
489
|
- !ruby/object:Gem::Version
|
|
487
490
|
version: '0'
|
|
488
491
|
requirements: []
|
|
489
|
-
rubygems_version: 3.5.
|
|
492
|
+
rubygems_version: 3.5.22
|
|
490
493
|
signing_key:
|
|
491
494
|
specification_version: 4
|
|
492
495
|
summary: The web, with simplicity
|
|
@@ -535,6 +538,7 @@ test_files:
|
|
|
535
538
|
- spec/integration/logging/exception_logging_spec.rb
|
|
536
539
|
- spec/integration/logging/notifications_spec.rb
|
|
537
540
|
- spec/integration/logging/request_logging_spec.rb
|
|
541
|
+
- spec/integration/operations/extension_spec.rb
|
|
538
542
|
- spec/integration/rack_app/body_parser_spec.rb
|
|
539
543
|
- spec/integration/rack_app/method_override_spec.rb
|
|
540
544
|
- spec/integration/rack_app/middleware_spec.rb
|
|
@@ -614,6 +618,7 @@ test_files:
|
|
|
614
618
|
- spec/unit/hanami/helpers/form_helper_spec.rb
|
|
615
619
|
- spec/unit/hanami/port_spec.rb
|
|
616
620
|
- spec/unit/hanami/providers/db/config/default_config_spec.rb
|
|
621
|
+
- spec/unit/hanami/providers/db/config/gateway_spec.rb
|
|
617
622
|
- spec/unit/hanami/providers/db/config_spec.rb
|
|
618
623
|
- spec/unit/hanami/router/errors/not_allowed_error_spec.rb
|
|
619
624
|
- spec/unit/hanami/router/errors/not_found_error_spec.rb
|