rom 2.0.2 → 3.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
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