rom 2.0.2 → 3.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 (149) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +4 -4
  3. data/CHANGELOG.md +34 -1
  4. data/Gemfile +16 -2
  5. data/Rakefile +7 -2
  6. data/lib/rom/array_dataset.rb +44 -0
  7. data/lib/rom/association_set.rb +11 -5
  8. data/lib/rom/auto_curry.rb +55 -0
  9. data/lib/rom/command.rb +70 -41
  10. data/lib/rom/command_registry.rb +7 -18
  11. data/lib/rom/commands/class_interface.rb +7 -6
  12. data/lib/rom/commands/composite.rb +0 -1
  13. data/lib/rom/commands/graph.rb +7 -15
  14. data/lib/rom/commands/lazy/update.rb +1 -1
  15. data/lib/rom/configuration_dsl/command.rb +6 -8
  16. data/lib/rom/configuration_dsl/mapper.rb +2 -3
  17. data/lib/rom/configuration_dsl/mapper_dsl.rb +0 -1
  18. data/lib/rom/configuration_dsl/relation.rb +4 -4
  19. data/lib/rom/configuration_dsl.rb +0 -4
  20. data/lib/rom/constants.rb +1 -1
  21. data/lib/rom/container.rb +0 -2
  22. data/lib/rom/create_container.rb +0 -2
  23. data/lib/rom/data_proxy.rb +94 -0
  24. data/lib/rom/enumerable_dataset.rb +68 -0
  25. data/lib/rom/gateway.rb +23 -6
  26. data/lib/rom/global/plugin_dsl.rb +0 -2
  27. data/lib/rom/global.rb +0 -2
  28. data/lib/rom/initializer.rb +26 -0
  29. data/lib/rom/lint/gateway.rb +17 -0
  30. data/lib/rom/mapper_registry.rb +1 -1
  31. data/lib/rom/memory/commands.rb +0 -2
  32. data/lib/rom/memory/dataset.rb +1 -2
  33. data/lib/rom/memory/relation.rb +14 -1
  34. data/lib/rom/memory/schema.rb +13 -0
  35. data/lib/rom/plugin_registry.rb +1 -1
  36. data/lib/rom/plugins/configuration/configuration_dsl.rb +6 -2
  37. data/lib/rom/plugins/relation/key_inference.rb +4 -2
  38. data/lib/rom/plugins/relation/registry_reader.rb +5 -1
  39. data/lib/rom/registry.rb +50 -0
  40. data/lib/rom/relation/class_interface.rb +94 -26
  41. data/lib/rom/relation/curried.rb +15 -15
  42. data/lib/rom/relation/view_dsl.rb +31 -0
  43. data/lib/rom/relation.rb +49 -34
  44. data/lib/rom/schema/dsl.rb +7 -9
  45. data/lib/rom/schema/type.rb +115 -0
  46. data/lib/rom/schema.rb +218 -18
  47. data/lib/rom/setup/auto_registration.rb +20 -17
  48. data/lib/rom/setup/auto_registration_strategies/base.rb +8 -3
  49. data/lib/rom/setup/auto_registration_strategies/custom_namespace.rb +4 -3
  50. data/lib/rom/setup/auto_registration_strategies/no_namespace.rb +5 -4
  51. data/lib/rom/setup/auto_registration_strategies/with_namespace.rb +3 -3
  52. data/lib/rom/setup/finalize/finalize_commands.rb +1 -1
  53. data/lib/rom/setup/finalize/finalize_mappers.rb +1 -1
  54. data/lib/rom/setup/finalize/finalize_relations.rb +3 -1
  55. data/lib/rom/setup/finalize.rb +1 -1
  56. data/lib/rom/transaction.rb +24 -0
  57. data/lib/rom/types.rb +9 -1
  58. data/lib/rom/version.rb +1 -1
  59. data/lib/rom.rb +4 -8
  60. data/rom.gemspec +4 -3
  61. data/spec/integration/command_registry_spec.rb +1 -14
  62. data/spec/integration/commands/create_spec.rb +5 -25
  63. data/spec/integration/commands/delete_spec.rb +1 -1
  64. data/spec/integration/commands/error_handling_spec.rb +1 -1
  65. data/spec/integration/commands/graph_spec.rb +20 -14
  66. data/spec/integration/commands/update_spec.rb +4 -27
  67. data/spec/integration/commands_spec.rb +1 -1
  68. data/spec/integration/{repositories → gateways}/extending_relations_spec.rb +1 -1
  69. data/spec/integration/{repositories → gateways}/setting_logger_spec.rb +2 -2
  70. data/spec/integration/mappers/combine_spec.rb +1 -1
  71. data/spec/integration/mappers/deep_embedded_spec.rb +1 -1
  72. data/spec/integration/mappers/definition_dsl_spec.rb +1 -1
  73. data/spec/integration/mappers/embedded_spec.rb +1 -1
  74. data/spec/integration/mappers/exclude_spec.rb +1 -1
  75. data/spec/integration/mappers/fold_spec.rb +1 -1
  76. data/spec/integration/mappers/group_spec.rb +1 -1
  77. data/spec/integration/mappers/overwrite_attributes_value_spec.rb +1 -1
  78. data/spec/integration/mappers/prefix_separator_spec.rb +1 -1
  79. data/spec/integration/mappers/prefix_spec.rb +1 -1
  80. data/spec/integration/mappers/prefixing_attributes_spec.rb +1 -1
  81. data/spec/integration/mappers/registering_custom_mappers_spec.rb +1 -1
  82. data/spec/integration/mappers/renaming_attributes_spec.rb +1 -1
  83. data/spec/integration/mappers/reusing_mappers_spec.rb +1 -1
  84. data/spec/integration/mappers/step_spec.rb +1 -1
  85. data/spec/integration/mappers/symbolizing_attributes_spec.rb +1 -1
  86. data/spec/integration/mappers/unfold_spec.rb +1 -1
  87. data/spec/integration/mappers/ungroup_spec.rb +1 -1
  88. data/spec/integration/mappers/unwrap_spec.rb +2 -2
  89. data/spec/integration/mappers/wrap_spec.rb +1 -1
  90. data/spec/integration/memory/commands/create_spec.rb +1 -1
  91. data/spec/integration/memory/commands/delete_spec.rb +1 -1
  92. data/spec/integration/memory/commands/update_spec.rb +1 -1
  93. data/spec/integration/multi_env_spec.rb +1 -1
  94. data/spec/integration/multi_repo_spec.rb +1 -1
  95. data/spec/integration/relations/default_dataset_spec.rb +1 -1
  96. data/spec/integration/relations/reading_spec.rb +1 -1
  97. data/spec/integration/relations/registry_dsl_spec.rb +1 -1
  98. data/spec/integration/setup_spec.rb +10 -4
  99. data/spec/shared/command_graph.rb +8 -4
  100. data/spec/shared/enumerable_dataset.rb +1 -1
  101. data/spec/spec_helper.rb +7 -9
  102. data/spec/support/schema.rb +14 -0
  103. data/spec/unit/rom/array_dataset_spec.rb +59 -0
  104. data/spec/unit/rom/association_set_spec.rb +4 -0
  105. data/spec/unit/rom/auto_curry_spec.rb +63 -0
  106. data/spec/unit/rom/commands/graph_spec.rb +12 -11
  107. data/spec/unit/rom/commands/lazy_spec.rb +8 -5
  108. data/spec/unit/rom/commands/pre_and_post_processors_spec.rb +269 -0
  109. data/spec/unit/rom/commands/result_spec.rb +1 -1
  110. data/spec/unit/rom/commands_spec.rb +9 -3
  111. data/spec/unit/rom/configuration_spec.rb +1 -1
  112. data/spec/unit/rom/container_spec.rb +11 -5
  113. data/spec/unit/rom/create_container_spec.rb +1 -1
  114. data/spec/unit/rom/enumerable_dataset_spec.rb +15 -0
  115. data/spec/unit/rom/gateway_spec.rb +1 -1
  116. data/spec/unit/rom/mapper_registry_spec.rb +1 -1
  117. data/spec/unit/rom/memory/commands_spec.rb +1 -1
  118. data/spec/unit/rom/memory/dataset_spec.rb +1 -1
  119. data/spec/unit/rom/memory/{repository_spec.rb → gateway_spec.rb} +1 -1
  120. data/spec/unit/rom/memory/inheritance_spec.rb +32 -0
  121. data/spec/unit/rom/memory/relation_spec.rb +15 -3
  122. data/spec/unit/rom/memory/storage_spec.rb +1 -1
  123. data/spec/unit/rom/plugin_spec.rb +1 -1
  124. data/spec/unit/rom/plugins/relation/key_inference_spec.rb +1 -1
  125. data/spec/unit/rom/registry_spec.rb +86 -0
  126. data/spec/unit/rom/relation/attribute_reader_spec.rb +17 -0
  127. data/spec/unit/rom/relation/composite_spec.rb +1 -1
  128. data/spec/unit/rom/relation/graph_spec.rb +1 -1
  129. data/spec/unit/rom/relation/lazy/combine_spec.rb +1 -1
  130. data/spec/unit/rom/relation/lazy_spec.rb +1 -1
  131. data/spec/unit/rom/relation/loaded_spec.rb +1 -1
  132. data/spec/unit/rom/relation/schema_spec.rb +10 -6
  133. data/spec/unit/rom/relation/view_spec.rb +112 -0
  134. data/spec/unit/rom/relation_spec.rb +16 -2
  135. data/spec/unit/rom/schema/accessing_attributes_spec.rb +52 -0
  136. data/spec/unit/rom/schema/exclude_spec.rb +15 -0
  137. data/spec/unit/rom/schema/finalize_spec.rb +59 -0
  138. data/spec/unit/rom/schema/key_predicate_spec.rb +15 -0
  139. data/spec/unit/rom/schema/merge_spec.rb +17 -0
  140. data/spec/unit/rom/schema/prefix_spec.rb +16 -0
  141. data/spec/unit/rom/schema/project_spec.rb +15 -0
  142. data/spec/unit/rom/schema/rename_spec.rb +22 -0
  143. data/spec/unit/rom/schema/type_spec.rb +49 -0
  144. data/spec/unit/rom/schema/wrap_spec.rb +17 -0
  145. data/spec/unit/rom/schema_spec.rb +2 -2
  146. metadata +69 -17
  147. data/lib/rom/plugins/relation/view/dsl.rb +0 -32
  148. data/lib/rom/plugins/relation/view.rb +0 -95
  149. data/spec/unit/rom/plugins/relation/view_spec.rb +0 -51
data/lib/rom/schema.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  require 'dry-equalizer'
2
2
 
3
- require 'rom/support/constants'
3
+ require 'rom/schema/type'
4
4
  require 'rom/schema/dsl'
5
5
  require 'rom/association_set'
6
6
 
@@ -10,6 +10,13 @@ module ROM
10
10
  # @api public
11
11
  class Schema
12
12
  EMPTY_ASSOCIATION_SET = AssociationSet.new(EMPTY_HASH).freeze
13
+ DEFAULT_INFERRER = proc { [EMPTY_ARRAY, EMPTY_ARRAY].freeze }
14
+
15
+ MissingAttributesError = Class.new(StandardError) do
16
+ def initialize(name, attributes)
17
+ super("missing attributes in #{name.inspect} schema: #{attributes.map(&:inspect).join(', ')}")
18
+ end
19
+ end
13
20
 
14
21
  include Dry::Equalizer(:name, :attributes, :associations)
15
22
  include Enumerable
@@ -19,7 +26,7 @@ module ROM
19
26
  attr_reader :name
20
27
 
21
28
  # @!attribute [r] attributes
22
- # @return [Hash] The hash with schema attribute types
29
+ # @return [Array] Array with schema attributes
23
30
  attr_reader :attributes
24
31
 
25
32
  # @!attribute [r] associations
@@ -30,34 +37,146 @@ module ROM
30
37
  # @return [#call] An optional inferrer object used in `finalize!`
31
38
  attr_reader :inferrer
32
39
 
33
- # @!attribute [r] primary_key
34
- # @return [Array<Dry::Types::Definition] Primary key array
35
- attr_reader :primary_key
40
+ # @api private
41
+ attr_reader :options
42
+
43
+ # @api private
44
+ attr_reader :relations
45
+
46
+ alias_method :to_ary, :attributes
36
47
 
37
- alias_method :to_h, :attributes
48
+ # @api public
49
+ def self.define(name, type_class: Type, attributes: EMPTY_ARRAY, associations: EMPTY_ASSOCIATION_SET, inferrer: DEFAULT_INFERRER)
50
+ new(
51
+ name,
52
+ attributes: attributes(attributes, type_class),
53
+ associations: associations,
54
+ inferrer: inferrer,
55
+ type_class: type_class
56
+ )
57
+ end
58
+
59
+ # @api private
60
+ def self.attributes(attributes, type_class)
61
+ attributes.map { |type| type_class.new(type) }
62
+ end
38
63
 
39
64
  # @api private
40
- def initialize(name, attributes, inferrer: nil, associations: EMPTY_ASSOCIATION_SET)
65
+ def initialize(name, options)
41
66
  @name = name
42
- @attributes = attributes
43
- @associations = associations
44
- @inferrer = inferrer
67
+ @options = options
68
+ @attributes = options[:attributes] || EMPTY_ARRAY
69
+ @associations = options[:associations]
70
+ @inferrer = options[:inferrer] || DEFAULT_INFERRER
71
+ @relations = options[:relations] || EMPTY_HASH
72
+ end
73
+
74
+ # Abstract method for creating a new relation based on schema definition
75
+ #
76
+ # This can be used by views to generate a new relation automatically.
77
+ # In example a schema can project a relation, join any additional relations
78
+ # if it uncludes attributes from other relations etc.
79
+ #
80
+ # Default implementation is a no-op and it simply returns back untouched relation
81
+ #
82
+ # @param [Relation]
83
+ #
84
+ # @return [Relation]
85
+ #
86
+ # @api public
87
+ def call(relation)
88
+ relation
45
89
  end
46
90
 
47
91
  # Iterate over schema's attributes
48
92
  #
49
- # @yield [Dry::Data::Type]
93
+ # @yield [Schema::Type]
50
94
  #
51
95
  # @api public
52
96
  def each(&block)
53
- attributes.each_value(&block)
97
+ attributes.each(&block)
98
+ end
99
+
100
+ # @api public
101
+ def empty?
102
+ attributes.size == 0
103
+ end
104
+
105
+ # @api public
106
+ def to_h
107
+ each_with_object({}) { |attr, h| h[attr.name] = attr }
54
108
  end
55
109
 
56
110
  # Return attribute
57
111
  #
58
112
  # @api public
59
- def [](name)
60
- attributes.fetch(name)
113
+ def [](key, src = name.to_sym)
114
+ attr =
115
+ if count_index[key].equal?(1)
116
+ name_index[key]
117
+ else
118
+ source_index[src][key]
119
+ end
120
+
121
+ unless attr
122
+ raise(KeyError, "#{key.inspect} attribute doesn't exist in #{src} schema")
123
+ end
124
+
125
+ attr
126
+ end
127
+
128
+ # Project a schema to include only specified attributes
129
+ #
130
+ # @param [*Array] names Attribute names
131
+ #
132
+ # @return [Schema]
133
+ #
134
+ # @api public
135
+ def project(*names)
136
+ new(names.map { |name| name.is_a?(Symbol) ? self[name] : name })
137
+ end
138
+
139
+ # Exclude provided attributes from a schema
140
+ #
141
+ # @param [*Array] names Attribute names
142
+ #
143
+ # @return [Schema]
144
+ #
145
+ # @api public
146
+ def exclude(*names)
147
+ project(*(map(&:name) - names))
148
+ end
149
+
150
+ # Project a schema with renamed attributes
151
+ #
152
+ # @param [Hash] mapping The attribute mappings
153
+ #
154
+ # @return [Schema]
155
+ #
156
+ # @api public
157
+ def rename(mapping)
158
+ new_attributes = map do |attr|
159
+ alias_name = mapping[attr.name]
160
+ alias_name ? attr.aliased(alias_name) : attr
161
+ end
162
+
163
+ new(new_attributes)
164
+ end
165
+
166
+ # Project a schema with renamed attributes using provided prefix
167
+ #
168
+ # @param [Symbol] prefix The name of the prefix
169
+ #
170
+ # @return [Schema]
171
+ #
172
+ # @api public
173
+ def prefix(prefix)
174
+ new(map { |attr| attr.prefixed(prefix) })
175
+ end
176
+
177
+ # @api public
178
+ def wrap(prefix = name.dataset)
179
+ new(map { |attr| attr.wrapped(prefix) })
61
180
  end
62
181
 
63
182
  # Return FK attribute for a given relation name
@@ -66,7 +185,39 @@ module ROM
66
185
  #
67
186
  # @api public
68
187
  def foreign_key(relation)
69
- detect { |attr| attr.meta[:foreign_key] && attr.meta[:relation] == relation }
188
+ detect { |attr| attr.foreign_key? && attr.target == relation }
189
+ end
190
+
191
+ # Return primary key attributes
192
+ #
193
+ # @return [Array<Schema::Type>]
194
+ #
195
+ # @api public
196
+ def primary_key
197
+ select(&:primary_key?)
198
+ end
199
+
200
+ # Merge with another schema
201
+ #
202
+ # @param [Schema] other Other schema
203
+ #
204
+ # @return [Schema]
205
+ #
206
+ # @api public
207
+ def merge(other)
208
+ new(attributes + other.attributes)
209
+ end
210
+ alias_method :+, :merge
211
+
212
+ # Return if a schema includes an attribute with the given name
213
+ #
214
+ # @param [Symbol] name The name of the attribute
215
+ #
216
+ # @return [Boolean]
217
+ #
218
+ # @api public
219
+ def key?(name)
220
+ ! attributes.detect { |attr| attr.name == name }.nil?
70
221
  end
71
222
 
72
223
  # This hook is called when relation is being build during container finalization
@@ -77,13 +228,62 @@ module ROM
77
228
  # @return [self]
78
229
  #
79
230
  # @api private
80
- def finalize!(gateway = nil, &block)
231
+ def finalize!(gateway: nil, relations: nil, &block)
81
232
  return self if frozen?
82
233
 
83
- @attributes = inferrer.call(name.dataset, gateway) if inferrer
84
- @primary_key = select { |attr| attr.meta[:primary_key] == true }
234
+ inferred, missing = inferrer.call(name, gateway)
235
+
236
+ attr_names = map(&:name)
237
+ inferred_attrs = self.class.attributes(inferred, type_class).
238
+ reject { |attr| attr_names.include?(attr.name) }
239
+
240
+ attributes.concat(inferred_attrs)
241
+
242
+ missing_attributes = missing - map(&:name)
243
+
244
+ if missing_attributes.size > 0
245
+ raise MissingAttributesError.new(name, missing_attributes)
246
+ end
247
+
248
+ options[:relations] = @relations = relations
249
+
85
250
  block.call if block
251
+
252
+ count_index
253
+ name_index
254
+ source_index
255
+
86
256
  freeze
87
257
  end
258
+
259
+ private
260
+
261
+ # @api private
262
+ def count_index
263
+ @count_index ||= map(&:name).map { |name| [name, count { |attr| attr.name == name }] }.to_h
264
+ end
265
+
266
+ # @api private
267
+ def name_index
268
+ @name_index ||= map { |attr| [attr.name, attr] }.to_h
269
+ end
270
+
271
+ # @api private
272
+ def source_index
273
+ @source_index ||= select(&:source).
274
+ group_by(&:source).
275
+ map { |src, grp| [src.to_sym, grp.map { |attr| [attr.name, attr] }.to_h] }.
276
+ to_h
277
+ end
278
+
279
+ # @api private
280
+ def type_class
281
+ options.fetch(:type_class)
282
+ end
283
+
284
+ # @api private
285
+ def new(attributes)
286
+ self.class.new(name, options.merge(attributes: attributes))
287
+ end
88
288
  end
89
289
  end
@@ -1,34 +1,37 @@
1
1
  require 'pathname'
2
2
 
3
- require 'rom/support/constants'
4
- require 'rom/support/inflector'
5
- require 'rom/support/options'
3
+ require 'dry/core/inflector'
6
4
 
5
+ require 'rom/types'
6
+ require 'rom/initializer'
7
7
  require 'rom/setup/auto_registration_strategies/no_namespace'
8
8
  require 'rom/setup/auto_registration_strategies/with_namespace'
9
9
  require 'rom/setup/auto_registration_strategies/custom_namespace'
10
10
 
11
11
  module ROM
12
12
  class AutoRegistration
13
- include Options
13
+ extend Initializer
14
14
 
15
- option :namespace, reader: true, type: [TrueClass, FalseClass, String], default: true
15
+ NamespaceType = Types::Strict::Bool | Types::Strict::String
16
+ PathnameType = Types.Constructor(Pathname, &Kernel.method(:Pathname))
16
17
 
17
- option :component_dirs, reader: true, type: ::Hash, default: {
18
+ param :directory, type: PathnameType
19
+
20
+ option :namespace, reader: true, type: NamespaceType, default: proc { true }
21
+
22
+ option :component_dirs, reader: true, type: Types::Strict::Hash, default: proc { {
18
23
  relations: :relations,
19
24
  mappers: :mappers,
20
25
  commands: :commands
21
- }
26
+ } }
22
27
 
23
- attr_reader :globs, :directory
24
-
25
- def initialize(directory, options = EMPTY_HASH)
26
- super
27
- @directory = Pathname(directory)
28
- @globs = Hash[component_dirs.map { |component, directory|
29
- [component, @directory.join("#{directory}/**/*.rb")]
30
- }]
31
- end
28
+ option :globs, reader: true, default: -> r {
29
+ Hash[
30
+ component_dirs.map { |component, directory|
31
+ [component, r.directory.join("#{directory}/**/*.rb")]
32
+ }
33
+ ]
34
+ }
32
35
 
33
36
  def relations
34
37
  load_entities(:relations)
@@ -62,7 +65,7 @@ module ROM
62
65
  file: file, directory: directory, entity: component_dirs.fetch(entity)
63
66
  ).call
64
67
  end
65
- Inflector.constantize(klass_name)
68
+ Dry::Core::Inflector.constantize(klass_name)
66
69
  end
67
70
  end
68
71
  end
@@ -1,11 +1,16 @@
1
+ require 'rom/types'
2
+ require 'rom/initializer'
3
+
1
4
  module ROM
2
5
  module AutoRegistrationStrategies
3
6
  class Base
4
- include Options
7
+ extend Initializer
8
+
9
+ PathnameType = Types.Definition(Pathname).constrained(type: Pathname)
5
10
 
6
- option :file, reader: true, type: String
11
+ option :file, reader: true, type: Types::Strict::String
7
12
 
8
- EXTENSION_REGEX = /\.rb$/.freeze
13
+ EXTENSION_REGEX = /\.rb\z/.freeze
9
14
  end
10
15
  end
11
16
  end
@@ -1,15 +1,16 @@
1
1
  require 'pathname'
2
2
 
3
- require 'rom/support/inflector'
3
+ require 'dry/core/inflector'
4
+ require 'rom/types'
4
5
  require 'rom/setup/auto_registration_strategies/base'
5
6
 
6
7
  module ROM
7
8
  module AutoRegistrationStrategies
8
9
  class CustomNamespace < Base
9
- option :namespace, reader: true, type: String
10
+ option :namespace, reader: true, type: Types::Strict::String
10
11
 
11
12
  def call
12
- "#{namespace}::#{Inflector.camelize(filename)}"
13
+ "#{namespace}::#{Dry::Core::Inflector.camelize(filename)}"
13
14
  end
14
15
 
15
16
  private
@@ -1,16 +1,17 @@
1
1
  require 'pathname'
2
2
 
3
- require 'rom/support/inflector'
3
+ require 'dry/core/inflector'
4
+ require 'rom/types'
4
5
  require 'rom/setup/auto_registration_strategies/base'
5
6
 
6
7
  module ROM
7
8
  module AutoRegistrationStrategies
8
9
  class NoNamespace < Base
9
- option :directory, reader: true, type: Pathname
10
- option :entity, reader: true, type: Symbol
10
+ option :directory, reader: true, type: PathnameType
11
+ option :entity, reader: true, type: Types::Strict::Symbol
11
12
 
12
13
  def call
13
- Inflector.camelize(
14
+ Dry::Core::Inflector.camelize(
14
15
  file.sub(/^#{directory}\/#{entity}\//, '').sub(EXTENSION_REGEX, '')
15
16
  )
16
17
  end
@@ -1,15 +1,15 @@
1
1
  require 'pathname'
2
2
 
3
- require 'rom/support/inflector'
3
+ require 'dry/core/inflector'
4
4
  require 'rom/setup/auto_registration_strategies/base'
5
5
 
6
6
  module ROM
7
7
  module AutoRegistrationStrategies
8
8
  class WithNamespace < Base
9
- option :directory, reader: true, type: Pathname
9
+ option :directory, reader: true, type: PathnameType
10
10
 
11
11
  def call
12
- Inflector.camelize(
12
+ Dry::Core::Inflector.camelize(
13
13
  file.sub(/^#{directory.dirname}\//, '').sub(EXTENSION_REGEX, '')
14
14
  )
15
15
  end
@@ -1,4 +1,4 @@
1
- require 'rom/support/registry'
1
+ require 'rom/registry'
2
2
  require 'rom/command_registry'
3
3
 
4
4
  module ROM
@@ -1,4 +1,4 @@
1
- require 'rom/support/registry'
1
+ require 'rom/registry'
2
2
 
3
3
  module ROM
4
4
  class Finalize
@@ -50,7 +50,9 @@ module ROM
50
50
  gateway = @gateways.fetch(klass.gateway)
51
51
  ds_proc = klass.dataset_proc || -> _ { self }
52
52
 
53
- klass.schema.finalize!(gateway) if klass.schema
53
+ klass.schema(infer: true) unless klass.schema
54
+ klass.schema.finalize!(gateway: gateway, relations: registry)
55
+
54
56
  dataset = gateway.dataset(klass.dataset).instance_exec(klass, &ds_proc)
55
57
 
56
58
  klass.new(dataset, __registry__: registry)
@@ -1,7 +1,7 @@
1
1
  require 'rom/relation'
2
2
  require 'rom/command'
3
3
 
4
- require 'rom/support/registry'
4
+ require 'rom/registry'
5
5
  require 'rom/command_registry'
6
6
  require 'rom/mapper_registry'
7
7
 
@@ -0,0 +1,24 @@
1
+ module ROM
2
+ # @api private
3
+ class Transaction
4
+ # @api private
5
+ Rollback = Class.new(StandardError)
6
+
7
+ # @api private
8
+ def run(opts = EMPTY_HASH)
9
+ yield(self)
10
+ rescue Rollback
11
+ # noop
12
+ end
13
+
14
+ # Unconditionally roll back the current transaction
15
+ #
16
+ # @api public
17
+ def rollback!
18
+ raise Rollback
19
+ end
20
+
21
+ # @api private
22
+ NoOp = Transaction.new.freeze
23
+ end
24
+ end
data/lib/rom/types.rb CHANGED
@@ -9,9 +9,17 @@ module ROM
9
9
  super
10
10
  end
11
11
 
12
+ def self.Definition(primitive)
13
+ Dry::Types::Definition.new(primitive)
14
+ end
15
+
16
+ def self.Constructor(primitive, &block)
17
+ Types.Definition(primitive).constructor(&block)
18
+ end
19
+
12
20
  module Methods
13
21
  def ForeignKey(relation, type = Types::Int)
14
- type.meta(foreign_key: true, relation: relation)
22
+ type.meta(foreign_key: true, target: relation)
15
23
  end
16
24
  end
17
25
  end
data/lib/rom/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module ROM
2
- VERSION = '2.0.2'.freeze
2
+ VERSION = '3.0.0.beta1'.freeze
3
3
  end
data/lib/rom.rb CHANGED
@@ -1,16 +1,12 @@
1
1
  require 'dry-equalizer'
2
+ require 'dry/core/constants'
2
3
 
3
- require 'rom-support'
4
4
  require 'rom/version'
5
5
  require 'rom/constants'
6
6
 
7
- # internal ROM support lib
8
- require 'rom/support/inflector'
9
- require 'rom/support/registry'
10
- require 'rom/support/options'
11
- require 'rom/support/class_macros'
12
- require 'rom/support/class_builder'
13
- require 'rom/support/inheritance_hook'
7
+ module ROM
8
+ include Dry::Core::Constants
9
+ end
14
10
 
15
11
  # core parts
16
12
  require 'rom/configuration_plugin'
data/rom.gemspec CHANGED
@@ -18,9 +18,10 @@ Gem::Specification.new do |gem|
18
18
  gem.add_runtime_dependency 'concurrent-ruby', '~> 1.0'
19
19
  gem.add_runtime_dependency 'dry-equalizer', '~> 0.2'
20
20
  gem.add_runtime_dependency 'dry-types', '~> 0.8'
21
- gem.add_runtime_dependency 'rom-support', '~> 2.0'
22
- gem.add_runtime_dependency 'rom-mapper', '~> 0.4.0'
21
+ gem.add_runtime_dependency 'dry-core', '~> 0.2', '>= 0.2.3'
22
+ gem.add_runtime_dependency 'dry-initializer', '~> 0.10', '>= 0.10.2'
23
+ gem.add_runtime_dependency 'rom-mapper', '~> 0.5.0.beta'
23
24
 
24
25
  gem.add_development_dependency 'rake', '~> 10.3'
25
- gem.add_development_dependency 'rspec', '~> 3.3'
26
+ gem.add_development_dependency 'rspec', '~> 3.5'
26
27
  end
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe 'ROM::CommandRegistry' do
3
+ RSpec.describe 'ROM::CommandRegistry' do
4
4
  include_context 'container'
5
5
 
6
6
  let(:users) { container.command(:users) }
@@ -11,7 +11,6 @@ describe 'ROM::CommandRegistry' do
11
11
  configuration.register_command(Class.new(ROM::Commands::Create[:memory]) do
12
12
  register_as :create
13
13
  relation :users
14
- validator proc { |input| raise(ROM::CommandError) unless input[:name] }
15
14
  end)
16
15
  end
17
16
 
@@ -41,18 +40,6 @@ describe 'ROM::CommandRegistry' do
41
40
  expect(result).to match_array([{ name: 'Jane' }])
42
41
  end
43
42
 
44
- it 'returns a failure result object on failed execution' do
45
- result = users.try { users.create.call({}) }
46
-
47
- expect(result.value).to be(nil)
48
- end
49
-
50
- it 'returns a failure result on unsuccessful curried-command execution' do
51
- result = users.try { users.create.curry({}) }
52
-
53
- expect(result.value).to be(nil)
54
- end
55
-
56
43
  it 'allows checking if a command is available using respond_to?' do
57
44
  expect(users).to respond_to(:create)
58
45
  end
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
  require 'dry-struct'
3
3
 
4
- describe 'Commands / Create' do
4
+ RSpec.describe 'Commands / Create' do
5
5
  include_context 'container'
6
6
  include_context 'users and tasks'
7
7
 
@@ -9,18 +9,6 @@ describe 'Commands / Create' do
9
9
  let(:tasks) { container.commands.tasks }
10
10
 
11
11
  before do
12
- module Test
13
- UserValidator = Class.new do
14
- ValidationError = Class.new(ROM::CommandError)
15
-
16
- def self.call(params)
17
- unless params[:name] && params[:email]
18
- raise ValidationError, ":name and :email are required"
19
- end
20
- end
21
- end
22
- end
23
-
24
12
  configuration.relation(:users)
25
13
  configuration.relation(:tasks)
26
14
 
@@ -28,16 +16,16 @@ describe 'Commands / Create' do
28
16
  relation :users
29
17
  register_as :create
30
18
  result :one
31
- validator Test::UserValidator
32
19
  end
33
20
 
34
21
  class Test::CreateTask < ROM::Commands::Create[:memory]
35
22
  relation :tasks
36
23
  register_as :create
37
24
  result :one
25
+ before :associate
38
26
 
39
- def execute(task, user)
40
- super(task.merge(name: user.to_h[:name]))
27
+ def associate(task, user)
28
+ task.merge(name: user.to_h[:name])
41
29
  end
42
30
  end
43
31
 
@@ -89,14 +77,6 @@ describe 'Commands / Create' do
89
77
  expect(result.value).to eql(name: 'Piotr', title: 'Finish command-api')
90
78
  end
91
79
 
92
- it 'returns validation object with errors on failed validation' do
93
- result = users.try { users.create.call(name: 'Piotr') }
94
-
95
- expect(result.error).to be_instance_of(Test::ValidationError)
96
- expect(result.error.message).to eql(":name and :email are required")
97
- expect(container.relations.users.count).to be(2)
98
- end
99
-
100
80
  describe '"result" option' do
101
81
  it 'returns a single tuple when set to :one' do
102
82
  configuration.commands(:users) do
@@ -122,7 +102,7 @@ describe 'Commands / Create' do
122
102
  end
123
103
  end
124
104
  container
125
- }.to raise_error(ROM::Options::InvalidOptionValueError)
105
+ }.to raise_error(Dry::Types::ConstraintError)
126
106
  end
127
107
  end
128
108
 
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe 'Commands / Delete' do
3
+ RSpec.describe 'Commands / Delete' do
4
4
  include_context 'container'
5
5
  include_context 'users and tasks'
6
6