hanami 2.1.1 → 2.2.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +19 -0
  3. data/README.md +7 -7
  4. data/hanami.gemspec +6 -6
  5. data/lib/hanami/app.rb +5 -1
  6. data/lib/hanami/config/db.rb +33 -0
  7. data/lib/hanami/config.rb +36 -9
  8. data/lib/hanami/extensions/db/repo.rb +103 -0
  9. data/lib/hanami/extensions.rb +4 -0
  10. data/lib/hanami/helpers/form_helper/form_builder.rb +2 -4
  11. data/lib/hanami/provider_registrar.rb +26 -0
  12. data/lib/hanami/providers/assets.rb +2 -20
  13. data/lib/hanami/providers/db/adapter.rb +68 -0
  14. data/lib/hanami/providers/db/adapters.rb +44 -0
  15. data/lib/hanami/providers/db/config.rb +66 -0
  16. data/lib/hanami/providers/db/sql_adapter.rb +80 -0
  17. data/lib/hanami/providers/db.rb +203 -0
  18. data/lib/hanami/providers/db_logging.rb +22 -0
  19. data/lib/hanami/providers/rack.rb +1 -1
  20. data/lib/hanami/providers/relations.rb +31 -0
  21. data/lib/hanami/providers/routes.rb +1 -13
  22. data/lib/hanami/rake_tasks.rb +8 -7
  23. data/lib/hanami/slice.rb +84 -4
  24. data/lib/hanami/version.rb +1 -1
  25. data/lib/hanami.rb +3 -0
  26. data/spec/integration/container/provider_environment_spec.rb +52 -0
  27. data/spec/integration/db/auto_registration_spec.rb +39 -0
  28. data/spec/integration/db/db_inflector_spec.rb +57 -0
  29. data/spec/integration/db/db_slices_spec.rb +327 -0
  30. data/spec/integration/db/db_spec.rb +220 -0
  31. data/spec/integration/db/logging_spec.rb +238 -0
  32. data/spec/integration/db/provider_config_spec.rb +88 -0
  33. data/spec/integration/db/provider_spec.rb +35 -0
  34. data/spec/integration/db/repo_spec.rb +215 -0
  35. data/spec/integration/db/slices_importing_from_parent.rb +130 -0
  36. data/spec/integration/slices/slice_configuration_spec.rb +4 -4
  37. data/spec/support/app_integration.rb +3 -0
  38. data/spec/unit/hanami/config/db_spec.rb +38 -0
  39. data/spec/unit/hanami/config/router_spec.rb +1 -1
  40. data/spec/unit/hanami/helpers/form_helper_spec.rb +31 -0
  41. data/spec/unit/hanami/providers/db/config/default_config_spec.rb +107 -0
  42. data/spec/unit/hanami/providers/db/config_spec.rb +206 -0
  43. data/spec/unit/hanami/slice_spec.rb +32 -0
  44. data/spec/unit/hanami/version_spec.rb +1 -1
  45. metadata +61 -19
@@ -0,0 +1,238 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe "DB / Logging", :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 "logs SQL queries" 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/relations/posts.rb", <<~RUBY
25
+ module TestApp
26
+ module Relations
27
+ class Posts < Hanami::DB::Relation
28
+ schema :posts, infer: true
29
+ end
30
+ end
31
+ end
32
+ RUBY
33
+
34
+ ENV["DATABASE_URL"] = "sqlite::memory"
35
+
36
+ require "hanami/setup"
37
+
38
+ logger_stream = StringIO.new
39
+ Hanami.app.config.logger.stream = logger_stream
40
+
41
+ require "hanami/prepare"
42
+
43
+ Hanami.app.prepare :db
44
+
45
+ # Manually run a migration and add a test record
46
+ gateway = Hanami.app["db.gateway"]
47
+ migration = gateway.migration do
48
+ change do
49
+ create_table :posts do
50
+ primary_key :id
51
+ column :title, :text, null: false
52
+ end
53
+
54
+ create_table :authors do
55
+ primary_key :id
56
+ end
57
+ end
58
+ end
59
+ migration.apply(gateway, :up)
60
+ gateway.connection.execute("INSERT INTO posts (title) VALUES ('Together breakfast')")
61
+
62
+ relation = Hanami.app["relations.posts"]
63
+ expect(relation.select(:title).to_a).to eq [{:title=>"Together breakfast"}]
64
+
65
+ logger_stream.rewind
66
+ log_lines = logger_stream.read.split("\n")
67
+
68
+ expect(log_lines.length).to eq 1
69
+ expect(log_lines.first).to match /Loaded :sqlite in \d+ms SELECT `posts`.`title` FROM `posts` ORDER BY `posts`.`id`/
70
+ end
71
+ end
72
+
73
+ describe "slices sharing app db config" do
74
+ it "logs SQL queries" do
75
+ with_tmp_directory(Dir.mktmpdir) do
76
+ write "config/app.rb", <<~RUBY
77
+ require "hanami"
78
+
79
+ module TestApp
80
+ class App < Hanami::App
81
+ end
82
+ end
83
+ RUBY
84
+
85
+ write "config/providers/db.rb", <<~RUBY
86
+ Hanami.app.configure_provider :db do
87
+ end
88
+ RUBY
89
+
90
+ ENV["DATABASE_URL"] = "sqlite::memory"
91
+
92
+ write "slices/admin/relations/posts.rb", <<~RUBY
93
+ module Admin
94
+ module Relations
95
+ class Posts < Hanami::DB::Relation
96
+ schema :posts, infer: true
97
+ end
98
+ end
99
+ end
100
+ RUBY
101
+
102
+ write "slices/main/relations/posts.rb", <<~RUBY
103
+ module Main
104
+ module Relations
105
+ class Posts < Hanami::DB::Relation
106
+ schema :posts, infer: true
107
+ end
108
+ end
109
+ end
110
+ RUBY
111
+
112
+ require "hanami/setup"
113
+
114
+ logger_stream = StringIO.new
115
+ Hanami.app.config.logger.stream = logger_stream
116
+
117
+ require "hanami/prepare"
118
+
119
+ Admin::Slice.prepare :db
120
+
121
+ # Manually run a migration
122
+ gateway = Admin::Slice["db.gateway"]
123
+ migration = gateway.migration do
124
+ change do
125
+ create_table :posts do
126
+ primary_key :id
127
+ column :title, :text, null: false
128
+ end
129
+ end
130
+ end
131
+ migration.apply(gateway, :up)
132
+ gateway.connection.execute("INSERT INTO posts (title) VALUES ('Together breakfast')")
133
+
134
+ Hanami.app.boot
135
+
136
+ # Booting the app will have the ROM schemas infer themself via some `PRAGMA` queries to the
137
+ # database, which themselves will emit logs. Clear those logs, since we want to focus on
138
+ # individual query logging in this test.
139
+ logger_stream.truncate(0)
140
+
141
+ relation = Admin::Slice["relations.posts"]
142
+ relation.select(:title).to_a
143
+
144
+ log_lines = logger_stream.string.split("\n")
145
+ expect(log_lines.length).to eq 1
146
+ expect(log_lines.last).to match /Loaded :sqlite in \d+ms SELECT `posts`.`title` FROM `posts` ORDER BY `posts`.`id`/
147
+
148
+ relation = Main::Slice["relations.posts"]
149
+ relation.select(:id).to_a
150
+
151
+ log_lines = logger_stream.string.split("\n")
152
+ expect(log_lines.length).to eq 2
153
+ expect(log_lines.last).to match /Loaded :sqlite in \d+ms SELECT `posts`.`id` FROM `posts` ORDER BY `posts`.`id`/
154
+ end
155
+ end
156
+ end
157
+
158
+ describe "slices with independent db config" do
159
+ # This is the same test as above, except without the config/providers/db.rb file.
160
+ it "logs SQL queries" do
161
+ with_tmp_directory(Dir.mktmpdir) do
162
+ write "config/app.rb", <<~RUBY
163
+ require "hanami"
164
+
165
+ module TestApp
166
+ class App < Hanami::App
167
+ end
168
+ end
169
+ RUBY
170
+
171
+ ENV["DATABASE_URL"] = "sqlite::memory"
172
+
173
+ write "slices/admin/relations/posts.rb", <<~RUBY
174
+ module Admin
175
+ module Relations
176
+ class Posts < Hanami::DB::Relation
177
+ schema :posts, infer: true
178
+ end
179
+ end
180
+ end
181
+ RUBY
182
+
183
+ write "slices/main/relations/posts.rb", <<~RUBY
184
+ module Main
185
+ module Relations
186
+ class Posts < Hanami::DB::Relation
187
+ schema :posts, infer: true
188
+ end
189
+ end
190
+ end
191
+ RUBY
192
+
193
+ require "hanami/setup"
194
+
195
+ logger_stream = StringIO.new
196
+ Hanami.app.config.logger.stream = logger_stream
197
+
198
+ require "hanami/prepare"
199
+
200
+ Admin::Slice.prepare :db
201
+
202
+ # Manually run a migration
203
+ gateway = Admin::Slice["db.gateway"]
204
+ migration = gateway.migration do
205
+ change do
206
+ create_table :posts do
207
+ primary_key :id
208
+ column :title, :text, null: false
209
+ end
210
+ end
211
+ end
212
+ migration.apply(gateway, :up)
213
+ gateway.connection.execute("INSERT INTO posts (title) VALUES ('Together breakfast')")
214
+
215
+ Hanami.app.boot
216
+
217
+ # Booting the app will have the ROM schemas infer themself via some `PRAGMA` queries to the
218
+ # database, which themselves will emit logs. Clear those logs, since we want to focus on
219
+ # individual query logging in this test.
220
+ logger_stream.truncate(0)
221
+
222
+ relation = Admin::Slice["relations.posts"]
223
+ relation.select(:title).to_a
224
+
225
+ log_lines = logger_stream.string.split("\n")
226
+ expect(log_lines.length).to eq 1
227
+ expect(log_lines.last).to match /Loaded :sqlite in \d+ms SELECT `posts`.`title` FROM `posts` ORDER BY `posts`.`id`/
228
+
229
+ relation = Main::Slice["relations.posts"]
230
+ relation.select(:id).to_a
231
+
232
+ log_lines = logger_stream.string.split("\n")
233
+ expect(log_lines.length).to eq 2
234
+ expect(log_lines.last).to match /Loaded :sqlite in \d+ms SELECT `posts`.`id` FROM `posts` ORDER BY `posts`.`id`/
235
+ end
236
+ end
237
+ end
238
+ end
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe "DB / Provider / Config", :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
+ describe "default config" do
14
+ it "provides default plugins and extensions" do
15
+ with_tmp_directory(Dir.mktmpdir) do
16
+ write "config/app.rb", <<~RUBY
17
+ require "hanami"
18
+
19
+ module TestApp
20
+ class App < Hanami::App
21
+ end
22
+ end
23
+ RUBY
24
+
25
+ write "config/db/.keep", ""
26
+
27
+ ENV["DATABASE_URL"] = "sqlite::memory"
28
+
29
+ require "hanami/prepare"
30
+
31
+ Hanami.app.prepare :db
32
+
33
+ plugins = Hanami.app["db.config"].setup.plugins
34
+ expect(plugins).to match [
35
+ an_object_satisfying {
36
+ _1.name == :instrumentation && _1.type == :relation &&
37
+ _1.config.notifications == Hanami.app["notifications"]
38
+ },
39
+ an_object_satisfying { _1.name == :auto_restrictions && _1.type == :relation }
40
+ ]
41
+
42
+ extensions = Hanami.app["db.gateway"].options[:extensions]
43
+ expect(extensions).to eq [:caller_logging, :error_sql, :sql_comments]
44
+ end
45
+ end
46
+ end
47
+
48
+ it "evaluates plugin config blocks in the context of the provider" do
49
+ with_tmp_directory(Dir.mktmpdir) do
50
+ write "config/app.rb", <<~RUBY
51
+ require "hanami"
52
+
53
+ module TestApp
54
+ class App < Hanami::App
55
+ end
56
+ end
57
+ RUBY
58
+
59
+ write "config/providers/db.rb", <<~RUBY
60
+ Hanami.app.configure_provider :db do
61
+ config.adapter :sql do |a|
62
+ a.skip_defaults :plugins
63
+
64
+ a.plugin relations: :instrumentation do |plugin|
65
+ plugin.notifications = target["custom_notifications"]
66
+ end
67
+ end
68
+ end
69
+ RUBY
70
+
71
+ write "app/custom_notifications.rb", <<~RUBY
72
+ module TestApp
73
+ class CustomNotifications
74
+ end
75
+ end
76
+ RUBY
77
+
78
+ ENV["DATABASE_URL"] = "sqlite::memory"
79
+
80
+ require "hanami/prepare"
81
+
82
+ Hanami.app.prepare :db
83
+
84
+ plugin = Hanami.app["db.config"].setup.plugins.find { _1.name == :instrumentation }
85
+ expect(plugin.config.notifications).to be_an_instance_of TestApp::CustomNotifications
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe "DB / Provider", :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 "is registered when only a config/db/ dir exists" 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 "config/db/.keep", ""
25
+
26
+ ENV["DATABASE_URL"] = "sqlite::memory"
27
+
28
+ require "hanami/prepare"
29
+
30
+ Hanami.app.prepare :db
31
+
32
+ expect(Hanami.app["db.gateway"]).to be
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,215 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe "DB / Repo", :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
+ specify "repos have a root inferred from their name, or can set their own" 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/repo.rb", <<~RUBY
25
+ module TestApp
26
+ class Repo < Hanami::DB::Repo
27
+ end
28
+ end
29
+ RUBY
30
+
31
+ write "app/relations/posts.rb", <<~RUBY
32
+ module TestApp
33
+ module Relations
34
+ class Posts < Hanami::DB::Relation
35
+ schema :posts, infer: true
36
+ end
37
+ end
38
+ end
39
+ RUBY
40
+
41
+ write "app/repos/post_repo.rb", <<~RUBY
42
+ module TestApp
43
+ module Repos
44
+ class PostRepo < Repo
45
+ def get(id)
46
+ posts.by_pk(id).one!
47
+ end
48
+ end
49
+ end
50
+ end
51
+ RUBY
52
+
53
+ write "app/repos/no_implicit_root_relation_repo.rb", <<~RUBY
54
+ module TestApp
55
+ module Repos
56
+ class NoImplicitRootRelationRepo < Repo
57
+ end
58
+ end
59
+ end
60
+ RUBY
61
+
62
+ write "app/repos/explicit_root_relation_repo.rb", <<~RUBY
63
+ module TestApp
64
+ module Repos
65
+ class ExplicitRootRelationRepo < Repo[:posts]
66
+ end
67
+ end
68
+ end
69
+ RUBY
70
+
71
+ ENV["DATABASE_URL"] = "sqlite::memory"
72
+
73
+ require "hanami/prepare"
74
+
75
+ Hanami.app.prepare :db
76
+
77
+ # Manually run a migration and add a test record
78
+ gateway = Hanami.app["db.gateway"]
79
+ migration = gateway.migration do
80
+ change do
81
+ # drop_table? :posts
82
+ create_table :posts do
83
+ primary_key :id
84
+ column :title, :text, null: false
85
+ end
86
+ end
87
+ end
88
+ migration.apply(gateway, :up)
89
+ gateway.connection.execute("INSERT INTO posts (title) VALUES ('Together breakfast')")
90
+
91
+ # Repos use a matching root relation automatically
92
+ repo = Hanami.app["repos.post_repo"]
93
+ expect(repo.get(1).title).to eq "Together breakfast"
94
+ expect(repo.root).to eql Hanami.app["relations.posts"]
95
+
96
+ # Non-matching repos still work, just with no root relation
97
+ repo = Hanami.app["repos.no_implicit_root_relation_repo"]
98
+ expect(repo.root).to be nil
99
+
100
+ # Repos can provide an explicit root relation
101
+ repo = Hanami.app["repos.explicit_root_relation_repo"]
102
+ expect(repo.root).to eql Hanami.app["relations.posts"]
103
+ end
104
+ end
105
+
106
+ specify "repos use relations and structs only from their own slice" do
107
+ with_tmp_directory(Dir.mktmpdir) do
108
+ write "config/app.rb", <<~RUBY
109
+ require "hanami"
110
+
111
+ module TestApp
112
+ class App < Hanami::App
113
+ end
114
+ end
115
+ RUBY
116
+
117
+ ENV["DATABASE_URL"] = "sqlite::memory"
118
+
119
+ write "slices/admin/db/struct.rb", <<~RUBY
120
+ module Admin
121
+ module DB
122
+ class Struct < Hanami::DB::Struct
123
+ end
124
+ end
125
+ end
126
+ RUBY
127
+
128
+ write "slices/admin/relations/posts.rb", <<~RUBY
129
+ module Admin
130
+ module Relations
131
+ class Posts < Hanami::DB::Relation
132
+ schema :posts, infer: true
133
+ end
134
+ end
135
+ end
136
+ RUBY
137
+
138
+ write "slices/admin/repo.rb", <<~RUBY
139
+ module Admin
140
+ class Repo < Hanami::DB::Repo
141
+ end
142
+ end
143
+ RUBY
144
+
145
+ write "slices/admin/repos/post_repo.rb", <<~RUBY
146
+ module Admin
147
+ module Repos
148
+ class PostRepo < Repo
149
+ end
150
+ end
151
+ end
152
+ RUBY
153
+
154
+ write "slices/admin/structs/post.rb", <<~RUBY
155
+ module Admin
156
+ module Structs
157
+ class Post < DB::Struct
158
+ end
159
+ end
160
+ end
161
+ RUBY
162
+
163
+ write "slices/main/relations/posts.rb", <<~RUBY
164
+ module Main
165
+ module Relations
166
+ class Posts < Hanami::DB::Relation
167
+ schema :posts, infer: true
168
+ end
169
+ end
170
+ end
171
+ RUBY
172
+
173
+ write "slices/main/repo.rb", <<~RUBY
174
+ module Main
175
+ class Repo < Hanami::DB::Repo
176
+ end
177
+ end
178
+ RUBY
179
+
180
+ write "slices/main/repos/post_repo.rb", <<~RUBY
181
+ module Main
182
+ module Repos
183
+ class PostRepo < Repo
184
+ end
185
+ end
186
+ end
187
+ RUBY
188
+
189
+ require "hanami/prepare"
190
+
191
+ Admin::Slice.prepare :db
192
+
193
+ # Manually run a migration
194
+ gateway = Admin::Slice["db.gateway"]
195
+ migration = gateway.migration do
196
+ change do
197
+ # drop_table? :posts
198
+ create_table :posts do
199
+ primary_key :id
200
+ column :title, :text, null: false
201
+ end
202
+ end
203
+ end
204
+ migration.apply(gateway, :up)
205
+ gateway.connection.execute("INSERT INTO posts (title) VALUES ('Together breakfast')")
206
+
207
+ expect(Admin::Slice["repos.post_repo"].posts).to eql Admin::Slice["relations.posts"]
208
+ expect(Admin::Slice["repos.post_repo"].posts.by_pk(1).one!.class).to be < Admin::Structs::Post
209
+
210
+ expect(Main::Slice["repos.post_repo"].posts).to eql Main::Slice["relations.posts"]
211
+ # Slice struct namespace used even when no concrete struct classes are defined
212
+ expect(Main::Slice["repos.post_repo"].posts.by_pk(1).one!.class).to be < Main::Structs::Post
213
+ end
214
+ end
215
+ end
@@ -0,0 +1,130 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe "DB / Slices / Importing from app", :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
+ specify "app DB components do not import into slices by default" 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/relations/posts.rb", <<~RUBY
25
+ module TestApp
26
+ module Relations
27
+ class Posts < Hanami::DB::Relation
28
+ schema :posts, infer: true
29
+ end
30
+ end
31
+ end
32
+ RUBY
33
+
34
+ write "slices/admin/.keep", ""
35
+
36
+ require "hanami/prepare"
37
+
38
+ expect { Admin::Slice.start :db }.to raise_error Dry::System::ProviderNotFoundError
39
+ end
40
+ end
41
+
42
+ specify "importing app DB components into slices via config.db.import_from_parent = true" do
43
+ with_tmp_directory(Dir.mktmpdir) do
44
+ write "config/app.rb", <<~RUBY
45
+ require "hanami"
46
+
47
+ module TestApp
48
+ class App < Hanami::App
49
+ config.db.import_from_parent = true
50
+ end
51
+ end
52
+ RUBY
53
+
54
+ write "app/relations/posts.rb", <<~RUBY
55
+ module TestApp
56
+ module Relations
57
+ class Posts < Hanami::DB::Relation
58
+ schema :posts, infer: true
59
+ end
60
+ end
61
+ end
62
+ RUBY
63
+
64
+ write "slices/admin/.keep", ""
65
+
66
+ ENV["DATABASE_URL"] = "sqlite::memory"
67
+
68
+ require "hanami/prepare"
69
+
70
+ Hanami.app.prepare :db
71
+
72
+ # Manually run a migration and add a test record
73
+ gateway = Hanami.app["db.gateway"]
74
+ migration = gateway.migration do
75
+ change do
76
+ # drop_table? :posts
77
+ create_table :posts do
78
+ primary_key :id
79
+ column :title, :text, null: false
80
+ end
81
+ end
82
+ end
83
+ migration.apply(gateway, :up)
84
+ gateway.connection.execute("INSERT INTO posts (title) VALUES ('Together breakfast')")
85
+
86
+ Admin::Slice.start :db
87
+
88
+ expect(Admin::Slice["db.rom"]).to be(Hanami.app["db.rom"])
89
+ expect(Admin::Slice["relations.posts"]).to be(Hanami.app["relations.posts"])
90
+
91
+ expect(Admin::Slice["relations.posts"].to_a).to eq [{id: 1, title: "Together breakfast"}]
92
+ end
93
+ end
94
+
95
+ specify "disabling import of the DB components within a specific slice" do
96
+ with_tmp_directory(Dir.mktmpdir) do
97
+ write "config/app.rb", <<~RUBY
98
+ require "hanami"
99
+
100
+ module TestApp
101
+ class App < Hanami::App
102
+ config.db.import_from_parent = true
103
+ end
104
+ end
105
+ RUBY
106
+
107
+ write "config/slices/admin.rb", <<~RUBY
108
+ module Admin
109
+ class Slice < Hanami::Slice
110
+ config.db.import_from_parent = false
111
+ end
112
+ end
113
+ RUBY
114
+
115
+ write "app/relations/posts.rb", <<~RUBY
116
+ module TestApp
117
+ module Relations
118
+ class Posts < Hanami::DB::Relation
119
+ schema :posts, infer: true
120
+ end
121
+ end
122
+ end
123
+ RUBY
124
+
125
+ require "hanami/prepare"
126
+
127
+ expect { Admin::Slice.start :db }.to raise_error Dry::System::ProviderNotFoundError
128
+ end
129
+ end
130
+ end