rom 5.4.2 → 6.0.0.alpha1

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 (186) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +58 -71
  3. data/LICENSE +1 -1
  4. data/README.md +7 -6
  5. data/lib/rom/array_dataset.rb +46 -0
  6. data/lib/rom/associations/abstract.rb +217 -0
  7. data/lib/rom/associations/definitions/abstract.rb +150 -0
  8. data/lib/rom/associations/definitions/many_to_many.rb +29 -0
  9. data/lib/rom/associations/definitions/many_to_one.rb +14 -0
  10. data/lib/rom/associations/definitions/one_to_many.rb +14 -0
  11. data/lib/rom/associations/definitions/one_to_one.rb +14 -0
  12. data/lib/rom/associations/definitions/one_to_one_through.rb +14 -0
  13. data/lib/rom/associations/definitions.rb +7 -0
  14. data/lib/rom/associations/many_to_many.rb +128 -0
  15. data/lib/rom/associations/many_to_one.rb +65 -0
  16. data/lib/rom/associations/one_to_many.rb +65 -0
  17. data/lib/rom/associations/one_to_one.rb +13 -0
  18. data/lib/rom/associations/one_to_one_through.rb +13 -0
  19. data/lib/rom/associations/through_identifier.rb +41 -0
  20. data/lib/rom/attribute.rb +425 -0
  21. data/lib/rom/auto_curry.rb +70 -0
  22. data/lib/rom/cache.rb +87 -0
  23. data/lib/rom/changeset/associated.rb +110 -0
  24. data/lib/rom/changeset/create.rb +18 -0
  25. data/lib/rom/changeset/delete.rb +15 -0
  26. data/lib/rom/changeset/extensions/relation.rb +26 -0
  27. data/lib/rom/changeset/pipe.rb +81 -0
  28. data/lib/rom/changeset/pipe_registry.rb +27 -0
  29. data/lib/rom/changeset/stateful.rb +285 -0
  30. data/lib/rom/changeset/update.rb +81 -0
  31. data/lib/rom/changeset.rb +185 -0
  32. data/lib/rom/command.rb +351 -0
  33. data/lib/rom/command_compiler.rb +201 -0
  34. data/lib/rom/command_proxy.rb +36 -0
  35. data/lib/rom/commands/class_interface.rb +236 -0
  36. data/lib/rom/commands/composite.rb +55 -0
  37. data/lib/rom/commands/create.rb +15 -0
  38. data/lib/rom/commands/delete.rb +16 -0
  39. data/lib/rom/commands/graph/class_interface.rb +64 -0
  40. data/lib/rom/commands/graph/input_evaluator.rb +94 -0
  41. data/lib/rom/commands/graph.rb +88 -0
  42. data/lib/rom/commands/lazy/create.rb +35 -0
  43. data/lib/rom/commands/lazy/delete.rb +39 -0
  44. data/lib/rom/commands/lazy/update.rb +46 -0
  45. data/lib/rom/commands/lazy.rb +106 -0
  46. data/lib/rom/commands/update.rb +16 -0
  47. data/lib/rom/commands.rb +5 -0
  48. data/lib/rom/compat/auto_registration.rb +115 -0
  49. data/lib/rom/compat/auto_registration_strategies/base.rb +29 -0
  50. data/lib/rom/compat/auto_registration_strategies/custom_namespace.rb +84 -0
  51. data/lib/rom/compat/auto_registration_strategies/no_namespace.rb +33 -0
  52. data/lib/rom/compat/auto_registration_strategies/with_namespace.rb +29 -0
  53. data/lib/rom/compat/command.rb +74 -0
  54. data/lib/rom/compat/components/dsl/schema.rb +130 -0
  55. data/lib/rom/compat/components.rb +91 -0
  56. data/lib/rom/compat/global.rb +17 -0
  57. data/lib/rom/compat/mapper.rb +22 -0
  58. data/lib/rom/compat/registries.rb +47 -0
  59. data/lib/rom/compat/relation.rb +40 -0
  60. data/lib/rom/compat/schema/dsl.rb +260 -0
  61. data/lib/rom/compat/setting_proxy.rb +44 -0
  62. data/lib/rom/compat/setup.rb +151 -0
  63. data/lib/rom/compat/transformer.rb +49 -0
  64. data/lib/rom/compat.rb +22 -0
  65. data/lib/rom/components/association.rb +26 -0
  66. data/lib/rom/components/command.rb +24 -0
  67. data/lib/rom/components/core.rb +148 -0
  68. data/lib/rom/components/dataset.rb +60 -0
  69. data/lib/rom/components/dsl/association.rb +47 -0
  70. data/lib/rom/components/dsl/command.rb +60 -0
  71. data/lib/rom/components/dsl/core.rb +126 -0
  72. data/lib/rom/components/dsl/dataset.rb +33 -0
  73. data/lib/rom/components/dsl/gateway.rb +14 -0
  74. data/lib/rom/components/dsl/mapper.rb +70 -0
  75. data/lib/rom/components/dsl/relation.rb +49 -0
  76. data/lib/rom/components/dsl/schema.rb +150 -0
  77. data/lib/rom/components/dsl/view.rb +82 -0
  78. data/lib/rom/components/dsl.rb +255 -0
  79. data/lib/rom/components/gateway.rb +50 -0
  80. data/lib/rom/components/mapper.rb +29 -0
  81. data/lib/rom/components/provider.rb +160 -0
  82. data/lib/rom/components/registry.rb +154 -0
  83. data/lib/rom/components/relation.rb +41 -0
  84. data/lib/rom/components/schema.rb +61 -0
  85. data/lib/rom/components/view.rb +55 -0
  86. data/lib/rom/components.rb +55 -0
  87. data/lib/rom/configuration_dsl.rb +4 -0
  88. data/lib/rom/constants.rb +135 -0
  89. data/lib/rom/container.rb +182 -0
  90. data/lib/rom/core.rb +125 -0
  91. data/lib/rom/data_proxy.rb +97 -0
  92. data/lib/rom/enumerable_dataset.rb +70 -0
  93. data/lib/rom/gateway.rb +232 -0
  94. data/lib/rom/global.rb +56 -0
  95. data/lib/rom/header/attribute.rb +190 -0
  96. data/lib/rom/header.rb +198 -0
  97. data/lib/rom/inferrer.rb +55 -0
  98. data/lib/rom/initializer.rb +80 -0
  99. data/lib/rom/lint/enumerable_dataset.rb +56 -0
  100. data/lib/rom/lint/gateway.rb +120 -0
  101. data/lib/rom/lint/linter.rb +79 -0
  102. data/lib/rom/lint/spec.rb +22 -0
  103. data/lib/rom/lint/test.rb +98 -0
  104. data/lib/rom/loader.rb +161 -0
  105. data/lib/rom/mapper/attribute_dsl.rb +480 -0
  106. data/lib/rom/mapper/dsl.rb +107 -0
  107. data/lib/rom/mapper/model_dsl.rb +61 -0
  108. data/lib/rom/mapper.rb +99 -0
  109. data/lib/rom/mapper_compiler.rb +84 -0
  110. data/lib/rom/memory/associations/many_to_many.rb +12 -0
  111. data/lib/rom/memory/associations/many_to_one.rb +12 -0
  112. data/lib/rom/memory/associations/one_to_many.rb +12 -0
  113. data/lib/rom/memory/associations/one_to_one.rb +12 -0
  114. data/lib/rom/memory/associations.rb +6 -0
  115. data/lib/rom/memory/commands.rb +60 -0
  116. data/lib/rom/memory/dataset.rb +127 -0
  117. data/lib/rom/memory/gateway.rb +66 -0
  118. data/lib/rom/memory/mapper_compiler.rb +10 -0
  119. data/lib/rom/memory/relation.rb +91 -0
  120. data/lib/rom/memory/schema.rb +32 -0
  121. data/lib/rom/memory/storage.rb +61 -0
  122. data/lib/rom/memory/types.rb +11 -0
  123. data/lib/rom/memory.rb +7 -0
  124. data/lib/rom/model_builder.rb +103 -0
  125. data/lib/rom/open_struct.rb +112 -0
  126. data/lib/rom/pipeline.rb +111 -0
  127. data/lib/rom/plugin.rb +130 -0
  128. data/lib/rom/plugins/class_methods.rb +37 -0
  129. data/lib/rom/plugins/command/schema.rb +45 -0
  130. data/lib/rom/plugins/command/timestamps.rb +149 -0
  131. data/lib/rom/plugins/dsl.rb +53 -0
  132. data/lib/rom/plugins/relation/changeset.rb +97 -0
  133. data/lib/rom/plugins/relation/instrumentation.rb +66 -0
  134. data/lib/rom/plugins/relation/registry_reader.rb +36 -0
  135. data/lib/rom/plugins/schema/timestamps.rb +59 -0
  136. data/lib/rom/plugins.rb +100 -0
  137. data/lib/rom/processor/composer.rb +37 -0
  138. data/lib/rom/processor/transformer.rb +415 -0
  139. data/lib/rom/processor.rb +30 -0
  140. data/lib/rom/registries/associations.rb +26 -0
  141. data/lib/rom/registries/commands.rb +11 -0
  142. data/lib/rom/registries/container.rb +12 -0
  143. data/lib/rom/registries/datasets.rb +21 -0
  144. data/lib/rom/registries/gateways.rb +8 -0
  145. data/lib/rom/registries/mappers.rb +21 -0
  146. data/lib/rom/registries/nestable.rb +32 -0
  147. data/lib/rom/registries/relations.rb +8 -0
  148. data/lib/rom/registries/root.rb +203 -0
  149. data/lib/rom/registries/schemas.rb +44 -0
  150. data/lib/rom/registries/views.rb +11 -0
  151. data/lib/rom/relation/class_interface.rb +61 -0
  152. data/lib/rom/relation/combined.rb +160 -0
  153. data/lib/rom/relation/commands.rb +65 -0
  154. data/lib/rom/relation/composite.rb +53 -0
  155. data/lib/rom/relation/curried.rb +129 -0
  156. data/lib/rom/relation/graph.rb +107 -0
  157. data/lib/rom/relation/loaded.rb +136 -0
  158. data/lib/rom/relation/materializable.rb +62 -0
  159. data/lib/rom/relation/name.rb +122 -0
  160. data/lib/rom/relation/wrap.rb +64 -0
  161. data/lib/rom/relation.rb +625 -0
  162. data/lib/rom/repository/class_interface.rb +162 -0
  163. data/lib/rom/repository/relation_reader.rb +48 -0
  164. data/lib/rom/repository/root.rb +75 -0
  165. data/lib/rom/repository/session.rb +60 -0
  166. data/lib/rom/repository.rb +179 -0
  167. data/lib/rom/schema/associations_dsl.rb +222 -0
  168. data/lib/rom/schema/inferrer.rb +106 -0
  169. data/lib/rom/schema.rb +471 -0
  170. data/lib/rom/settings.rb +141 -0
  171. data/lib/rom/setup.rb +297 -0
  172. data/lib/rom/struct.rb +99 -0
  173. data/lib/rom/struct_compiler.rb +114 -0
  174. data/lib/rom/support/configurable.rb +213 -0
  175. data/lib/rom/support/inflector.rb +31 -0
  176. data/lib/rom/support/memoizable.rb +61 -0
  177. data/lib/rom/support/notifications.rb +238 -0
  178. data/lib/rom/transaction.rb +26 -0
  179. data/lib/rom/transformer.rb +46 -0
  180. data/lib/rom/types.rb +74 -0
  181. data/lib/rom/version.rb +1 -1
  182. data/lib/rom-changeset.rb +4 -0
  183. data/lib/rom-core.rb +3 -0
  184. data/lib/rom-repository.rb +4 -0
  185. data/lib/rom.rb +3 -3
  186. metadata +302 -23
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rom/transformer"
4
+
5
+ module ROM
6
+ Transformer.class_eval do
7
+ class << self
8
+ prepend SettingProxy
9
+
10
+ # Configure relation for the transformer
11
+ #
12
+ # @example with a custom name
13
+ # class UsersMapper < ROM::Transformer
14
+ # relation :users, as: :json_serializer
15
+ #
16
+ # map do
17
+ # rename_keys user_id: :id
18
+ # deep_stringify_keys
19
+ # end
20
+ # end
21
+ #
22
+ # users.map_with(:json_serializer)
23
+ #
24
+ # @param name [Symbol]
25
+ # @param options [Hash]
26
+ # @option options :as [Symbol] Mapper identifier
27
+ #
28
+ # @deprecated
29
+ #
30
+ # @api public
31
+ def relation(name = Undefined, as: name)
32
+ if name == Undefined
33
+ config.component.relation
34
+ else
35
+ config.component.relation = name
36
+ config.component.namespace = name
37
+ config.component.id = as
38
+ end
39
+ end
40
+
41
+ def setting_mapping
42
+ @setting_mapping ||= {
43
+ register_as: [:component, :id],
44
+ relation: [:component, [:id, :relation, :namespace]]
45
+ }.freeze
46
+ end
47
+ end
48
+ end
49
+ end
data/lib/rom/compat.rb ADDED
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This file loads a bunch of patches that maintain compatibility with rom 5.x.
4
+ # It is not loaded by default in 6.0. During 6.x release series, these patches
5
+ # will be gradually deprecated and eventually removed in rom 7.0.
6
+
7
+ require "rom/core"
8
+
9
+ # old api patches
10
+ require_relative "compat/global"
11
+ require_relative "compat/auto_registration"
12
+ require_relative "compat/setting_proxy"
13
+ require_relative "compat/setup"
14
+ require_relative "compat/relation"
15
+ require_relative "compat/command"
16
+ require_relative "compat/transformer"
17
+ require_relative "compat/mapper"
18
+
19
+ # new api patches
20
+ require_relative "compat/components/dsl/schema"
21
+ require_relative "compat/components"
22
+ require_relative "compat/registries"
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "core"
4
+
5
+ module ROM
6
+ module Components
7
+ # @api public
8
+ class Association < Core
9
+ # @!attribute [r] definition
10
+ # @return [Association::Definition]
11
+ option :definition
12
+
13
+ # @api public
14
+ def build
15
+ association_class.new(definition, registry.relations)
16
+ end
17
+
18
+ private
19
+
20
+ # @api private
21
+ def association_class
22
+ ROM.adapters[config.adapter].const_get(:Associations).const_get(definition.type)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "core"
4
+
5
+ module ROM
6
+ module Components
7
+ # @api public
8
+ class Command < Core
9
+ # @!attribute [r] constant
10
+ # @return [Class] Component's target class
11
+ option :constant, type: Types.Interface(:new)
12
+
13
+ # @api public
14
+ def build
15
+ gateway.command(constant, relation: registry.relations[config.relation])
16
+ end
17
+
18
+ # @api private
19
+ def adapter
20
+ config.adapter
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,148 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dry/effects"
4
+ require "dry/core/class_attributes"
5
+ require "dry/core/memoizable"
6
+
7
+ require "rom/constants"
8
+ require "rom/initializer"
9
+ require "rom/types"
10
+
11
+ module ROM
12
+ module Components
13
+ # Abstract component class
14
+ #
15
+ # @api public
16
+ class Core
17
+ include Dry::Effects.Reader(:registry)
18
+
19
+ extend Initializer
20
+ extend Dry::Core::ClassAttributes
21
+
22
+ include Dry::Core::Memoizable
23
+
24
+ defines :type
25
+
26
+ # @api private
27
+ def self.inherited(klass)
28
+ super
29
+ klass.type(Inflector.component_id(klass).to_sym)
30
+ end
31
+
32
+ # @!attribute [r] provider
33
+ # @return [Object] Component's provider
34
+ option :provider
35
+
36
+ # @!attribute [r] config
37
+ # @return [Object] Component's config
38
+ option :config, type: Types.Instance(Dry::Configurable::Config)
39
+
40
+ # @!attribute [r] gateway
41
+ # @return [Proc] Optional component evaluation block
42
+ option :block, type: Types.Interface(:to_proc), optional: true
43
+
44
+ # @api public
45
+ def type
46
+ self.class.type
47
+ end
48
+
49
+ # @api public
50
+ def abstract
51
+ config.abstract
52
+ end
53
+ alias_method :abstract?, :abstract
54
+
55
+ # Default container key
56
+ #
57
+ # @return [String]
58
+ #
59
+ # @api public
60
+ memoize def key
61
+ "#{namespace}.#{id}"
62
+ end
63
+
64
+ # @api public
65
+ def id
66
+ config.id
67
+ end
68
+
69
+ # @api public
70
+ def namespace
71
+ config.namespace
72
+ end
73
+
74
+ # This method is meant to return a run-time component instance
75
+ #
76
+ # @api public
77
+ def build(**)
78
+ raise NotImplementedError
79
+ end
80
+
81
+ # @api public
82
+ def inflector
83
+ config.inflector
84
+ end
85
+
86
+ # @api private
87
+ def components
88
+ provider.components
89
+ end
90
+
91
+ # @api private
92
+ def local_components
93
+ EMPTY_ARRAY
94
+ end
95
+
96
+ # @api private
97
+ def apply_plugins
98
+ already_applied = plugins.reject(&:applied?).map do |plugin|
99
+ plugin.enable(constant) unless plugin.enabled?
100
+ plugin.apply unless plugin.applied?
101
+ plugin.name
102
+ end
103
+
104
+ apply_external_plugins(gateway_plugins, already_applied) if gateway?
105
+ apply_external_plugins(provider_plugins, already_applied)
106
+ end
107
+
108
+ # @api private
109
+ def apply_external_plugins(plugins, already_applied)
110
+ plugins
111
+ .reject { |plugin| already_applied.include?(plugin.name) }
112
+ .each { |external_plugin|
113
+ config.plugins << external_plugin.configure.enable(constant).apply
114
+ }
115
+ end
116
+
117
+ # @api private
118
+ def plugins
119
+ config.plugins.select { |plugin| plugin.type == type }
120
+ end
121
+
122
+ # @api private
123
+ def gateway_plugins
124
+ gateway.config.plugins.select { |plugin| plugin.type == type }
125
+ end
126
+
127
+ # @api private
128
+ def provider_plugins
129
+ provider.config.component.plugins.select { |plugin| plugin.type == type }
130
+ end
131
+
132
+ # @api public
133
+ def plugin_options
134
+ plugins.map(&:plugin_options).reduce(:merge) || EMPTY_HASH
135
+ end
136
+
137
+ # @api public
138
+ def gateway?
139
+ registry.gateways.key?(config[:gateway])
140
+ end
141
+
142
+ # @api public
143
+ def gateway
144
+ registry.gateways[config[:gateway]]
145
+ end
146
+ end
147
+ end
148
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "core"
4
+
5
+ module ROM
6
+ module Components
7
+ # @api public
8
+ class Dataset < Core
9
+ # @api public
10
+ def build
11
+ if gateway?
12
+ blocks.reduce(gateway.dataset(id)) { |ds, blk| evaluate_block(ds, blk) }
13
+ elsif block
14
+ schema ? block.(schema) : block.()
15
+ else
16
+ EMPTY_ARRAY
17
+ end
18
+ end
19
+
20
+ # @api private
21
+ def blocks
22
+ [*dataset_components.map(&:block), block].compact
23
+ end
24
+
25
+ # @api private
26
+ def evaluate_block(ds, block)
27
+ ds.instance_exec(schema, &block)
28
+ end
29
+
30
+ # @api adapter
31
+ def adapter
32
+ config.adapter
33
+ end
34
+
35
+ # @api adapter
36
+ def relation_id
37
+ config.relation_id
38
+ end
39
+
40
+ private
41
+
42
+ # @api private
43
+ memoize def schema
44
+ if id == relation_id
45
+ registry.schemas[id] if registry.schemas.key?(id)
46
+ elsif relation_id
47
+ registry.fetch("schemas.#{relation_id}.#{id}") {
48
+ registry.fetch("schemas.#{relation_id}")
49
+ }
50
+ elsif registry.schemas.key?(id)
51
+ registry.schemas[id]
52
+ end
53
+ end
54
+ # @api private
55
+ memoize def dataset_components
56
+ provider.components.datasets(abstract: true, adapter: adapter)
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rom/schema/associations_dsl"
4
+ require "rom/relation/name"
5
+
6
+ require_relative "core"
7
+
8
+ module ROM
9
+ module Components
10
+ module DSL
11
+ # Setup DSL-specific relation extensions
12
+ #
13
+ # @private
14
+ class Association < Core
15
+ key :associations
16
+
17
+ # @api private
18
+ def call
19
+ configure
20
+
21
+ backend.instance_eval(&block)
22
+
23
+ backend.call.each do |definition|
24
+ components.add(key, definition: definition, config: config.join(definition, :right))
25
+ end
26
+ end
27
+
28
+ # @api private
29
+ def backend
30
+ @backend ||= ROM::Schema::AssociationsDSL.new(source, inflector)
31
+ end
32
+
33
+ # @api private
34
+ def source
35
+ if provider.config.component.key?(:id)
36
+ # TODO: decouple associations DSL from Relation::Name
37
+ ROM::Relation::Name[
38
+ provider.config.component.id, provider.config.component.dataset
39
+ ]
40
+ else
41
+ config.source
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "core"
4
+
5
+ module ROM
6
+ module Components
7
+ module DSL
8
+ # Command `define` DSL used by Setup#commands
9
+ #
10
+ # @private
11
+ class Command < Core
12
+ key :commands
13
+
14
+ nested(true)
15
+
16
+ # Define a command class
17
+ #
18
+ # @param [Symbol] name of the command
19
+ # @param [Hash] options
20
+ # @option options [Symbol] :type The type of the command
21
+ #
22
+ # @return [Class] generated class
23
+ #
24
+ # @api public
25
+ def define(id, type: id, **options, &block)
26
+ command_type = inflector.classify(type)
27
+ parent = adapter_namespace.const_get(command_type)
28
+
29
+ constant = build_class(name: class_name(command_type), parent: parent) do |dsl|
30
+ config.update(options)
31
+
32
+ config.component.update(dsl.config)
33
+ config.component.update(id: id, adapter: dsl.adapter)
34
+
35
+ class_exec(&block) if block
36
+ end
37
+
38
+ call(constant: constant, config: constant.config.component)
39
+ end
40
+
41
+ # @api private
42
+ def class_name(command_type)
43
+ class_name_inferrer[
44
+ config[:relation],
45
+ type: :command,
46
+ inflector: inflector,
47
+ adapter: adapter,
48
+ command_type: command_type,
49
+ class_namespace: provider.config.class_namespace
50
+ ]
51
+ end
52
+
53
+ # @api private
54
+ def adapter_namespace
55
+ ROM::Command.adapter_namespace(adapter)
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,126 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dry/core/memoizable"
4
+ require "dry/core/class_builder"
5
+
6
+ require "rom/plugins/class_methods"
7
+ require "rom/constants"
8
+ require "rom/initializer"
9
+
10
+ module ROM
11
+ module Components
12
+ module DSL
13
+ # @private
14
+ class Core
15
+ extend Initializer
16
+ extend Dry::Core::ClassAttributes
17
+ include Plugins::ClassMethods
18
+
19
+ defines(:key, :type, :nested)
20
+
21
+ include Dry::Core::Memoizable
22
+
23
+ nested false
24
+
25
+ # @api private
26
+ option :provider
27
+
28
+ # @api private
29
+ option :config, optional: true, default: -> { EMPTY_HASH }
30
+
31
+ # @api private
32
+ option :block, optional: true
33
+
34
+ # @api private
35
+ def self.inherited(klass)
36
+ super
37
+ klass.type(Inflector.component_id(klass).to_sym)
38
+ end
39
+
40
+ # @api private
41
+ def build_class(name: class_name, parent: class_parent, &block)
42
+ Dry::Core::ClassBuilder.new(name: name, parent: parent).call do |klass|
43
+ klass.config.component.update(config)
44
+ klass.class_exec(self, &block) if block
45
+ end
46
+ end
47
+
48
+ # @api private
49
+ def key
50
+ self.class.key
51
+ end
52
+
53
+ # @api private
54
+ def type
55
+ self.class.type
56
+ end
57
+
58
+ # @api private
59
+ def call(**options)
60
+ components.add(key, config: configure, block: block, **options)
61
+ end
62
+
63
+ # @api private
64
+ def configure
65
+ config.freeze
66
+ end
67
+
68
+ # @api private
69
+ def plugin(name, **options)
70
+ plugin = enabled_plugins[name]
71
+ plugin.config.update(options) unless options.empty?
72
+ plugin
73
+ end
74
+
75
+ # @api private
76
+ def enabled_plugins
77
+ config.plugins
78
+ .select { |plugin| plugin.type == type }
79
+ .to_h { |plugin| [plugin.name, plugin] }
80
+ end
81
+
82
+ # @api private
83
+ def enable_plugins
84
+ config.plugins.map! do |plugin|
85
+ if plugin.is_a?(Symbol)
86
+ plugins[plugin].configure.enable(self)
87
+ elsif plugin.type == type
88
+ plugin.configure.enable(respond_to?(:constant) ? constant : self)
89
+ else
90
+ plugin
91
+ end
92
+ end
93
+ end
94
+
95
+ private
96
+
97
+ # @api private
98
+ def components
99
+ provider.components
100
+ end
101
+
102
+ # @api private
103
+ def inflector
104
+ provider.config.component.inflector
105
+ end
106
+
107
+ # @api private
108
+ def class_name_inferrer
109
+ provider.config.class_name_inferrer
110
+ end
111
+
112
+ # @api private
113
+ memoize def adapter
114
+ config.adapter || gateway_adapter
115
+ end
116
+
117
+ # @api private
118
+ def gateway_adapter
119
+ if provider.config.key?(:gateways)
120
+ provider.config.gateways[config.gateway]&.fetch(:adapter)
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "core"
4
+
5
+ module ROM
6
+ module Components
7
+ module DSL
8
+ # @private
9
+ class Dataset < Core
10
+ key :datasets
11
+
12
+ def configure
13
+ if relation?
14
+ config.join!({namespace: relation_id}, :right) if config.id != relation_id
15
+
16
+ config.relation_id = relation_id
17
+ end
18
+ super
19
+ end
20
+
21
+ private
22
+
23
+ def relation_id
24
+ provider.config.component.id
25
+ end
26
+
27
+ def relation?
28
+ provider.config.component.type == :relation
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "core"
4
+
5
+ module ROM
6
+ module Components
7
+ module DSL
8
+ # @private
9
+ class Gateway < Core
10
+ key :gateways
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dry/core/class_builder"
4
+
5
+ require_relative "core"
6
+
7
+ module ROM
8
+ module Components
9
+ module DSL
10
+ # Mapper definition DSL used by Setup DSL
11
+ #
12
+ # @private
13
+ class Mapper < Core
14
+ key(:mappers)
15
+
16
+ nested(true)
17
+
18
+ # Define a mapper class
19
+ #
20
+ # @param [Symbol] id Mapper identifier
21
+ # @param [Hash] options
22
+ #
23
+ # @return [Class]
24
+ #
25
+ # @api public
26
+ def define(id, parent: id, **options, &block)
27
+ class_opts = {name: class_name(id), parent: class_parent(parent)}
28
+
29
+ constant = build_class(**class_opts) do |dsl|
30
+ config.update(options)
31
+
32
+ config.component.update(id: id, relation: parent)
33
+ config.component.join!({namespace: parent}, :right) if dsl.config.namespace != parent
34
+
35
+ class_eval(&block) if block
36
+ end
37
+
38
+ call(constant: constant, config: constant.config.component)
39
+ end
40
+
41
+ # @api private
42
+ def class_parent(parent)
43
+ components.get(:mappers, relation: parent)&.constant || ROM::Mapper
44
+ end
45
+
46
+ # @api private
47
+ def class_name(id)
48
+ "ROM::Mapper[#{id}]"
49
+ end
50
+
51
+ # Register any object as a mapper for a given relation
52
+ #
53
+ # @param [Symbol] relation The relation registry id
54
+ # @param [Hash<Symbol, Object>] mappers A hash with mapper objects
55
+ #
56
+ # @return [Array<Components::Mapper>]
57
+ #
58
+ # @api public
59
+ def register(namespace, mappers)
60
+ mappers.map do |id, mapper|
61
+ call(
62
+ object: mapper,
63
+ config: config.join({id: id, relation: namespace, namespace: namespace}, :right)
64
+ )
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end