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.
- checksums.yaml +4 -4
- data/.travis.yml +4 -4
- data/CHANGELOG.md +34 -1
- data/Gemfile +16 -2
- data/Rakefile +7 -2
- data/lib/rom/array_dataset.rb +44 -0
- data/lib/rom/association_set.rb +11 -5
- data/lib/rom/auto_curry.rb +55 -0
- data/lib/rom/command.rb +70 -41
- data/lib/rom/command_registry.rb +7 -18
- data/lib/rom/commands/class_interface.rb +7 -6
- data/lib/rom/commands/composite.rb +0 -1
- data/lib/rom/commands/graph.rb +7 -15
- data/lib/rom/commands/lazy/update.rb +1 -1
- data/lib/rom/configuration_dsl/command.rb +6 -8
- data/lib/rom/configuration_dsl/mapper.rb +2 -3
- data/lib/rom/configuration_dsl/mapper_dsl.rb +0 -1
- data/lib/rom/configuration_dsl/relation.rb +4 -4
- data/lib/rom/configuration_dsl.rb +0 -4
- data/lib/rom/constants.rb +1 -1
- data/lib/rom/container.rb +0 -2
- data/lib/rom/create_container.rb +0 -2
- data/lib/rom/data_proxy.rb +94 -0
- data/lib/rom/enumerable_dataset.rb +68 -0
- data/lib/rom/gateway.rb +23 -6
- data/lib/rom/global/plugin_dsl.rb +0 -2
- data/lib/rom/global.rb +0 -2
- data/lib/rom/initializer.rb +26 -0
- data/lib/rom/lint/gateway.rb +17 -0
- data/lib/rom/mapper_registry.rb +1 -1
- data/lib/rom/memory/commands.rb +0 -2
- data/lib/rom/memory/dataset.rb +1 -2
- data/lib/rom/memory/relation.rb +14 -1
- data/lib/rom/memory/schema.rb +13 -0
- data/lib/rom/plugin_registry.rb +1 -1
- data/lib/rom/plugins/configuration/configuration_dsl.rb +6 -2
- data/lib/rom/plugins/relation/key_inference.rb +4 -2
- data/lib/rom/plugins/relation/registry_reader.rb +5 -1
- data/lib/rom/registry.rb +50 -0
- data/lib/rom/relation/class_interface.rb +94 -26
- data/lib/rom/relation/curried.rb +15 -15
- data/lib/rom/relation/view_dsl.rb +31 -0
- data/lib/rom/relation.rb +49 -34
- data/lib/rom/schema/dsl.rb +7 -9
- data/lib/rom/schema/type.rb +115 -0
- data/lib/rom/schema.rb +218 -18
- data/lib/rom/setup/auto_registration.rb +20 -17
- data/lib/rom/setup/auto_registration_strategies/base.rb +8 -3
- data/lib/rom/setup/auto_registration_strategies/custom_namespace.rb +4 -3
- data/lib/rom/setup/auto_registration_strategies/no_namespace.rb +5 -4
- data/lib/rom/setup/auto_registration_strategies/with_namespace.rb +3 -3
- data/lib/rom/setup/finalize/finalize_commands.rb +1 -1
- data/lib/rom/setup/finalize/finalize_mappers.rb +1 -1
- data/lib/rom/setup/finalize/finalize_relations.rb +3 -1
- data/lib/rom/setup/finalize.rb +1 -1
- data/lib/rom/transaction.rb +24 -0
- data/lib/rom/types.rb +9 -1
- data/lib/rom/version.rb +1 -1
- data/lib/rom.rb +4 -8
- data/rom.gemspec +4 -3
- data/spec/integration/command_registry_spec.rb +1 -14
- data/spec/integration/commands/create_spec.rb +5 -25
- data/spec/integration/commands/delete_spec.rb +1 -1
- data/spec/integration/commands/error_handling_spec.rb +1 -1
- data/spec/integration/commands/graph_spec.rb +20 -14
- data/spec/integration/commands/update_spec.rb +4 -27
- data/spec/integration/commands_spec.rb +1 -1
- data/spec/integration/{repositories → gateways}/extending_relations_spec.rb +1 -1
- data/spec/integration/{repositories → gateways}/setting_logger_spec.rb +2 -2
- data/spec/integration/mappers/combine_spec.rb +1 -1
- data/spec/integration/mappers/deep_embedded_spec.rb +1 -1
- data/spec/integration/mappers/definition_dsl_spec.rb +1 -1
- data/spec/integration/mappers/embedded_spec.rb +1 -1
- data/spec/integration/mappers/exclude_spec.rb +1 -1
- data/spec/integration/mappers/fold_spec.rb +1 -1
- data/spec/integration/mappers/group_spec.rb +1 -1
- data/spec/integration/mappers/overwrite_attributes_value_spec.rb +1 -1
- data/spec/integration/mappers/prefix_separator_spec.rb +1 -1
- data/spec/integration/mappers/prefix_spec.rb +1 -1
- data/spec/integration/mappers/prefixing_attributes_spec.rb +1 -1
- data/spec/integration/mappers/registering_custom_mappers_spec.rb +1 -1
- data/spec/integration/mappers/renaming_attributes_spec.rb +1 -1
- data/spec/integration/mappers/reusing_mappers_spec.rb +1 -1
- data/spec/integration/mappers/step_spec.rb +1 -1
- data/spec/integration/mappers/symbolizing_attributes_spec.rb +1 -1
- data/spec/integration/mappers/unfold_spec.rb +1 -1
- data/spec/integration/mappers/ungroup_spec.rb +1 -1
- data/spec/integration/mappers/unwrap_spec.rb +2 -2
- data/spec/integration/mappers/wrap_spec.rb +1 -1
- data/spec/integration/memory/commands/create_spec.rb +1 -1
- data/spec/integration/memory/commands/delete_spec.rb +1 -1
- data/spec/integration/memory/commands/update_spec.rb +1 -1
- data/spec/integration/multi_env_spec.rb +1 -1
- data/spec/integration/multi_repo_spec.rb +1 -1
- data/spec/integration/relations/default_dataset_spec.rb +1 -1
- data/spec/integration/relations/reading_spec.rb +1 -1
- data/spec/integration/relations/registry_dsl_spec.rb +1 -1
- data/spec/integration/setup_spec.rb +10 -4
- data/spec/shared/command_graph.rb +8 -4
- data/spec/shared/enumerable_dataset.rb +1 -1
- data/spec/spec_helper.rb +7 -9
- data/spec/support/schema.rb +14 -0
- data/spec/unit/rom/array_dataset_spec.rb +59 -0
- data/spec/unit/rom/association_set_spec.rb +4 -0
- data/spec/unit/rom/auto_curry_spec.rb +63 -0
- data/spec/unit/rom/commands/graph_spec.rb +12 -11
- data/spec/unit/rom/commands/lazy_spec.rb +8 -5
- data/spec/unit/rom/commands/pre_and_post_processors_spec.rb +269 -0
- data/spec/unit/rom/commands/result_spec.rb +1 -1
- data/spec/unit/rom/commands_spec.rb +9 -3
- data/spec/unit/rom/configuration_spec.rb +1 -1
- data/spec/unit/rom/container_spec.rb +11 -5
- data/spec/unit/rom/create_container_spec.rb +1 -1
- data/spec/unit/rom/enumerable_dataset_spec.rb +15 -0
- data/spec/unit/rom/gateway_spec.rb +1 -1
- data/spec/unit/rom/mapper_registry_spec.rb +1 -1
- data/spec/unit/rom/memory/commands_spec.rb +1 -1
- data/spec/unit/rom/memory/dataset_spec.rb +1 -1
- data/spec/unit/rom/memory/{repository_spec.rb → gateway_spec.rb} +1 -1
- data/spec/unit/rom/memory/inheritance_spec.rb +32 -0
- data/spec/unit/rom/memory/relation_spec.rb +15 -3
- data/spec/unit/rom/memory/storage_spec.rb +1 -1
- data/spec/unit/rom/plugin_spec.rb +1 -1
- data/spec/unit/rom/plugins/relation/key_inference_spec.rb +1 -1
- data/spec/unit/rom/registry_spec.rb +86 -0
- data/spec/unit/rom/relation/attribute_reader_spec.rb +17 -0
- data/spec/unit/rom/relation/composite_spec.rb +1 -1
- data/spec/unit/rom/relation/graph_spec.rb +1 -1
- data/spec/unit/rom/relation/lazy/combine_spec.rb +1 -1
- data/spec/unit/rom/relation/lazy_spec.rb +1 -1
- data/spec/unit/rom/relation/loaded_spec.rb +1 -1
- data/spec/unit/rom/relation/schema_spec.rb +10 -6
- data/spec/unit/rom/relation/view_spec.rb +112 -0
- data/spec/unit/rom/relation_spec.rb +16 -2
- data/spec/unit/rom/schema/accessing_attributes_spec.rb +52 -0
- data/spec/unit/rom/schema/exclude_spec.rb +15 -0
- data/spec/unit/rom/schema/finalize_spec.rb +59 -0
- data/spec/unit/rom/schema/key_predicate_spec.rb +15 -0
- data/spec/unit/rom/schema/merge_spec.rb +17 -0
- data/spec/unit/rom/schema/prefix_spec.rb +16 -0
- data/spec/unit/rom/schema/project_spec.rb +15 -0
- data/spec/unit/rom/schema/rename_spec.rb +22 -0
- data/spec/unit/rom/schema/type_spec.rb +49 -0
- data/spec/unit/rom/schema/wrap_spec.rb +17 -0
- data/spec/unit/rom/schema_spec.rb +2 -2
- metadata +69 -17
- data/lib/rom/plugins/relation/view/dsl.rb +0 -32
- data/lib/rom/plugins/relation/view.rb +0 -95
- 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/
|
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 [
|
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
|
-
#
|
34
|
-
|
35
|
-
|
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
|
-
|
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,
|
65
|
+
def initialize(name, options)
|
41
66
|
@name = name
|
42
|
-
@
|
43
|
-
@
|
44
|
-
@
|
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 [
|
93
|
+
# @yield [Schema::Type]
|
50
94
|
#
|
51
95
|
# @api public
|
52
96
|
def each(&block)
|
53
|
-
attributes.
|
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
|
-
|
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.
|
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
|
231
|
+
def finalize!(gateway: nil, relations: nil, &block)
|
81
232
|
return self if frozen?
|
82
233
|
|
83
|
-
|
84
|
-
|
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 '
|
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
|
-
|
13
|
+
extend Initializer
|
14
14
|
|
15
|
-
|
15
|
+
NamespaceType = Types::Strict::Bool | Types::Strict::String
|
16
|
+
PathnameType = Types.Constructor(Pathname, &Kernel.method(:Pathname))
|
16
17
|
|
17
|
-
|
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
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
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
|
-
|
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
|
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 '
|
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 '
|
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:
|
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 '
|
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:
|
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
|
@@ -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
|
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)
|
data/lib/rom/setup/finalize.rb
CHANGED
@@ -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,
|
22
|
+
type.meta(foreign_key: true, target: relation)
|
15
23
|
end
|
16
24
|
end
|
17
25
|
end
|
data/lib/rom/version.rb
CHANGED
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
|
-
|
8
|
-
|
9
|
-
|
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 '
|
22
|
-
gem.add_runtime_dependency '
|
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.
|
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
|
40
|
-
|
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(
|
105
|
+
}.to raise_error(Dry::Types::ConstraintError)
|
126
106
|
end
|
127
107
|
end
|
128
108
|
|