senro_usecaser 0.1.0

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.
@@ -0,0 +1,751 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # rubocop:disable all
5
+
6
+ # rbs_inline: enabled
7
+
8
+ require_relative "../lib/senro_usecaser"
9
+
10
+ # =============================================================================
11
+ # サンプル: Namespace を活用したマルチドメインシステム
12
+ # =============================================================================
13
+ #
14
+ # このサンプルでは以下の Namespace 機能を検証します:
15
+ # 1. 基本的な namespace でのサービス登録
16
+ # 2. ネストした namespace (admin::reports)
17
+ # 3. namespace のフォールバック(子から親へ)
18
+ # 4. UseCase での namespace 指定(自動解決)
19
+ # 5. resolve_in による明示的な namespace 解決
20
+ # 6. Scoped Container と namespace の組み合わせ
21
+ # 7. infer_namespace_from_module によるモジュール名からの namespace 自動推論
22
+ #
23
+ # =============================================================================
24
+
25
+ # サンプル全体を NamespaceDemo モジュールで囲み、
26
+ # 他のサンプル(order_system.rb)とのクラス名衝突を回避
27
+ module NamespaceDemo
28
+ # ===========================================================================
29
+ # モデル
30
+ # ===========================================================================
31
+
32
+ class User
33
+ #: Integer
34
+ attr_reader :id
35
+
36
+ #: String
37
+ attr_reader :name
38
+
39
+ #: String
40
+ attr_reader :role
41
+
42
+ #: (id: Integer, name: String, role: String) -> void
43
+ def initialize(id:, name:, role:)
44
+ @id = id
45
+ @name = name
46
+ @role = role
47
+ end
48
+ end
49
+
50
+ class AuditLog
51
+ #: String
52
+ attr_reader :action
53
+
54
+ #: User
55
+ attr_reader :performed_by
56
+
57
+ #: Time
58
+ attr_reader :timestamp
59
+
60
+ #: (action: String, performed_by: User, timestamp: Time) -> void
61
+ def initialize(action:, performed_by:, timestamp:)
62
+ @action = action
63
+ @performed_by = performed_by
64
+ @timestamp = timestamp
65
+ end
66
+ end
67
+
68
+ # ===========================================================================
69
+ # 共有インターフェース
70
+ # ===========================================================================
71
+
72
+ # 全 namespace で共有されるロガー
73
+ class Logger
74
+ #: String
75
+ attr_reader :prefix
76
+
77
+ #: (?String) -> void
78
+ def initialize(prefix = "[LOG]")
79
+ @prefix = prefix
80
+ end
81
+
82
+ #: (String) -> void
83
+ def info(message)
84
+ puts " #{@prefix} #{message}"
85
+ end
86
+ end
87
+
88
+ # ===========================================================================
89
+ # Public 用のサービス実装
90
+ # ===========================================================================
91
+
92
+ module Public
93
+ class UserRepository
94
+ #: () -> void
95
+ def initialize
96
+ @users = {
97
+ 1 => User.new(id: 1, name: "一般ユーザーA", role: "user"),
98
+ 2 => User.new(id: 2, name: "一般ユーザーB", role: "user")
99
+ } #: Hash[Integer, User]
100
+ end
101
+
102
+ #: (Integer) -> User?
103
+ def find(id)
104
+ @users[id]
105
+ end
106
+
107
+ #: () -> Array[User]
108
+ def all
109
+ @users.values
110
+ end
111
+ end
112
+
113
+ class NotificationService
114
+ #: (User, String) -> bool
115
+ def notify(user, message)
116
+ puts " [Public Notification] #{user.name}: #{message}"
117
+ true
118
+ end
119
+ end
120
+ end
121
+
122
+ # ===========================================================================
123
+ # Admin 用のサービス実装
124
+ # ===========================================================================
125
+
126
+ module Admin
127
+ class UserRepository
128
+ #: () -> void
129
+ def initialize
130
+ @users = {
131
+ 100 => User.new(id: 100, name: "管理者A", role: "admin"),
132
+ 101 => User.new(id: 101, name: "管理者B", role: "super_admin")
133
+ } #: Hash[Integer, User]
134
+ end
135
+
136
+ #: (Integer) -> User?
137
+ def find(id)
138
+ @users[id]
139
+ end
140
+
141
+ #: () -> Array[User]
142
+ def all
143
+ @users.values
144
+ end
145
+
146
+ # Admin 専用: ユーザーの全情報を取得
147
+ #: (Integer) -> Hash[Symbol, untyped]?
148
+ def find_with_permissions(id)
149
+ user = @users[id]
150
+ return nil unless user
151
+
152
+ {
153
+ user: user,
154
+ permissions: user.role == "super_admin" ? [:all] : %i[read write],
155
+ last_login: Time.now - 3600
156
+ }
157
+ end
158
+ end
159
+
160
+ class NotificationService
161
+ #: (User, String) -> bool
162
+ def notify(user, message)
163
+ puts " [Admin Notification] [PRIORITY] #{user.name}: #{message}"
164
+ true
165
+ end
166
+ end
167
+
168
+ class AuditLogger
169
+ #: () -> void
170
+ def initialize
171
+ @logs = [] #: Array[AuditLog]
172
+ end
173
+
174
+ #: (action: String, performed_by: User) -> AuditLog
175
+ def log(action:, performed_by:)
176
+ entry = AuditLog.new(action: action, performed_by: performed_by, timestamp: Time.now)
177
+ @logs << entry
178
+ puts " [Audit] #{performed_by.name}: #{action}"
179
+ entry
180
+ end
181
+
182
+ #: () -> Array[AuditLog]
183
+ def recent_logs
184
+ @logs.last(10)
185
+ end
186
+ end
187
+ end
188
+
189
+ # ===========================================================================
190
+ # Admin::Reports 用のサービス実装(ネストした namespace)
191
+ # ===========================================================================
192
+
193
+ module Admin
194
+ module Reports
195
+ class ReportGenerator
196
+ #: (String, Hash[Symbol, untyped]) -> String
197
+ def generate(type, data)
198
+ puts " [ReportGenerator] レポート生成: #{type}"
199
+ "Report: #{type} - #{data.keys.join(", ")}"
200
+ end
201
+ end
202
+
203
+ class ReportExporter
204
+ #: (String, Symbol) -> String
205
+ def export(report, format)
206
+ puts " [ReportExporter] エクスポート: #{format}"
207
+ "#{report} (#{format}形式)"
208
+ end
209
+ end
210
+ end
211
+ end
212
+
213
+ # ===========================================================================
214
+ # Provider 定義
215
+ # ===========================================================================
216
+
217
+ # 共有サービス(ルート namespace)
218
+ class CoreProvider < SenroUsecaser::Provider
219
+ #: (SenroUsecaser::Container) -> void
220
+ def register(container)
221
+ container.register(:logger, Logger.new)
222
+ end
223
+ end
224
+
225
+ # ===========================================================================
226
+ # パターン1: Provider の namespace DSL を使用
227
+ # ===========================================================================
228
+ # メリット: シンプル、Provider レベルで namespace を宣言
229
+ # デメリット: Steep の型チェックでエラーが出る場合がある
230
+
231
+ # Public namespace のサービス(namespace DSL 使用)
232
+ class PublicProvider < SenroUsecaser::Provider
233
+ namespace :public
234
+ depends_on CoreProvider
235
+
236
+ #: (SenroUsecaser::Container) -> void
237
+ def register(container)
238
+ container.register_singleton(:user_repository) { |_c| Public::UserRepository.new }
239
+ container.register_singleton(:notification_service) { |_c| Public::NotificationService.new }
240
+ end
241
+ end
242
+
243
+ # ===========================================================================
244
+ # パターン2: Container の namespace メソッドを直接使用
245
+ # ===========================================================================
246
+ # メリット: 型チェックが通りやすい、柔軟なネスト構造が可能
247
+ # デメリット: やや冗長
248
+
249
+ # Admin namespace のサービス(Container.namespace 直接使用)
250
+ class AdminProvider < SenroUsecaser::Provider
251
+ depends_on CoreProvider
252
+
253
+ #: (SenroUsecaser::Container) -> void
254
+ def register(container)
255
+ container.namespace(:admin) do
256
+ # @type self: SenroUsecaser::Container
257
+ register_singleton(:user_repository) { |_c| Admin::UserRepository.new }
258
+ register_singleton(:notification_service) { |_c| Admin::NotificationService.new }
259
+ register_singleton(:audit_logger) { |_c| Admin::AuditLogger.new }
260
+ end
261
+ end
262
+
263
+ #: (SenroUsecaser::Container) -> void
264
+ def after_boot(container)
265
+ logger = container.resolve(:logger) #: Logger
266
+ logger.info("AdminProvider: 管理者サービス初期化完了")
267
+ end
268
+ end
269
+
270
+ # Admin::Reports namespace のサービス(Container.namespace ネスト使用)
271
+ class AdminReportsProvider < SenroUsecaser::Provider
272
+ depends_on AdminProvider
273
+
274
+ #: (SenroUsecaser::Container) -> void
275
+ def register(container)
276
+ container.namespace(:admin) do
277
+ # @type self: SenroUsecaser::Container
278
+ namespace(:reports) do
279
+ # @type self: SenroUsecaser::Container
280
+ register_singleton(:report_generator) { |_c| Admin::Reports::ReportGenerator.new }
281
+ register_singleton(:report_exporter) { |_c| Admin::Reports::ReportExporter.new }
282
+ end
283
+ end
284
+ end
285
+ end
286
+
287
+ # ===========================================================================
288
+ # UseCase 定義
289
+ # ===========================================================================
290
+
291
+ # Public namespace の UseCase
292
+ class ListPublicUsersUseCase < SenroUsecaser::Base
293
+ namespace :public
294
+
295
+ class Output
296
+ #: (users: Array[User]) -> void
297
+ def initialize(users:)
298
+ @users = users #: Array[User]
299
+ end
300
+
301
+ #: () -> Array[User]
302
+ attr_reader :users
303
+ end
304
+
305
+ depends_on :user_repository, Public::UserRepository
306
+ depends_on :logger, Logger # ルートからフォールバック解決される
307
+
308
+ # @rbs!
309
+ # def user_repository: () -> Public::UserRepository
310
+ # def logger: () -> Logger
311
+
312
+ output Output
313
+
314
+ #: (?untyped, **untyped) -> SenroUsecaser::Result[Output]
315
+ def call(_input = nil, **_args)
316
+ logger.info("Public ユーザー一覧を取得")
317
+ users = user_repository.all
318
+ success(Output.new(users: users))
319
+ end
320
+ end
321
+
322
+ # Admin namespace の UseCase
323
+ class ListAdminUsersUseCase < SenroUsecaser::Base
324
+ namespace :admin
325
+
326
+ class Output
327
+ #: (users: Array[User]) -> void
328
+ def initialize(users:)
329
+ @users = users #: Array[User]
330
+ end
331
+
332
+ #: () -> Array[User]
333
+ attr_reader :users
334
+ end
335
+
336
+ depends_on :user_repository, Admin::UserRepository
337
+ depends_on :audit_logger, Admin::AuditLogger
338
+ depends_on :logger, Logger # ルートからフォールバック解決される
339
+
340
+ # @rbs!
341
+ # def user_repository: () -> Admin::UserRepository
342
+ # def audit_logger: () -> Admin::AuditLogger
343
+ # def logger: () -> Logger
344
+
345
+ output Output
346
+
347
+ #: (?untyped, **untyped) -> SenroUsecaser::Result[Output]
348
+ def call(_input = nil, **_args)
349
+ logger.info("Admin ユーザー一覧を取得")
350
+
351
+ # 管理者操作なので監査ログを記録
352
+ admin = user_repository.find(100)
353
+ audit_logger.log(action: "list_admin_users", performed_by: admin) if admin
354
+
355
+ users = user_repository.all
356
+ success(Output.new(users: users))
357
+ end
358
+ end
359
+
360
+ # Admin::Reports namespace の UseCase(ネストした namespace)
361
+ class GenerateUserReportUseCase < SenroUsecaser::Base
362
+ namespace "admin::reports"
363
+
364
+ class Input
365
+ #: (report_type: String) -> void
366
+ def initialize(report_type:)
367
+ @report_type = report_type #: String
368
+ end
369
+
370
+ #: () -> String
371
+ attr_reader :report_type
372
+ end
373
+
374
+ class Output
375
+ #: (report: String) -> void
376
+ def initialize(report:)
377
+ @report = report #: String
378
+ end
379
+
380
+ #: () -> String
381
+ attr_reader :report
382
+ end
383
+
384
+ depends_on :report_generator, Admin::Reports::ReportGenerator
385
+ depends_on :report_exporter, Admin::Reports::ReportExporter
386
+ depends_on :user_repository, Admin::UserRepository # admin namespace からフォールバック
387
+ depends_on :audit_logger, Admin::AuditLogger # admin namespace からフォールバック
388
+ depends_on :logger, Logger # ルートからフォールバック
389
+
390
+ # @rbs!
391
+ # def report_generator: () -> Admin::Reports::ReportGenerator
392
+ # def report_exporter: () -> Admin::Reports::ReportExporter
393
+ # def user_repository: () -> Admin::UserRepository
394
+ # def audit_logger: () -> Admin::AuditLogger
395
+ # def logger: () -> Logger
396
+
397
+ input Input
398
+ output Output
399
+
400
+ #: (Input) -> SenroUsecaser::Result[Output]
401
+ def call(input)
402
+ logger.info("レポート生成開始: #{input.report_type}")
403
+
404
+ users = user_repository.all
405
+ report = report_generator.generate(input.report_type, { users: users, count: users.length })
406
+ exported = report_exporter.export(report, :pdf)
407
+
408
+ admin = user_repository.find(100)
409
+ audit_logger.log(action: "generate_report:#{input.report_type}", performed_by: admin) if admin
410
+
411
+ success(Output.new(report: exported))
412
+ end
413
+ end
414
+
415
+ # リクエストスコープで current_user を注入しつつ、namespace を活用
416
+ class AdminActionUseCase < SenroUsecaser::Base
417
+ namespace :admin
418
+
419
+ class Output
420
+ #: (message: String) -> void
421
+ def initialize(message:)
422
+ @message = message #: String
423
+ end
424
+
425
+ #: () -> String
426
+ attr_reader :message
427
+ end
428
+
429
+ depends_on :current_user, User
430
+ depends_on :audit_logger, Admin::AuditLogger
431
+ depends_on :notification_service, Admin::NotificationService
432
+
433
+ # @rbs!
434
+ # def current_user: () -> User
435
+ # def audit_logger: () -> Admin::AuditLogger
436
+ # def notification_service: () -> Admin::NotificationService
437
+
438
+ output Output
439
+
440
+ #: (?untyped, **untyped) -> SenroUsecaser::Result[Output]
441
+ def call(_input = nil, **_args)
442
+ audit_logger.log(action: "admin_action", performed_by: current_user)
443
+ notification_service.notify(current_user, "アクションを実行しました")
444
+ success(Output.new(message: "#{current_user.name} がアクションを実行"))
445
+ end
446
+ end
447
+ end
448
+
449
+ # =============================================================================
450
+ # infer_namespace_from_module のデモ用 UseCase
451
+ # =============================================================================
452
+ # NamespaceDemo モジュールの外に定義することで、
453
+ # モジュール名がそのまま namespace として推論される
454
+
455
+ # Public::InferredUseCase → namespace "public" として推論
456
+ module Public
457
+ class InferredUseCase < SenroUsecaser::Base
458
+ # namespace を明示的に設定しない!
459
+ # infer_namespace_from_module = true の場合、モジュール名 "Public" から
460
+ # namespace "public" が自動的に推論される
461
+
462
+ class Output
463
+ #: (message: String) -> void
464
+ def initialize(message:)
465
+ @message = message #: String
466
+ end
467
+
468
+ #: () -> String
469
+ attr_reader :message
470
+ end
471
+
472
+ depends_on :user_repository, NamespaceDemo::Public::UserRepository
473
+ depends_on :logger, NamespaceDemo::Logger
474
+
475
+ # @rbs!
476
+ # def user_repository: () -> NamespaceDemo::Public::UserRepository
477
+ # def logger: () -> NamespaceDemo::Logger
478
+
479
+ output Output
480
+
481
+ #: (?untyped, **untyped) -> SenroUsecaser::Result[Output]
482
+ def call(_input = nil, **_args)
483
+ logger.info("InferredUseCase: namespace を自動推論して実行")
484
+ users = user_repository.all
485
+ success(Output.new(message: "#{users.length} 人のユーザーを取得(namespace 自動推論)"))
486
+ end
487
+ end
488
+ end
489
+
490
+ # Admin::Reports::InferredReportUseCase → namespace "admin::reports" として推論
491
+ module Admin
492
+ module Reports
493
+ class InferredReportUseCase < SenroUsecaser::Base
494
+ # namespace を明示的に設定しない!
495
+ # infer_namespace_from_module = true の場合、モジュール名から
496
+ # namespace "admin::reports" が自動的に推論される
497
+
498
+ class Output
499
+ #: (message: String) -> void
500
+ def initialize(message:)
501
+ @message = message #: String
502
+ end
503
+
504
+ #: () -> String
505
+ attr_reader :message
506
+ end
507
+
508
+ depends_on :report_generator, NamespaceDemo::Admin::Reports::ReportGenerator
509
+ depends_on :user_repository, NamespaceDemo::Admin::UserRepository
510
+ depends_on :logger, NamespaceDemo::Logger
511
+
512
+ # @rbs!
513
+ # def report_generator: () -> NamespaceDemo::Admin::Reports::ReportGenerator
514
+ # def user_repository: () -> NamespaceDemo::Admin::UserRepository
515
+ # def logger: () -> NamespaceDemo::Logger
516
+
517
+ output Output
518
+
519
+ #: (?untyped, **untyped) -> SenroUsecaser::Result[Output]
520
+ def call(_input = nil, **_args)
521
+ logger.info("InferredReportUseCase: ネストした namespace を自動推論して実行")
522
+ users = user_repository.all
523
+ report = report_generator.generate("inferred_report", { count: users.length })
524
+ success(Output.new(message: "レポート生成完了: #{report}(namespace 自動推論)"))
525
+ end
526
+ end
527
+ end
528
+ end
529
+
530
+ # =============================================================================
531
+ # infer_namespace_from_module を使った Provider のデモ
532
+ # =============================================================================
533
+ # Provider もモジュール名から namespace を自動推論できる
534
+
535
+ # Inferred::ServiceProvider → namespace "inferred" として推論
536
+ module Inferred
537
+ class ServiceProvider < SenroUsecaser::Provider
538
+ # namespace を明示的に設定しない!
539
+ # infer_namespace_from_module = true の場合、モジュール名 "Inferred" から
540
+ # namespace "inferred" が自動的に推論される
541
+
542
+ #: (SenroUsecaser::Container) -> void
543
+ def register(container)
544
+ container.register(:inferred_service, "This service was registered in inferred namespace")
545
+ end
546
+ end
547
+ end
548
+
549
+ # =============================================================================
550
+ # テスト実行
551
+ # =============================================================================
552
+
553
+ puts "=" * 70
554
+ puts "SenroUsecaser Namespace デモ"
555
+ puts "=" * 70
556
+ puts
557
+
558
+ # 状態をリセット
559
+ SenroUsecaser.reset!
560
+
561
+ # Provider を設定
562
+ SenroUsecaser.configure do |config|
563
+ config.providers = [
564
+ NamespaceDemo::CoreProvider,
565
+ NamespaceDemo::PublicProvider,
566
+ NamespaceDemo::AdminProvider,
567
+ NamespaceDemo::AdminReportsProvider
568
+ ]
569
+ end
570
+
571
+ puts "1. Provider の起動とnamespace登録"
572
+ puts "-" * 70
573
+ SenroUsecaser.boot!
574
+ puts
575
+
576
+ # -----------------------------------------------------------------------------
577
+ puts "2. Container の namespace 構造確認"
578
+ puts "-" * 70
579
+
580
+ container = SenroUsecaser.container
581
+ puts " 登録済みキー:"
582
+ container.keys.sort.each do |key|
583
+ puts " - #{key}"
584
+ end
585
+ puts
586
+
587
+ # -----------------------------------------------------------------------------
588
+ puts "3. namespace フォールバック確認"
589
+ puts "-" * 70
590
+
591
+ # admin namespace から logger(ルートに登録)を解決
592
+ puts " admin namespace から logger を解決:"
593
+ admin_logger = container.resolve_in(:admin, :logger) #: NamespaceDemo::Logger
594
+ admin_logger.info("admin namespace から解決された logger です")
595
+
596
+ # admin::reports namespace から audit_logger(admin に登録)を解決
597
+ puts " admin::reports namespace から audit_logger を解決:"
598
+ reports_audit_logger = container.resolve_in("admin::reports", :audit_logger) #: NamespaceDemo::Admin::AuditLogger
599
+ admin = container.resolve_in(:admin, :user_repository).find(100) #: NamespaceDemo::User?
600
+ reports_audit_logger.log(action: "test_fallback", performed_by: admin) if admin
601
+ puts
602
+
603
+ # -----------------------------------------------------------------------------
604
+ puts "4. Public namespace UseCase 実行"
605
+ puts "-" * 70
606
+
607
+ result = NamespaceDemo::ListPublicUsersUseCase.call
608
+ if result.success?
609
+ output = result.value!
610
+ puts " 取得したユーザー数: #{output.users.length}"
611
+ output.users.each do |user|
612
+ puts " - #{user.name} (#{user.role})"
613
+ end
614
+ end
615
+ puts
616
+
617
+ # -----------------------------------------------------------------------------
618
+ puts "5. Admin namespace UseCase 実行"
619
+ puts "-" * 70
620
+
621
+ result = NamespaceDemo::ListAdminUsersUseCase.call
622
+ if result.success?
623
+ output = result.value!
624
+ puts " 取得した管理者数: #{output.users.length}"
625
+ output.users.each do |user|
626
+ puts " - #{user.name} (#{user.role})"
627
+ end
628
+ end
629
+ puts
630
+
631
+ # -----------------------------------------------------------------------------
632
+ puts "6. Admin::Reports namespace UseCase 実行(ネストした namespace)"
633
+ puts "-" * 70
634
+
635
+ input = NamespaceDemo::GenerateUserReportUseCase::Input.new(report_type: "monthly_summary")
636
+ result = NamespaceDemo::GenerateUserReportUseCase.call(input)
637
+ if result.success?
638
+ output = result.value!
639
+ puts " 生成されたレポート: #{output.report}"
640
+ end
641
+ puts
642
+
643
+ # -----------------------------------------------------------------------------
644
+ puts "7. 同じキーの異なる namespace 解決確認"
645
+ puts "-" * 70
646
+
647
+ public_repo = container.resolve_in(:public, :user_repository) #: NamespaceDemo::Public::UserRepository
648
+ admin_repo = container.resolve_in(:admin, :user_repository) #: NamespaceDemo::Admin::UserRepository
649
+
650
+ puts " Public UserRepository:"
651
+ public_repo.all.each do |user|
652
+ puts " - #{user.name}"
653
+ end
654
+
655
+ puts " Admin UserRepository:"
656
+ admin_repo.all.each do |user|
657
+ puts " - #{user.name}"
658
+ end
659
+ puts
660
+
661
+ # -----------------------------------------------------------------------------
662
+ puts "8. Scoped Container と namespace の組み合わせ"
663
+ puts "-" * 70
664
+
665
+ # リクエストスコープのコンテナを作成(admin namespace に current_user を追加)
666
+ current_admin = NamespaceDemo::User.new(id: 100, name: "現在の管理者", role: "admin")
667
+
668
+ scoped_container = container.scope do
669
+ # @type self: SenroUsecaser::Container
670
+ namespace(:admin) do
671
+ # @type self: SenroUsecaser::Container
672
+ register(:current_user, current_admin)
673
+ end
674
+ end
675
+
676
+ result = NamespaceDemo::AdminActionUseCase.call(container: scoped_container)
677
+ if result.success?
678
+ output = result.value!
679
+ puts " 結果: #{output.message}"
680
+ end
681
+ puts
682
+
683
+ # -----------------------------------------------------------------------------
684
+ puts "9. registered? と registered_in? の確認"
685
+ puts "-" * 70
686
+
687
+ puts " container.registered_in?(:admin, :user_repository) = #{container.registered_in?(:admin, :user_repository)}"
688
+ puts " container.registered_in?(:public, :user_repository) = #{container.registered_in?(:public, :user_repository)}"
689
+ puts " container.registered_in?(:admin, :logger) = #{container.registered_in?(:admin, :logger)} (ルートからフォールバック)"
690
+ puts " container.registered_in?(\"admin::reports\", :report_generator) = #{container.registered_in?("admin::reports",
691
+ :report_generator)}"
692
+ puts " container.registered_in?(\"admin::reports\", :audit_logger) = #{container.registered_in?("admin::reports",
693
+ :audit_logger)} (adminからフォールバック)"
694
+ puts " container.registered_in?(:public, :audit_logger) = #{container.registered_in?(:public, :audit_logger)} (存在しない)"
695
+ puts
696
+
697
+ # -----------------------------------------------------------------------------
698
+ puts "10. infer_namespace_from_module の確認"
699
+ puts "-" * 70
700
+
701
+ # 設定を有効化
702
+ SenroUsecaser.configuration.infer_namespace_from_module = true
703
+ puts " infer_namespace_from_module = true に設定"
704
+
705
+ # Public::InferredUseCase は namespace を明示していないが、
706
+ # モジュール名から "public" namespace が推論される
707
+ puts " Public::InferredUseCase を実行(namespace 自動推論):"
708
+ result = Public::InferredUseCase.call
709
+ if result.success?
710
+ output = result.value!
711
+ puts " 結果: #{output.message}"
712
+ end
713
+
714
+ # Admin::Reports::InferredReportUseCase はネストしたモジュールから
715
+ # "admin::reports" namespace が推論される
716
+ puts " Admin::Reports::InferredReportUseCase を実行(ネストした namespace 自動推論):"
717
+ result = Admin::Reports::InferredReportUseCase.call
718
+ if result.success?
719
+ output = result.value!
720
+ puts " 結果: #{output.message}"
721
+ end
722
+ puts
723
+
724
+ # Provider も同様にモジュール名から namespace を推論できる
725
+ puts " Provider の namespace 自動推論:"
726
+ # Inferred::ServiceProvider を登録(namespace "inferred" が推論される)
727
+ Inferred::ServiceProvider.call(SenroUsecaser.container)
728
+ puts " Inferred::ServiceProvider を登録"
729
+
730
+ # 登録されたキーを確認
731
+ inferred_keys = SenroUsecaser.container.keys.select { |k| k.start_with?("inferred") }
732
+ puts " 登録されたキー: #{inferred_keys.join(", ")}"
733
+
734
+ # 値を取得
735
+ value = SenroUsecaser.container.resolve_in(:inferred, :inferred_service)
736
+ puts " 取得した値: #{value}"
737
+
738
+ # 設定を元に戻す
739
+ SenroUsecaser.configuration.infer_namespace_from_module = false
740
+ puts
741
+
742
+ # -----------------------------------------------------------------------------
743
+ puts "11. シャットダウン"
744
+ puts "-" * 70
745
+ SenroUsecaser.shutdown!
746
+ puts " 完了"
747
+ puts
748
+
749
+ puts "=" * 70
750
+ puts "Namespace デモ完了"
751
+ puts "=" * 70