rom 3.3.3 → 4.0.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 (241) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +2 -599
  3. data/lib/rom/version.rb +1 -1
  4. data/lib/rom.rb +3 -44
  5. metadata +19 -295
  6. data/.gitignore +0 -24
  7. data/.rspec +0 -3
  8. data/.rubocop.yml +0 -87
  9. data/.rubocop_todo.yml +0 -46
  10. data/.travis.yml +0 -24
  11. data/.yardopts +0 -2
  12. data/CODE_OF_CONDUCT.md +0 -13
  13. data/CONTRIBUTING.md +0 -1
  14. data/Gemfile +0 -54
  15. data/Guardfile +0 -24
  16. data/Rakefile +0 -28
  17. data/lib/rom/array_dataset.rb +0 -44
  18. data/lib/rom/association_set.rb +0 -49
  19. data/lib/rom/auto_curry.rb +0 -55
  20. data/lib/rom/command.rb +0 -494
  21. data/lib/rom/command_registry.rb +0 -148
  22. data/lib/rom/commands/class_interface.rb +0 -270
  23. data/lib/rom/commands/composite.rb +0 -53
  24. data/lib/rom/commands/create.rb +0 -13
  25. data/lib/rom/commands/delete.rb +0 -14
  26. data/lib/rom/commands/graph/builder.rb +0 -176
  27. data/lib/rom/commands/graph/class_interface.rb +0 -62
  28. data/lib/rom/commands/graph/input_evaluator.rb +0 -62
  29. data/lib/rom/commands/graph.rb +0 -95
  30. data/lib/rom/commands/lazy/create.rb +0 -23
  31. data/lib/rom/commands/lazy/delete.rb +0 -27
  32. data/lib/rom/commands/lazy/update.rb +0 -34
  33. data/lib/rom/commands/lazy.rb +0 -99
  34. data/lib/rom/commands/result.rb +0 -96
  35. data/lib/rom/commands/update.rb +0 -14
  36. data/lib/rom/commands.rb +0 -3
  37. data/lib/rom/configuration.rb +0 -90
  38. data/lib/rom/configuration_dsl/command.rb +0 -41
  39. data/lib/rom/configuration_dsl/command_dsl.rb +0 -35
  40. data/lib/rom/configuration_dsl/mapper.rb +0 -36
  41. data/lib/rom/configuration_dsl/mapper_dsl.rb +0 -43
  42. data/lib/rom/configuration_dsl/relation.rb +0 -26
  43. data/lib/rom/configuration_dsl.rb +0 -107
  44. data/lib/rom/configuration_plugin.rb +0 -17
  45. data/lib/rom/constants.rb +0 -36
  46. data/lib/rom/container.rb +0 -233
  47. data/lib/rom/create_container.rb +0 -60
  48. data/lib/rom/data_proxy.rb +0 -94
  49. data/lib/rom/enumerable_dataset.rb +0 -68
  50. data/lib/rom/environment.rb +0 -70
  51. data/lib/rom/gateway.rb +0 -196
  52. data/lib/rom/global/plugin_dsl.rb +0 -47
  53. data/lib/rom/global.rb +0 -58
  54. data/lib/rom/initializer.rb +0 -26
  55. data/lib/rom/lint/enumerable_dataset.rb +0 -54
  56. data/lib/rom/lint/gateway.rb +0 -120
  57. data/lib/rom/lint/linter.rb +0 -78
  58. data/lib/rom/lint/spec.rb +0 -20
  59. data/lib/rom/lint/test.rb +0 -98
  60. data/lib/rom/mapper_registry.rb +0 -35
  61. data/lib/rom/memory/commands.rb +0 -56
  62. data/lib/rom/memory/dataset.rb +0 -97
  63. data/lib/rom/memory/gateway.rb +0 -64
  64. data/lib/rom/memory/relation.rb +0 -62
  65. data/lib/rom/memory/schema.rb +0 -13
  66. data/lib/rom/memory/storage.rb +0 -59
  67. data/lib/rom/memory/types.rb +0 -9
  68. data/lib/rom/memory.rb +0 -4
  69. data/lib/rom/pipeline.rb +0 -122
  70. data/lib/rom/plugin.rb +0 -20
  71. data/lib/rom/plugin_base.rb +0 -40
  72. data/lib/rom/plugin_registry.rb +0 -173
  73. data/lib/rom/plugins/command/schema.rb +0 -37
  74. data/lib/rom/plugins/configuration/configuration_dsl.rb +0 -21
  75. data/lib/rom/plugins/relation/instrumentation.rb +0 -51
  76. data/lib/rom/plugins/relation/key_inference.rb +0 -48
  77. data/lib/rom/plugins/relation/registry_reader.rb +0 -33
  78. data/lib/rom/registry.rb +0 -50
  79. data/lib/rom/relation/class_interface.rb +0 -356
  80. data/lib/rom/relation/composite.rb +0 -46
  81. data/lib/rom/relation/curried.rb +0 -109
  82. data/lib/rom/relation/graph.rb +0 -125
  83. data/lib/rom/relation/loaded.rb +0 -127
  84. data/lib/rom/relation/materializable.rb +0 -66
  85. data/lib/rom/relation/name.rb +0 -102
  86. data/lib/rom/relation/view_dsl.rb +0 -64
  87. data/lib/rom/relation.rb +0 -250
  88. data/lib/rom/relation_registry.rb +0 -9
  89. data/lib/rom/schema/attribute.rb +0 -390
  90. data/lib/rom/schema/dsl.rb +0 -67
  91. data/lib/rom/schema.rb +0 -407
  92. data/lib/rom/setup/auto_registration.rb +0 -74
  93. data/lib/rom/setup/auto_registration_strategies/base.rb +0 -16
  94. data/lib/rom/setup/auto_registration_strategies/custom_namespace.rb +0 -63
  95. data/lib/rom/setup/auto_registration_strategies/no_namespace.rb +0 -20
  96. data/lib/rom/setup/auto_registration_strategies/with_namespace.rb +0 -18
  97. data/lib/rom/setup/finalize/finalize_commands.rb +0 -47
  98. data/lib/rom/setup/finalize/finalize_mappers.rb +0 -36
  99. data/lib/rom/setup/finalize/finalize_relations.rb +0 -83
  100. data/lib/rom/setup/finalize.rb +0 -152
  101. data/lib/rom/setup.rb +0 -65
  102. data/lib/rom/support/configurable.rb +0 -85
  103. data/lib/rom/transaction.rb +0 -24
  104. data/lib/rom/types.rb +0 -49
  105. data/log/.gitkeep +0 -0
  106. data/rakelib/benchmark.rake +0 -15
  107. data/rakelib/mutant.rake +0 -19
  108. data/rakelib/rubocop.rake +0 -18
  109. data/rom.gemspec +0 -25
  110. data/spec/fixtures/app/commands/create_user.rb +0 -2
  111. data/spec/fixtures/app/mappers/user_list.rb +0 -2
  112. data/spec/fixtures/app/my_commands/create_user.rb +0 -2
  113. data/spec/fixtures/app/my_mappers/user_list.rb +0 -2
  114. data/spec/fixtures/app/my_relations/users.rb +0 -2
  115. data/spec/fixtures/app/relations/users.rb +0 -2
  116. data/spec/fixtures/custom/commands/create_user.rb +0 -6
  117. data/spec/fixtures/custom/mappers/user_list.rb +0 -6
  118. data/spec/fixtures/custom/relations/users.rb +0 -6
  119. data/spec/fixtures/custom_namespace/commands/create_customer.rb +0 -8
  120. data/spec/fixtures/custom_namespace/mappers/customer_list.rb +0 -8
  121. data/spec/fixtures/custom_namespace/relations/customers.rb +0 -8
  122. data/spec/fixtures/lib/persistence/commands/create_user.rb +0 -6
  123. data/spec/fixtures/lib/persistence/mappers/user_list.rb +0 -6
  124. data/spec/fixtures/lib/persistence/my_commands/create_user.rb +0 -6
  125. data/spec/fixtures/lib/persistence/my_mappers/user_list.rb +0 -6
  126. data/spec/fixtures/lib/persistence/my_relations/users.rb +0 -6
  127. data/spec/fixtures/lib/persistence/relations/users.rb +0 -6
  128. data/spec/fixtures/wrong/commands/create_customer.rb +0 -8
  129. data/spec/fixtures/wrong/mappers/customer_list.rb +0 -8
  130. data/spec/fixtures/wrong/relations/customers.rb +0 -8
  131. data/spec/integration/command_registry_spec.rb +0 -47
  132. data/spec/integration/commands/create_spec.rb +0 -157
  133. data/spec/integration/commands/delete_spec.rb +0 -67
  134. data/spec/integration/commands/error_handling_spec.rb +0 -25
  135. data/spec/integration/commands/graph_builder_spec.rb +0 -213
  136. data/spec/integration/commands/graph_spec.rb +0 -294
  137. data/spec/integration/commands/update_spec.rb +0 -86
  138. data/spec/integration/commands_spec.rb +0 -67
  139. data/spec/integration/gateways/extending_relations_spec.rb +0 -58
  140. data/spec/integration/gateways/setting_logger_spec.rb +0 -34
  141. data/spec/integration/mappers/combine_spec.rb +0 -117
  142. data/spec/integration/mappers/deep_embedded_spec.rb +0 -44
  143. data/spec/integration/mappers/definition_dsl_spec.rb +0 -206
  144. data/spec/integration/mappers/embedded_spec.rb +0 -62
  145. data/spec/integration/mappers/exclude_spec.rb +0 -27
  146. data/spec/integration/mappers/fold_spec.rb +0 -71
  147. data/spec/integration/mappers/group_spec.rb +0 -163
  148. data/spec/integration/mappers/overwrite_attributes_value_spec.rb +0 -51
  149. data/spec/integration/mappers/prefix_separator_spec.rb +0 -52
  150. data/spec/integration/mappers/prefix_spec.rb +0 -48
  151. data/spec/integration/mappers/prefixing_attributes_spec.rb +0 -37
  152. data/spec/integration/mappers/registering_custom_mappers_spec.rb +0 -28
  153. data/spec/integration/mappers/renaming_attributes_spec.rb +0 -125
  154. data/spec/integration/mappers/reusing_mappers_spec.rb +0 -43
  155. data/spec/integration/mappers/step_spec.rb +0 -119
  156. data/spec/integration/mappers/symbolizing_attributes_spec.rb +0 -77
  157. data/spec/integration/mappers/unfold_spec.rb +0 -92
  158. data/spec/integration/mappers/ungroup_spec.rb +0 -126
  159. data/spec/integration/mappers/unwrap_spec.rb +0 -93
  160. data/spec/integration/mappers/wrap_spec.rb +0 -155
  161. data/spec/integration/memory/commands/create_spec.rb +0 -23
  162. data/spec/integration/memory/commands/delete_spec.rb +0 -23
  163. data/spec/integration/memory/commands/update_spec.rb +0 -23
  164. data/spec/integration/multi_env_spec.rb +0 -69
  165. data/spec/integration/multi_repo_spec.rb +0 -46
  166. data/spec/integration/relations/default_dataset_spec.rb +0 -38
  167. data/spec/integration/relations/inheritance_spec.rb +0 -37
  168. data/spec/integration/relations/reading_spec.rb +0 -169
  169. data/spec/integration/relations/registry_dsl_spec.rb +0 -45
  170. data/spec/integration/setup_spec.rb +0 -193
  171. data/spec/shared/command_behavior.rb +0 -28
  172. data/spec/shared/command_graph.rb +0 -54
  173. data/spec/shared/container.rb +0 -9
  174. data/spec/shared/enumerable_dataset.rb +0 -52
  175. data/spec/shared/gateway_only.rb +0 -6
  176. data/spec/shared/materializable.rb +0 -36
  177. data/spec/shared/no_container.rb +0 -16
  178. data/spec/shared/one_behavior.rb +0 -26
  179. data/spec/shared/proxy.rb +0 -0
  180. data/spec/shared/users_and_tasks.rb +0 -10
  181. data/spec/spec_helper.rb +0 -59
  182. data/spec/support/constant_leak_finder.rb +0 -14
  183. data/spec/support/mutant.rb +0 -10
  184. data/spec/support/schema.rb +0 -14
  185. data/spec/support/types.rb +0 -5
  186. data/spec/test/memory_repository_lint_test.rb +0 -27
  187. data/spec/unit/rom/array_dataset_spec.rb +0 -59
  188. data/spec/unit/rom/association_set_spec.rb +0 -48
  189. data/spec/unit/rom/auto_curry_spec.rb +0 -71
  190. data/spec/unit/rom/commands/graph_spec.rb +0 -192
  191. data/spec/unit/rom/commands/lazy_spec.rb +0 -310
  192. data/spec/unit/rom/commands/pre_and_post_processors_spec.rb +0 -343
  193. data/spec/unit/rom/commands/result_spec.rb +0 -70
  194. data/spec/unit/rom/commands_spec.rb +0 -188
  195. data/spec/unit/rom/configurable_spec.rb +0 -49
  196. data/spec/unit/rom/configuration_spec.rb +0 -61
  197. data/spec/unit/rom/container_spec.rb +0 -109
  198. data/spec/unit/rom/create_container_spec.rb +0 -151
  199. data/spec/unit/rom/enumerable_dataset_spec.rb +0 -15
  200. data/spec/unit/rom/environment_spec.rb +0 -123
  201. data/spec/unit/rom/gateway_spec.rb +0 -146
  202. data/spec/unit/rom/mapper_registry_spec.rb +0 -25
  203. data/spec/unit/rom/memory/commands_spec.rb +0 -43
  204. data/spec/unit/rom/memory/dataset_spec.rb +0 -31
  205. data/spec/unit/rom/memory/gateway_spec.rb +0 -12
  206. data/spec/unit/rom/memory/inheritance_spec.rb +0 -32
  207. data/spec/unit/rom/memory/relation_spec.rb +0 -121
  208. data/spec/unit/rom/memory/storage_spec.rb +0 -45
  209. data/spec/unit/rom/plugin_spec.rb +0 -150
  210. data/spec/unit/rom/plugins/command/schema_spec.rb +0 -66
  211. data/spec/unit/rom/plugins/relation/instrumentation_spec.rb +0 -44
  212. data/spec/unit/rom/plugins/relation/key_inference_spec.rb +0 -85
  213. data/spec/unit/rom/registry_spec.rb +0 -86
  214. data/spec/unit/rom/relation/attribute_reader_spec.rb +0 -17
  215. data/spec/unit/rom/relation/call_spec.rb +0 -51
  216. data/spec/unit/rom/relation/composite_spec.rb +0 -106
  217. data/spec/unit/rom/relation/curried_spec.rb +0 -67
  218. data/spec/unit/rom/relation/graph_spec.rb +0 -106
  219. data/spec/unit/rom/relation/lazy/combine_spec.rb +0 -165
  220. data/spec/unit/rom/relation/lazy/graph_spec.rb +0 -165
  221. data/spec/unit/rom/relation/lazy_spec.rb +0 -214
  222. data/spec/unit/rom/relation/loaded_spec.rb +0 -53
  223. data/spec/unit/rom/relation/name_spec.rb +0 -58
  224. data/spec/unit/rom/relation/output_schema_spec.rb +0 -28
  225. data/spec/unit/rom/relation/schema_spec.rb +0 -259
  226. data/spec/unit/rom/relation/view_spec.rb +0 -158
  227. data/spec/unit/rom/relation_spec.rb +0 -252
  228. data/spec/unit/rom/schema/accessing_attributes_spec.rb +0 -52
  229. data/spec/unit/rom/schema/append_spec.rb +0 -17
  230. data/spec/unit/rom/schema/exclude_spec.rb +0 -15
  231. data/spec/unit/rom/schema/finalize_spec.rb +0 -59
  232. data/spec/unit/rom/schema/key_predicate_spec.rb +0 -15
  233. data/spec/unit/rom/schema/merge_spec.rb +0 -17
  234. data/spec/unit/rom/schema/prefix_spec.rb +0 -16
  235. data/spec/unit/rom/schema/project_spec.rb +0 -15
  236. data/spec/unit/rom/schema/rename_spec.rb +0 -22
  237. data/spec/unit/rom/schema/type_spec.rb +0 -49
  238. data/spec/unit/rom/schema/uniq_spec.rb +0 -21
  239. data/spec/unit/rom/schema/wrap_spec.rb +0 -18
  240. data/spec/unit/rom/schema_spec.rb +0 -10
  241. data/spec/unit/rom/setup/auto_registration_spec.rb +0 -214
data/lib/rom/schema.rb DELETED
@@ -1,407 +0,0 @@
1
- require 'dry-equalizer'
2
-
3
- require 'rom/schema/attribute'
4
- require 'rom/schema/dsl'
5
- require 'rom/association_set'
6
-
7
- module ROM
8
- # Relation schema
9
- #
10
- # Schemas hold detailed information about relation tuples, including their
11
- # primitive types (String, Integer, Hash, etc. or custom classes), as well as
12
- # various meta information like primary/foreign key and literally any other
13
- # information that a given database adapter may need.
14
- #
15
- # Adapters can extend this class and it can be used in adapter-specific relations.
16
- # In example rom-sql extends schema with Association DSL and many additional
17
- # SQL-specific APIs in schema types.
18
- #
19
- # Schemas are used for projecting canonical relations into other relations and
20
- # every relation object maintains its schema. This means that we always have
21
- # all information about relation tuples, even when a relation was projected and
22
- # diverged from its canonical form.
23
- #
24
- # Furthermore schema attributes know their source relations, which makes it
25
- # possible to merge schemas from multiple relations and maintain information
26
- # about the source relations. In example when two relations are joined, their
27
- # schemas are merged, and we know which attributes belong to which relation.
28
- #
29
- # @api public
30
- class Schema
31
- EMPTY_ASSOCIATION_SET = AssociationSet.new(EMPTY_HASH).freeze
32
-
33
- DEFAULT_INFERRER = proc { [EMPTY_ARRAY, EMPTY_ARRAY].freeze }
34
-
35
- MissingAttributesError = Class.new(StandardError) do
36
- def initialize(name, attributes)
37
- super("missing attributes in #{name.inspect} schema: #{attributes.map(&:inspect).join(', ')}")
38
- end
39
- end
40
-
41
- include Dry::Equalizer(:name, :attributes, :associations)
42
- include Enumerable
43
-
44
- # @!attribute [r] name
45
- # @return [Symbol] The name of this schema
46
- attr_reader :name
47
-
48
- # @!attribute [r] attributes
49
- # @return [Array] Array with schema attributes
50
- attr_reader :attributes
51
-
52
- # @!attribute [r] associations
53
- # @return [AssociationSet] Optional association set (this is adapter-specific)
54
- attr_reader :associations
55
-
56
- # @!attribute [r] inferrer
57
- # @return [#call] An optional inferrer object used in `finalize!`
58
- attr_reader :inferrer
59
-
60
- # @api private
61
- attr_reader :options
62
-
63
- # @api private
64
- attr_reader :relations
65
-
66
- alias_method :to_ary, :attributes
67
-
68
- # Define a relation schema from plain rom types
69
- #
70
- # Resulting schema will decorate plain rom types with adapter-specific types
71
- # By default `Schema::Attribute` will be used
72
- #
73
- # @param [Relation::Name, Symbol] name The schema name, typically ROM::Relation::Name
74
- #
75
- # @return [Schema]
76
- #
77
- # @api public
78
- def self.define(name, attr_class: Attribute, attributes: EMPTY_ARRAY, associations: EMPTY_ASSOCIATION_SET, inferrer: DEFAULT_INFERRER)
79
- new(
80
- name,
81
- attributes: attributes(attributes, attr_class),
82
- associations: associations,
83
- inferrer: inferrer,
84
- attr_class: attr_class
85
- )
86
- end
87
-
88
- # @api private
89
- def self.attributes(attributes, attr_class)
90
- attributes.map { |type| attr_class.new(type) }
91
- end
92
-
93
- # @api private
94
- def initialize(name, options)
95
- @name = name
96
- @options = options
97
- @attributes = options[:attributes] || EMPTY_ARRAY
98
- @associations = options[:associations]
99
- @inferrer = options[:inferrer] || DEFAULT_INFERRER
100
- @relations = options[:relations] || EMPTY_HASH
101
- end
102
-
103
- # Abstract method for creating a new relation based on schema definition
104
- #
105
- # This can be used by views to generate a new relation automatically.
106
- # In example a schema can project a relation, join any additional relations
107
- # if it uncludes attributes from other relations etc.
108
- #
109
- # Default implementation is a no-op and it simply returns back untouched relation
110
- #
111
- # @param [Relation]
112
- #
113
- # @return [Relation]
114
- #
115
- # @api public
116
- def call(relation)
117
- relation
118
- end
119
-
120
- # Iterate over schema's attributes
121
- #
122
- # @yield [Schema::Attribute]
123
- #
124
- # @api public
125
- def each(&block)
126
- attributes.each(&block)
127
- end
128
-
129
- # Check if schema has any attributes
130
- #
131
- # @return [TrueClass, FalseClass]
132
- #
133
- # @api public
134
- def empty?
135
- attributes.size == 0
136
- end
137
-
138
- # Coerce schema into a <AttributeName=>Attribute> Hash
139
- #
140
- # @return [Hash]
141
- #
142
- # @api public
143
- def to_h
144
- each_with_object({}) { |attr, h| h[attr.name] = attr }
145
- end
146
-
147
- # Return attribute
148
- #
149
- # @param [Symbol] key The attribute name
150
- # @param [Symbol, Relation::Name] src The source relation (for merged schemas)
151
- #
152
- # @raise KeyError
153
- #
154
- # @api public
155
- def [](key, src = name.to_sym)
156
- attr =
157
- if count_index[key].equal?(1)
158
- name_index[key]
159
- else
160
- source_index[src][key]
161
- end
162
-
163
- unless attr
164
- raise(KeyError, "#{key.inspect} attribute doesn't exist in #{src} schema")
165
- end
166
-
167
- attr
168
- end
169
-
170
- # Project a schema to include only specified attributes
171
- #
172
- # @param [*Array<Symbol, Schema::Attribute>] names Attribute names
173
- #
174
- # @return [Schema]
175
- #
176
- # @api public
177
- def project(*names)
178
- new(names.map { |name| name.is_a?(Symbol) ? self[name] : name })
179
- end
180
-
181
- # Exclude provided attributes from a schema
182
- #
183
- # @param [*Array] names Attribute names
184
- #
185
- # @return [Schema]
186
- #
187
- # @api public
188
- def exclude(*names)
189
- project(*(map(&:name) - names))
190
- end
191
-
192
- # Project a schema with renamed attributes
193
- #
194
- # @param [Hash] mapping The attribute mappings
195
- #
196
- # @return [Schema]
197
- #
198
- # @api public
199
- def rename(mapping)
200
- new_attributes = map do |attr|
201
- alias_name = mapping[attr.name]
202
- alias_name ? attr.aliased(alias_name) : attr
203
- end
204
-
205
- new(new_attributes)
206
- end
207
-
208
- # Project a schema with renamed attributes using provided prefix
209
- #
210
- # @param [Symbol] prefix The name of the prefix
211
- #
212
- # @return [Schema]
213
- #
214
- # @api public
215
- def prefix(prefix)
216
- new(map { |attr| attr.prefixed(prefix) })
217
- end
218
-
219
- # Return new schema with all attributes marked as prefixed and wrapped
220
- #
221
- # This is useful when relations are joined and the right side should be marked
222
- # as wrapped
223
- #
224
- # @param [Symbol] prefix The prefix used for aliasing wrapped attributes
225
- #
226
- # @return [Schema]
227
- #
228
- # @api public
229
- def wrap(prefix = name.dataset)
230
- new(map { |attr| attr.wrapped? ? attr : attr.wrapped(prefix) })
231
- end
232
-
233
- # Return FK attribute for a given relation name
234
- #
235
- # @return [Schema::Attribute]
236
- #
237
- # @api public
238
- def foreign_key(relation)
239
- detect { |attr| attr.foreign_key? && attr.target == relation }
240
- end
241
-
242
- # Return primary key attributes
243
- #
244
- # @return [Array<Schema::Attribute>]
245
- #
246
- # @api public
247
- def primary_key
248
- select(&:primary_key?)
249
- end
250
-
251
- # Merge with another schema
252
- #
253
- # @param [Schema] other Other schema
254
- #
255
- # @return [Schema]
256
- #
257
- # @api public
258
- def merge(other)
259
- append(*other)
260
- end
261
- alias_method :+, :merge
262
-
263
- # Append more attributes to the schema
264
- #
265
- # This returns a new schema instance
266
- #
267
- # @param [*Array<Schema::Attribute>]
268
- #
269
- # @return [Schema]
270
- #
271
- # @api public
272
- def append(*new_attributes)
273
- new(attributes + new_attributes)
274
- end
275
-
276
- # Return a new schema with uniq attributes
277
- #
278
- # @param [*Array<Schema::Attribute>]
279
- #
280
- # @return [Schema]
281
- #
282
- # @api public
283
- def uniq(&block)
284
- if block
285
- new(attributes.uniq(&block))
286
- else
287
- new(attributes.uniq(&:name))
288
- end
289
- end
290
-
291
- # Return if a schema includes an attribute with the given name
292
- #
293
- # @param [Symbol] name The name of the attribute
294
- #
295
- # @return [Boolean]
296
- #
297
- # @api public
298
- def key?(name)
299
- ! attributes.detect { |attr| attr.name == name }.nil?
300
- end
301
-
302
- # This hook is called when relation is being build during container finalization
303
- #
304
- # When block is provided it'll be called just before freezing the instance
305
- # so that additional ivars can be set
306
- #
307
- # @return [self]
308
- #
309
- # @api private
310
- def finalize!(gateway: nil, relations: nil, &block)
311
- return self if frozen?
312
-
313
- inferred, missing = inferrer.call(name, gateway)
314
-
315
- attr_names = map(&:name)
316
- inferred_attrs = self.class.attributes(inferred, attr_class).
317
- reject { |attr| attr_names.include?(attr.name) }
318
-
319
- attributes.concat(inferred_attrs)
320
-
321
- missing_attributes = missing - map(&:name)
322
-
323
- if missing_attributes.size > 0
324
- raise MissingAttributesError.new(name, missing_attributes)
325
- end
326
-
327
- block.call if block
328
-
329
- count_index
330
- name_index
331
- source_index
332
-
333
- freeze
334
- end
335
-
336
- # Return coercion function using attribute read types
337
- #
338
- # This is used for `output_schema` in relations
339
- #
340
- # @return [Dry::Types::Hash]
341
- #
342
- # @api private
343
- def to_output_hash
344
- Types::Coercible::Hash.schema(
345
- map { |attr| [attr.key, attr.to_read_type] }.to_h
346
- )
347
- end
348
-
349
- # Return coercion function using attribute types
350
- #
351
- # This is used for `input_schema` in relations, typically commands use it
352
- # for processing input
353
- #
354
- # @return [Dry::Types::Hash]
355
- #
356
- # @api private
357
- def to_input_hash
358
- Types::Coercible::Hash.schema(
359
- map { |attr| [attr.name, attr] }.to_h
360
- )
361
- end
362
-
363
- # Return a new schema with new options
364
- #
365
- # @example
366
- # schema.with(inferrer: my_inferrer)
367
- #
368
- # @param [Hash] new_options
369
- #
370
- # @return [Schema]
371
- #
372
- # @api public
373
- def with(new_options)
374
- self.class.new(name, options.merge(new_options))
375
- end
376
-
377
- private
378
-
379
- # @api private
380
- def count_index
381
- @count_index ||= map(&:name).map { |name| [name, count { |attr| attr.name == name }] }.to_h
382
- end
383
-
384
- # @api private
385
- def name_index
386
- @name_index ||= map { |attr| [attr.name, attr] }.to_h
387
- end
388
-
389
- # @api private
390
- def source_index
391
- @source_index ||= select(&:source).
392
- group_by(&:source).
393
- map { |src, grp| [src.to_sym, grp.map { |attr| [attr.name, attr] }.to_h] }.
394
- to_h
395
- end
396
-
397
- # @api private
398
- def attr_class
399
- options.fetch(:attr_class)
400
- end
401
-
402
- # @api private
403
- def new(attributes)
404
- self.class.new(name, options.merge(attributes: attributes))
405
- end
406
- end
407
- end
@@ -1,74 +0,0 @@
1
- require 'pathname'
2
-
3
- require 'dry/core/inflector'
4
-
5
- require 'rom/types'
6
- require 'rom/initializer'
7
- require 'rom/setup/auto_registration_strategies/no_namespace'
8
- require 'rom/setup/auto_registration_strategies/with_namespace'
9
- require 'rom/setup/auto_registration_strategies/custom_namespace'
10
-
11
- module ROM
12
- class AutoRegistration
13
- extend Initializer
14
-
15
- NamespaceType = Types::Strict::Bool | Types::Strict::String
16
- PathnameType = Types.Constructor(Pathname, &Kernel.method(:Pathname))
17
- DEFAULT_MAPPING = {
18
- relations: :relations,
19
- mappers: :mappers,
20
- commands: :commands
21
- }.freeze
22
-
23
- param :directory, type: PathnameType
24
-
25
- option :namespace, type: NamespaceType, default: -> { true }
26
-
27
- option :component_dirs, type: Types::Strict::Hash, default: -> { DEFAULT_MAPPING }
28
-
29
- option :globs, default: -> {
30
- Hash[
31
- component_dirs.map { |component, path|
32
- [component, directory.join("#{path}/**/*.rb")]
33
- }
34
- ]
35
- }
36
-
37
- def relations
38
- load_entities(:relations)
39
- end
40
-
41
- def commands
42
- load_entities(:commands)
43
- end
44
-
45
- def mappers
46
- load_entities(:mappers)
47
- end
48
-
49
- private
50
-
51
- def load_entities(entity)
52
- Dir[globs[entity]].map do |file|
53
- require file
54
- klass_name =
55
- case namespace
56
- when String
57
- AutoRegistrationStrategies::CustomNamespace.new(
58
- namespace: namespace, file: file, directory: directory
59
- ).call
60
- when TrueClass
61
- AutoRegistrationStrategies::WithNamespace.new(
62
- file: file, directory: directory
63
- ).call
64
- when FalseClass
65
- AutoRegistrationStrategies::NoNamespace.new(
66
- file: file, directory: directory, entity: component_dirs.fetch(entity)
67
- ).call
68
- end
69
-
70
- Dry::Core::Inflector.constantize(klass_name)
71
- end
72
- end
73
- end
74
- end
@@ -1,16 +0,0 @@
1
- require 'rom/types'
2
- require 'rom/initializer'
3
-
4
- module ROM
5
- module AutoRegistrationStrategies
6
- class Base
7
- extend Initializer
8
-
9
- PathnameType = Types.Definition(Pathname).constrained(type: Pathname)
10
-
11
- option :file, type: Types::Strict::String
12
-
13
- EXTENSION_REGEX = /\.rb\z/
14
- end
15
- end
16
- end
@@ -1,63 +0,0 @@
1
- require 'pathname'
2
-
3
- require 'dry/core/inflector'
4
- require 'rom/types'
5
- require 'rom/setup/auto_registration_strategies/base'
6
-
7
- module ROM
8
- module AutoRegistrationStrategies
9
- class CustomNamespace < Base
10
- option :directory, type: PathnameType
11
- option :namespace, type: Types::Strict::String
12
-
13
- def call
14
- potential = []
15
- attempted = []
16
-
17
- path_arr.reverse.each do |dir|
18
- const_fragment = potential.unshift(
19
- Dry::Core::Inflector.camelize(dir)
20
- ).join("::")
21
-
22
- constant = "#{namespace}::#{const_fragment}"
23
-
24
- return constant if ns_const.const_defined?(const_fragment)
25
-
26
- attempted << constant
27
- end
28
-
29
- # If we have reached this point, its means constant is not defined and
30
- # NameError will be thrown if we attempt to camelize something like:
31
- # `"#{namespace}::#{Dry::Core::Inflector.camelize(filename)}"`
32
- # so we can assume naming convention was not respected in required
33
- # file.
34
-
35
- raise NameError, name_error_message(attempted)
36
- end
37
-
38
- private
39
-
40
- def name_error_message(attempted)
41
- "required file does not define expected constant name; either " \
42
- "register your constant explicitly of try following the path" \
43
- "naming convention like:\n\n\t- #{attempted.join("\n\t- ")}\n"
44
- end
45
-
46
- def filename
47
- Pathname(file).basename('.rb')
48
- end
49
-
50
- def ns_const
51
- @namespace_constant ||= Dry::Core::Inflector.constantize(namespace)
52
- end
53
-
54
- def path_arr
55
- file_path << filename
56
- end
57
-
58
- def file_path
59
- File.dirname(file).split("/") - directory.to_s.split("/")
60
- end
61
- end
62
- end
63
- end
@@ -1,20 +0,0 @@
1
- require 'pathname'
2
-
3
- require 'dry/core/inflector'
4
- require 'rom/types'
5
- require 'rom/setup/auto_registration_strategies/base'
6
-
7
- module ROM
8
- module AutoRegistrationStrategies
9
- class NoNamespace < Base
10
- option :directory, type: PathnameType
11
- option :entity, type: Types::Strict::Symbol
12
-
13
- def call
14
- Dry::Core::Inflector.camelize(
15
- file.sub(/^#{directory}\/#{entity}\//, '').sub(EXTENSION_REGEX, '')
16
- )
17
- end
18
- end
19
- end
20
- end
@@ -1,18 +0,0 @@
1
- require 'pathname'
2
-
3
- require 'dry/core/inflector'
4
- require 'rom/setup/auto_registration_strategies/base'
5
-
6
- module ROM
7
- module AutoRegistrationStrategies
8
- class WithNamespace < Base
9
- option :directory, type: PathnameType
10
-
11
- def call
12
- Dry::Core::Inflector.camelize(
13
- file.sub(/^#{directory.dirname}\//, '').sub(EXTENSION_REGEX, '')
14
- )
15
- end
16
- end
17
- end
18
- end
@@ -1,47 +0,0 @@
1
- require 'rom/registry'
2
- require 'rom/command_registry'
3
-
4
- module ROM
5
- class Finalize
6
- class FinalizeCommands
7
- # Build command registry hash for provided relations
8
- #
9
- # @param [RelationRegistry] relations registry
10
- # @param [Hash] gateways
11
- # @param [Array] command_classes a list of command subclasses
12
- #
13
- # @api private
14
- def initialize(relations, gateways, command_classes)
15
- @relations = relations
16
- @gateways = gateways
17
- @command_classes = command_classes
18
- end
19
-
20
- # @return [Hash]
21
- #
22
- # @api private
23
- def run!
24
- registry = @command_classes.each_with_object({}) do |klass, h|
25
- rel_name = klass.relation
26
- next unless rel_name
27
-
28
- relation = @relations[rel_name]
29
- name = klass.register_as || klass.default_name
30
-
31
- gateway = @gateways[relation.class.gateway]
32
- gateway.extend_command_class(klass, relation.dataset)
33
-
34
- klass.extend_for_relation(relation) if klass.restrictable
35
-
36
- (h[rel_name] ||= {})[name] = klass.build(relation)
37
- end
38
-
39
- commands = registry.each_with_object({}) do |(name, rel_commands), h|
40
- h[name] = CommandRegistry.new(name, rel_commands)
41
- end
42
-
43
- Registry.new(commands)
44
- end
45
- end
46
- end
47
- end
@@ -1,36 +0,0 @@
1
- require 'rom/registry'
2
-
3
- module ROM
4
- class Finalize
5
- class FinalizeMappers
6
- # @api private
7
- def initialize(mapper_classes, mapper_objects)
8
- @mapper_classes = mapper_classes
9
- @mapper_objects = mapper_objects
10
- end
11
-
12
- # @api private
13
- def run!
14
- registry = @mapper_classes.each_with_object({}) do |klass, h|
15
- name = klass.register_as || klass.relation
16
- (h[klass.base_relation] ||= {})[name] = klass.build
17
- end
18
-
19
- registry_hash = registry.each_with_object({}).each { |(relation, mappers), h|
20
- h[relation] = MapperRegistry.new(mappers)
21
- }
22
-
23
- @mapper_objects.each do |relation, mappers|
24
- if registry_hash.key?(relation)
25
- mappers_registry = registry_hash[relation]
26
- mappers.each { |name, mapper| mappers_registry[name] = mapper }
27
- else
28
- registry_hash[relation] = MapperRegistry.new(mappers)
29
- end
30
- end
31
-
32
- Registry.new(registry_hash)
33
- end
34
- end
35
- end
36
- end