rom 0.5.0 → 0.6.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.
Files changed (142) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +19 -15
  3. data/.rubocop_todo.yml +28 -0
  4. data/.travis.yml +8 -1
  5. data/CHANGELOG.md +40 -0
  6. data/Gemfile +10 -2
  7. data/Guardfile +12 -10
  8. data/README.md +42 -43
  9. data/Rakefile +13 -23
  10. data/lib/rom.rb +19 -27
  11. data/lib/rom/command.rb +118 -0
  12. data/lib/rom/command_registry.rb +13 -27
  13. data/lib/rom/commands.rb +1 -59
  14. data/lib/rom/commands/abstract.rb +147 -0
  15. data/lib/rom/commands/composite.rb +47 -0
  16. data/lib/rom/commands/create.rb +2 -17
  17. data/lib/rom/commands/delete.rb +5 -25
  18. data/lib/rom/commands/result.rb +5 -5
  19. data/lib/rom/commands/update.rb +3 -27
  20. data/lib/rom/constants.rb +19 -0
  21. data/lib/rom/env.rb +85 -35
  22. data/lib/rom/global.rb +173 -42
  23. data/lib/rom/header.rb +5 -5
  24. data/lib/rom/header/attribute.rb +2 -2
  25. data/lib/rom/lint/enumerable_dataset.rb +52 -0
  26. data/lib/rom/lint/linter.rb +64 -0
  27. data/lib/rom/lint/repository.rb +78 -0
  28. data/lib/rom/lint/spec.rb +20 -0
  29. data/lib/rom/lint/test.rb +98 -0
  30. data/lib/rom/mapper.rb +32 -5
  31. data/lib/rom/mapper/attribute_dsl.rb +240 -0
  32. data/lib/rom/mapper/dsl.rb +100 -0
  33. data/lib/rom/mapper/model_dsl.rb +55 -0
  34. data/lib/rom/mapper_registry.rb +8 -1
  35. data/lib/rom/memory.rb +4 -0
  36. data/lib/rom/memory/commands.rb +46 -0
  37. data/lib/rom/memory/dataset.rb +72 -0
  38. data/lib/rom/memory/relation.rb +44 -0
  39. data/lib/rom/memory/repository.rb +62 -0
  40. data/lib/rom/memory/storage.rb +57 -0
  41. data/lib/rom/model_builder.rb +44 -5
  42. data/lib/rom/processor.rb +1 -1
  43. data/lib/rom/processor/transproc.rb +109 -16
  44. data/lib/rom/reader.rb +91 -39
  45. data/lib/rom/relation.rb +165 -26
  46. data/lib/rom/relation/composite.rb +132 -0
  47. data/lib/rom/relation/curried.rb +48 -0
  48. data/lib/rom/relation/lazy.rb +173 -0
  49. data/lib/rom/relation/loaded.rb +75 -0
  50. data/lib/rom/relation/registry_reader.rb +23 -0
  51. data/lib/rom/repository.rb +93 -34
  52. data/lib/rom/setup.rb +54 -98
  53. data/lib/rom/setup/finalize.rb +85 -76
  54. data/lib/rom/setup_dsl/command.rb +36 -0
  55. data/lib/rom/setup_dsl/command_dsl.rb +34 -0
  56. data/lib/rom/setup_dsl/mapper.rb +32 -0
  57. data/lib/rom/setup_dsl/mapper_dsl.rb +30 -0
  58. data/lib/rom/setup_dsl/relation.rb +21 -0
  59. data/lib/rom/setup_dsl/setup.rb +75 -0
  60. data/lib/rom/support/array_dataset.rb +38 -0
  61. data/lib/rom/support/class_builder.rb +44 -0
  62. data/lib/rom/support/class_macros.rb +56 -0
  63. data/lib/rom/support/data_proxy.rb +102 -0
  64. data/lib/rom/support/enumerable_dataset.rb +58 -0
  65. data/lib/rom/support/inflector.rb +73 -0
  66. data/lib/rom/support/options.rb +188 -0
  67. data/lib/rom/support/registry.rb +4 -8
  68. data/lib/rom/version.rb +1 -1
  69. data/rakelib/benchmark.rake +13 -0
  70. data/rakelib/mutant.rake +16 -0
  71. data/rakelib/rubocop.rake +18 -0
  72. data/rom.gemspec +4 -7
  73. data/spec/integration/commands/create_spec.rb +32 -24
  74. data/spec/integration/commands/delete_spec.rb +15 -7
  75. data/spec/integration/commands/update_spec.rb +13 -11
  76. data/spec/integration/mappers/deep_embedded_spec.rb +4 -11
  77. data/spec/integration/mappers/definition_dsl_spec.rb +31 -44
  78. data/spec/integration/mappers/embedded_spec.rb +9 -24
  79. data/spec/integration/mappers/group_spec.rb +22 -30
  80. data/spec/integration/mappers/prefixing_attributes_spec.rb +18 -23
  81. data/spec/integration/mappers/renaming_attributes_spec.rb +23 -38
  82. data/spec/integration/mappers/symbolizing_attributes_spec.rb +18 -24
  83. data/spec/integration/mappers/wrap_spec.rb +22 -30
  84. data/spec/integration/multi_repo_spec.rb +15 -37
  85. data/spec/integration/relations/reading_spec.rb +82 -14
  86. data/spec/integration/repositories/extending_relations_spec.rb +50 -0
  87. data/spec/integration/{adapters → repositories}/setting_logger_spec.rb +6 -5
  88. data/spec/integration/setup_spec.rb +59 -62
  89. data/spec/shared/enumerable_dataset.rb +49 -0
  90. data/spec/shared/one_behavior.rb +26 -0
  91. data/spec/shared/users_and_tasks.rb +11 -23
  92. data/spec/spec_helper.rb +16 -7
  93. data/spec/support/constant_leak_finder.rb +14 -0
  94. data/spec/test/memory_repository_lint_test.rb +27 -0
  95. data/spec/unit/rom/command_registry_spec.rb +44 -0
  96. data/spec/unit/rom/commands/result_spec.rb +14 -0
  97. data/spec/unit/rom/commands_spec.rb +174 -0
  98. data/spec/unit/rom/env_spec.rb +40 -7
  99. data/spec/unit/rom/global_spec.rb +14 -0
  100. data/spec/unit/rom/{mapper_builder_spec.rb → mapper/dsl_spec.rb} +52 -38
  101. data/spec/unit/rom/mapper_spec.rb +51 -10
  102. data/spec/unit/rom/{adapter/memory → memory}/dataset_spec.rb +6 -4
  103. data/spec/unit/rom/memory/repository_spec.rb +12 -0
  104. data/spec/unit/rom/memory/storage_spec.rb +45 -0
  105. data/spec/unit/rom/model_builder_spec.rb +4 -3
  106. data/spec/unit/rom/processor/transproc_spec.rb +1 -0
  107. data/spec/unit/rom/reader_spec.rb +97 -24
  108. data/spec/unit/rom/relation/composite_spec.rb +65 -0
  109. data/spec/unit/rom/relation/lazy_spec.rb +145 -0
  110. data/spec/unit/rom/relation/loaded_spec.rb +28 -0
  111. data/spec/unit/rom/relation_spec.rb +111 -6
  112. data/spec/unit/rom/repository_spec.rb +59 -9
  113. data/spec/unit/rom/setup_spec.rb +99 -11
  114. data/spec/unit/rom/support/array_dataset_spec.rb +59 -0
  115. data/spec/unit/rom/support/class_builder_spec.rb +42 -0
  116. data/spec/unit/rom/support/enumerable_dataset_spec.rb +17 -0
  117. data/spec/unit/rom/support/inflector_spec.rb +89 -0
  118. data/spec/unit/rom/support/options_spec.rb +119 -0
  119. metadata +74 -112
  120. data/lib/rom/adapter.rb +0 -191
  121. data/lib/rom/adapter/memory.rb +0 -32
  122. data/lib/rom/adapter/memory/commands.rb +0 -31
  123. data/lib/rom/adapter/memory/dataset.rb +0 -67
  124. data/lib/rom/adapter/memory/storage.rb +0 -26
  125. data/lib/rom/commands/with_options.rb +0 -18
  126. data/lib/rom/config.rb +0 -70
  127. data/lib/rom/mapper_builder.rb +0 -52
  128. data/lib/rom/mapper_builder/mapper_dsl.rb +0 -114
  129. data/lib/rom/mapper_builder/model_dsl.rb +0 -29
  130. data/lib/rom/reader_builder.rb +0 -48
  131. data/lib/rom/relation_builder.rb +0 -62
  132. data/lib/rom/setup/base_relation_dsl.rb +0 -46
  133. data/lib/rom/setup/command_dsl.rb +0 -46
  134. data/lib/rom/setup/mapper_dsl.rb +0 -19
  135. data/lib/rom/setup/relation_dsl.rb +0 -20
  136. data/lib/rom/setup/schema_dsl.rb +0 -33
  137. data/spec/integration/adapters/extending_relations_spec.rb +0 -41
  138. data/spec/integration/commands/try_spec.rb +0 -27
  139. data/spec/integration/schema_spec.rb +0 -77
  140. data/spec/unit/config_spec.rb +0 -60
  141. data/spec/unit/rom/adapter_spec.rb +0 -79
  142. data/spec/unit/rom_spec.rb +0 -14
@@ -1,3 +1,5 @@
1
+ require 'rom/command'
2
+
1
3
  module ROM
2
4
  module Commands
3
5
  # Delete command
@@ -5,10 +7,11 @@ module ROM
5
7
  # This command removes tuples from its target relation
6
8
  #
7
9
  # @abstract
8
- class Delete < AbstractCommand
10
+ class Delete < Command
9
11
  attr_reader :target
10
12
 
11
- def initialize(relation, options)
13
+ # @api private
14
+ def initialize(relation, options = {})
12
15
  super
13
16
  @target = options[:target] || relation
14
17
  end
@@ -18,29 +21,6 @@ module ROM
18
21
  assert_tuple_count
19
22
  super
20
23
  end
21
-
22
- # Execute the command
23
- #
24
- # @abstract
25
- #
26
- # @return [Array] an array with removed tuples
27
- #
28
- # @api private
29
- def execute
30
- raise(
31
- NotImplementedError,
32
- "#{self.class}##{__method__} must be implemented"
33
- )
34
- end
35
-
36
- # Create a new delete command scoped to specific relation and execute it
37
- #
38
- # @api private
39
- def new(*args, &block)
40
- new_options = options.merge(target: relation.public_send(*args, &block))
41
- command = self.class.new(relation, new_options)
42
- command.call
43
- end
44
24
  end
45
25
  end
46
26
  end
@@ -2,7 +2,7 @@ module ROM
2
2
  module Commands
3
3
  # Abstract result class for success and error results
4
4
  #
5
- # @public
5
+ # @api public
6
6
  class Result
7
7
  # Return command execution result
8
8
  #
@@ -26,11 +26,11 @@ module ROM
26
26
 
27
27
  # Success result has a value and no error
28
28
  #
29
- # @public
29
+ # @api public
30
30
  class Success < Result
31
31
  # @api private
32
32
  def initialize(value)
33
- @value = value
33
+ @value = value.is_a?(self.class) ? value.value : value
34
34
  end
35
35
 
36
36
  # Call next command on continuation
@@ -46,13 +46,13 @@ module ROM
46
46
  #
47
47
  # @api public
48
48
  def to_ary
49
- value
49
+ value.to_ary
50
50
  end
51
51
  end
52
52
 
53
53
  # Failure result has an error and no value
54
54
  #
55
- # @public
55
+ # @api public
56
56
  class Failure < Result
57
57
  # @api private
58
58
  def initialize(error)
@@ -1,4 +1,4 @@
1
- require 'rom/commands/with_options'
1
+ require 'rom/command'
2
2
 
3
3
  module ROM
4
4
  module Commands
@@ -7,37 +7,13 @@ module ROM
7
7
  # This command updates all tuples in its relation with new attributes
8
8
  #
9
9
  # @abstract
10
- class Update < AbstractCommand
11
- include WithOptions
12
-
13
- alias_method :set, :call
14
-
10
+ class Update < Command
15
11
  # @see AbstractCommand#call
16
12
  def call(*args)
17
13
  assert_tuple_count
18
14
  super
19
15
  end
20
-
21
- # Execute the update command
22
- #
23
- # @return [Array] an array with updated tuples
24
- #
25
- # @abstract
26
- #
27
- # @api private
28
- def execute(_params)
29
- raise(
30
- NotImplementedError,
31
- "#{self.class}##{__method__} must be implemented"
32
- )
33
- end
34
-
35
- # Return new update command with new relation
36
- #
37
- # @api private
38
- def new(*args, &block)
39
- self.class.new(relation.public_send(*args, &block), options)
40
- end
16
+ alias_method :set, :call
41
17
  end
42
18
  end
43
19
  end
@@ -0,0 +1,19 @@
1
+ # Constants and errors common in the whole library
2
+ module ROM
3
+ Undefined = Object.new.freeze
4
+
5
+ AdapterLoadError = Class.new(StandardError)
6
+
7
+ EnvAlreadyFinalizedError = Class.new(StandardError)
8
+ RelationAlreadyDefinedError = Class.new(StandardError)
9
+ NoRelationError = Class.new(StandardError)
10
+ CommandError = Class.new(StandardError)
11
+ TupleCountMismatchError = Class.new(CommandError)
12
+ MapperMissingError = Class.new(StandardError)
13
+
14
+ InvalidOptionValueError = Class.new(StandardError)
15
+ InvalidOptionKeyError = Class.new(StandardError)
16
+
17
+ EMPTY_ARRAY = [].freeze
18
+ EMPTY_HASH = {}.freeze
19
+ end
data/lib/rom/env.rb CHANGED
@@ -1,33 +1,102 @@
1
+ require 'rom/relation/loaded'
2
+
1
3
  module ROM
2
- # Exposes defined repositories, schema, relations and mappers
4
+ # Exposes defined repositories, relations and mappers
3
5
  #
4
6
  # @api public
5
7
  class Env
6
- include Adamantium::Flat
7
- include Equalizer.new(
8
- :repositories, :schema, :relations, :mappers, :commands
9
- )
8
+ include Equalizer.new(:repositories, :relations, :mappers, :commands)
9
+
10
+ # @return [Hash] configured repositories
11
+ #
12
+ # @api public
13
+ attr_reader :repositories
14
+
15
+ # @return [RelationRegistry] relation registry
16
+ #
17
+ # @api public
18
+ attr_reader :relations
19
+
20
+ # @return [ReaderRegistry] reader registry
21
+ #
22
+ # @api public
23
+ attr_reader :readers
24
+
25
+ # @return [Registry] command registry
26
+ #
27
+ # @api public
28
+ attr_reader :commands
10
29
 
11
- attr_reader :repositories, :schema, :relations, :mappers, :commands
30
+ # @return [Registry] mapper registry
31
+ #
32
+ # @api public
33
+ attr_reader :mappers
12
34
 
13
35
  # @api private
14
- def initialize(repositories, schema, relations, mappers, commands)
36
+ def initialize(repositories, relations, readers, commands)
15
37
  @repositories = repositories
16
- @schema = schema
17
38
  @relations = relations
18
- @mappers = mappers
39
+ @readers = readers
19
40
  @commands = commands
41
+ initialize_mappers
42
+ freeze
43
+ end
44
+
45
+ # Load relation by name
46
+ #
47
+ # @example
48
+ #
49
+ # rom.relation(:users)
50
+ # rom.relation(:users) { |r| r.by_name('Jane') }
51
+ #
52
+ # # with mapping
53
+ # rom.relation(:users).map_with(:presenter)
54
+ #
55
+ # rom.relation(:users) { |r| r.page(1) }.map_with(:presenter, :json_serializer)
56
+ #
57
+ # @param [Symbol] name of the relation to load
58
+ #
59
+ # @yield [Relation]
60
+ #
61
+ # @return [Relation::Loaded]
62
+ #
63
+ # @api public
64
+ def relation(name, &block)
65
+ relation =
66
+ if block
67
+ yield(relations[name])
68
+ else
69
+ relations[name]
70
+ end
71
+
72
+ if mappers.elements.key?(name)
73
+ relation.to_lazy(mappers: mappers[name])
74
+ else
75
+ relation.to_lazy
76
+ end
20
77
  end
21
78
 
22
79
  # Returns a reader with access to defined mappers
23
80
  #
24
81
  # @example
25
82
  #
83
+ # # with a mapper derived from relation access path "users.adults"
26
84
  # rom.read(:users).adults.to_a
27
85
  #
86
+ # # or with explicit mapper name
87
+ # rom.read(:users).with(:some_mapper).to_a
88
+ #
89
+ # @param [Symbol] name of the registered reader
90
+ #
28
91
  # @api public
29
- def read(name)
30
- mappers[name]
92
+ def read(name, &block)
93
+ reader = readers[name]
94
+
95
+ if block
96
+ yield(reader)
97
+ else
98
+ reader
99
+ end
31
100
  end
32
101
 
33
102
  # Returns commands registry for the given relation
@@ -41,33 +110,14 @@ module ROM
41
110
  commands[name]
42
111
  end
43
112
 
44
- # Return repository identified by its name
45
- #
46
- # @return [Repository]
47
- #
48
- # @api private
49
- def [](name)
50
- repositories.fetch(name)
51
- end
52
-
53
- # @api private
54
- def respond_to_missing?(name, include_private = false)
55
- repositories.key?(name) || super
56
- end
57
-
58
113
  private
59
114
 
60
- # Return repository if the method matches repository name
61
- #
62
- # @return [Repository]
63
- #
64
115
  # @api private
65
- def method_missing(name, *args, &block)
66
- if repositories.key?(name)
67
- repositories[name]
68
- else
69
- super
70
- end
116
+ def initialize_mappers
117
+ elements = readers.each_with_object({}) { |(name, reader), h|
118
+ h[name] = reader.mappers
119
+ }
120
+ @mappers = Registry.new(elements)
71
121
  end
72
122
  end
73
123
  end
data/lib/rom/global.rb CHANGED
@@ -1,13 +1,85 @@
1
+ require 'rom/setup'
2
+ require 'rom/repository'
3
+
1
4
  module ROM
2
5
  # Globally accessible public interface exposed via ROM module
3
6
  #
4
- # @public
7
+ # @api public
5
8
  module Global
6
- # Starts the setup process for schema, relations, mappers and commands
9
+ # Set base global registries in ROM constant
10
+ #
11
+ # @api private
12
+ def self.extended(rom)
13
+ super
14
+
15
+ rom.instance_variable_set('@adapters', {})
16
+ rom.instance_variable_set('@repositories', {})
17
+ end
18
+
19
+ # An internal adapter identifier => adapter module map used by setup
20
+ #
21
+ # @return [Hash<Symbol=>Module>]
22
+ #
23
+ # @api private
24
+ attr_reader :adapters
25
+
26
+ # An internal repo => identifier map used by the setup
27
+ #
28
+ # @return [Hash]
29
+ #
30
+ # @api private
31
+ attr_reader :repositories
32
+
33
+ # Setup object created during env setup phase
34
+ #
35
+ # This gets set to nil after setup is finalized
36
+ #
37
+ # @return [Setup]
38
+ #
39
+ # @api private
40
+ attr_reader :boot
41
+
42
+ # Return global default ROM environment configured by the setup
43
+ #
44
+ # @return [Env]
45
+ #
46
+ # @api public
47
+ attr_reader :env
48
+
49
+ # Starts the setup process for relations, mappers and commands.
50
+ #
51
+ # @overload setup(type, *args)
52
+ # Sets up a single-repository environment given a repository type provided
53
+ # under the ROM umbrella. For custom repositories, create an instance and
54
+ # pass it directly.
55
+ #
56
+ # @param [Symbol] type
57
+ # @param [Array] *args
58
+ #
59
+ # @overload setup(repository)
60
+ # @param [Repository] repository
61
+ #
62
+ # @overload setup(repositories)
63
+ # Sets up multiple repositories.
64
+ #
65
+ # @param [Hash{Symbol=>Symbol,Array}] repositories
66
+ #
67
+ # @return [Setup] boot object
7
68
  #
8
69
  # @example
70
+ # # Use the in-memory adapter shipped with ROM as the default repository.
71
+ # env = ROM.setup(:memory, 'memory://test')
72
+ # # Use `rom-sql` with an in-memory sqlite database as default repository.
73
+ # ROM.setup(:sql, 'sqlite::memory')
74
+ # # Registers a `default` and a `warehouse` repository.
75
+ # env = ROM.setup(
76
+ # default: [:sql, 'sqlite::memory'],
77
+ # warehouse: [:sql, 'postgres://localhost/warehouse']
78
+ # )
9
79
  #
10
- # ROM.setup('sqlite::memory')
80
+ # @example A full environment
81
+ #
82
+ # ROM.setup(:memory, 'memory://test')
11
83
  #
12
84
  # ROM.relation(:users) do
13
85
  # # ...
@@ -28,80 +100,139 @@ module ROM
28
100
  # ROM.finalize # builds the env
29
101
  # ROM.env # returns the env registry
30
102
  #
31
- # @param [Hash] options repository URIs
32
- #
33
- # @return [Setup] boot object
34
- #
35
103
  # @api public
36
104
  def setup(*args, &block)
37
- config = Config.build(*args)
38
-
39
- adapters = config.each_with_object({}) do |(name, uri_or_opts), hash|
40
- uri, opts =
41
- if uri_or_opts.is_a?(Hash)
42
- uri_or_opts.values_at(:uri, :options)
43
- else
44
- [uri_or_opts, {}]
45
- end
46
-
47
- hash[name] = Adapter.setup(uri, opts)
48
- end
49
-
50
- repositories = adapters.each_with_object({}) do |(name, adapter), hash|
51
- hash[name] = Repository.new(adapter)
52
- end
53
-
54
- boot = Setup.new(repositories)
105
+ config = setup_config(*args)
106
+ @boot = Setup.new(setup_repositories(config), adapters.keys.first)
55
107
 
56
108
  if block
57
- boot.instance_exec(&block)
58
- boot.finalize
109
+ @boot.instance_exec(&block)
110
+ @boot.finalize
59
111
  else
60
- @boot = boot
112
+ @boot
61
113
  end
62
114
  end
63
115
 
64
- # @see ROM::Setup#schema
116
+ # Global relation setup DSL
65
117
  #
66
- # @api public
67
- def schema(&block)
68
- boot.schema(&block)
69
- end
70
-
71
- # @see ROM::Setup#relation
118
+ # @example
119
+ # ROM.setup(:memory)
120
+ #
121
+ # ROM.relation(:users) do
122
+ # def by_name(name)
123
+ # restrict(name: name)
124
+ # end
125
+ # end
72
126
  #
73
127
  # @api public
74
128
  def relation(*args, &block)
75
129
  boot.relation(*args, &block)
76
130
  end
77
131
 
132
+ # Global commands setup DSL
133
+ #
134
+ # @example
135
+ # ROM.setup(:memory)
136
+ #
137
+ # ROM.commands(:users) do
138
+ # define(:create) do
139
+ # # ..
140
+ # end
141
+ # end
142
+ #
78
143
  # @api public
79
144
  def commands(*args, &block)
80
145
  boot.commands(*args, &block)
81
146
  end
82
147
 
148
+ # Global mapper setup DSL
149
+ #
150
+ # @example
151
+ # ROM.setup(:memory)
152
+ #
153
+ # ROM.mappers do
154
+ # define(:uses) do
155
+ # # ..
156
+ # end
157
+ # end
158
+ #
83
159
  # @api public
84
160
  def mappers(*args, &block)
85
161
  boot.mappers(*args, &block)
86
162
  end
87
163
 
88
- # @api public
89
- def env
90
- @env
91
- end
92
-
164
+ # Finalize the setup and store default global env under ROM.env
165
+ #
166
+ # @example
167
+ # ROM.setup(:memory)
168
+ # ROM.finalize # => ROM
169
+ # ROM.boot # => nil
170
+ # ROM.env # => the env
171
+ #
172
+ # @return [ROM]
173
+ #
93
174
  # @api public
94
175
  def finalize
95
176
  @env = boot.finalize
177
+ self
178
+ ensure
96
179
  @boot = nil
180
+ end
181
+
182
+ # Register adapter namespace under a specified identifier
183
+ #
184
+ # @param [Symbol] identifier
185
+ # @param [Class,Module] adapter
186
+ #
187
+ # @return [self]
188
+ #
189
+ # @api private
190
+ def register_adapter(identifier, adapter)
191
+ adapters[identifier] = adapter
97
192
  self
98
193
  end
99
194
 
195
+ # Relation subclass registration during setup phase
196
+ #
197
+ # @api private
198
+ def register_relation(klass)
199
+ boot.register_relation(klass) if boot
200
+ end
201
+
202
+ # Mapper subclass registration during setup phase
203
+ #
204
+ # @api private
205
+ def register_mapper(klass)
206
+ boot.register_mapper(klass) if boot
207
+ end
208
+
209
+ # Command subclass registration during setup phase
210
+ #
211
+ # @api private
212
+ def register_command(klass)
213
+ boot.register_command(klass) if boot
214
+ end
215
+
100
216
  private
101
217
 
218
+ # Helper method to handle single- or multi-repo setup options
219
+ #
220
+ # @api private
221
+ def setup_config(*args)
222
+ args.first.is_a?(Hash) ? args.first : { default: args }
223
+ end
224
+
225
+ # Build repositories using the setup interface
226
+ #
102
227
  # @api private
103
- def boot
104
- @boot
228
+ def setup_repositories(config)
229
+ config.each_with_object({}) do |(name, spec), hash|
230
+ identifier, *args = Array(spec)
231
+ repository = Repository.setup(identifier, *(args.flatten))
232
+ hash[name] = repository
233
+
234
+ repositories[repository] = identifier unless identifier.is_a?(Repository)
235
+ end
105
236
  end
106
237
  end
107
238
  end