rom 5.4.1 → 6.0.0.alpha1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +58 -65
- data/LICENSE +1 -1
- data/README.md +7 -6
- data/lib/rom/array_dataset.rb +46 -0
- data/lib/rom/associations/abstract.rb +217 -0
- data/lib/rom/associations/definitions/abstract.rb +150 -0
- data/lib/rom/associations/definitions/many_to_many.rb +29 -0
- data/lib/rom/associations/definitions/many_to_one.rb +14 -0
- data/lib/rom/associations/definitions/one_to_many.rb +14 -0
- data/lib/rom/associations/definitions/one_to_one.rb +14 -0
- data/lib/rom/associations/definitions/one_to_one_through.rb +14 -0
- data/lib/rom/associations/definitions.rb +7 -0
- data/lib/rom/associations/many_to_many.rb +128 -0
- data/lib/rom/associations/many_to_one.rb +65 -0
- data/lib/rom/associations/one_to_many.rb +65 -0
- data/lib/rom/associations/one_to_one.rb +13 -0
- data/lib/rom/associations/one_to_one_through.rb +13 -0
- data/lib/rom/associations/through_identifier.rb +41 -0
- data/lib/rom/attribute.rb +425 -0
- data/lib/rom/auto_curry.rb +70 -0
- data/lib/rom/cache.rb +87 -0
- data/lib/rom/changeset/associated.rb +110 -0
- data/lib/rom/changeset/create.rb +18 -0
- data/lib/rom/changeset/delete.rb +15 -0
- data/lib/rom/changeset/extensions/relation.rb +26 -0
- data/lib/rom/changeset/pipe.rb +81 -0
- data/lib/rom/changeset/pipe_registry.rb +27 -0
- data/lib/rom/changeset/stateful.rb +285 -0
- data/lib/rom/changeset/update.rb +81 -0
- data/lib/rom/changeset.rb +185 -0
- data/lib/rom/command.rb +351 -0
- data/lib/rom/command_compiler.rb +201 -0
- data/lib/rom/command_proxy.rb +36 -0
- data/lib/rom/commands/class_interface.rb +236 -0
- data/lib/rom/commands/composite.rb +55 -0
- data/lib/rom/commands/create.rb +15 -0
- data/lib/rom/commands/delete.rb +16 -0
- data/lib/rom/commands/graph/class_interface.rb +64 -0
- data/lib/rom/commands/graph/input_evaluator.rb +94 -0
- data/lib/rom/commands/graph.rb +88 -0
- data/lib/rom/commands/lazy/create.rb +35 -0
- data/lib/rom/commands/lazy/delete.rb +39 -0
- data/lib/rom/commands/lazy/update.rb +46 -0
- data/lib/rom/commands/lazy.rb +106 -0
- data/lib/rom/commands/update.rb +16 -0
- data/lib/rom/commands.rb +5 -0
- data/lib/rom/compat/auto_registration.rb +115 -0
- data/lib/rom/compat/auto_registration_strategies/base.rb +29 -0
- data/lib/rom/compat/auto_registration_strategies/custom_namespace.rb +84 -0
- data/lib/rom/compat/auto_registration_strategies/no_namespace.rb +33 -0
- data/lib/rom/compat/auto_registration_strategies/with_namespace.rb +29 -0
- data/lib/rom/compat/command.rb +74 -0
- data/lib/rom/compat/components/dsl/schema.rb +130 -0
- data/lib/rom/compat/components.rb +91 -0
- data/lib/rom/compat/global.rb +17 -0
- data/lib/rom/compat/mapper.rb +22 -0
- data/lib/rom/compat/registries.rb +47 -0
- data/lib/rom/compat/relation.rb +40 -0
- data/lib/rom/compat/schema/dsl.rb +260 -0
- data/lib/rom/compat/setting_proxy.rb +44 -0
- data/lib/rom/compat/setup.rb +151 -0
- data/lib/rom/compat/transformer.rb +49 -0
- data/lib/rom/compat.rb +22 -0
- data/lib/rom/components/association.rb +26 -0
- data/lib/rom/components/command.rb +24 -0
- data/lib/rom/components/core.rb +148 -0
- data/lib/rom/components/dataset.rb +60 -0
- data/lib/rom/components/dsl/association.rb +47 -0
- data/lib/rom/components/dsl/command.rb +60 -0
- data/lib/rom/components/dsl/core.rb +126 -0
- data/lib/rom/components/dsl/dataset.rb +33 -0
- data/lib/rom/components/dsl/gateway.rb +14 -0
- data/lib/rom/components/dsl/mapper.rb +70 -0
- data/lib/rom/components/dsl/relation.rb +49 -0
- data/lib/rom/components/dsl/schema.rb +150 -0
- data/lib/rom/components/dsl/view.rb +82 -0
- data/lib/rom/components/dsl.rb +255 -0
- data/lib/rom/components/gateway.rb +50 -0
- data/lib/rom/components/mapper.rb +29 -0
- data/lib/rom/components/provider.rb +160 -0
- data/lib/rom/components/registry.rb +154 -0
- data/lib/rom/components/relation.rb +41 -0
- data/lib/rom/components/schema.rb +61 -0
- data/lib/rom/components/view.rb +55 -0
- data/lib/rom/components.rb +55 -0
- data/lib/rom/configuration_dsl.rb +4 -0
- data/lib/rom/constants.rb +135 -0
- data/lib/rom/container.rb +182 -0
- data/lib/rom/core.rb +125 -0
- data/lib/rom/data_proxy.rb +97 -0
- data/lib/rom/enumerable_dataset.rb +70 -0
- data/lib/rom/gateway.rb +232 -0
- data/lib/rom/global.rb +56 -0
- data/lib/rom/header/attribute.rb +190 -0
- data/lib/rom/header.rb +198 -0
- data/lib/rom/inferrer.rb +55 -0
- data/lib/rom/initializer.rb +80 -0
- data/lib/rom/lint/enumerable_dataset.rb +56 -0
- data/lib/rom/lint/gateway.rb +120 -0
- data/lib/rom/lint/linter.rb +79 -0
- data/lib/rom/lint/spec.rb +22 -0
- data/lib/rom/lint/test.rb +98 -0
- data/lib/rom/loader.rb +161 -0
- data/lib/rom/mapper/attribute_dsl.rb +480 -0
- data/lib/rom/mapper/dsl.rb +107 -0
- data/lib/rom/mapper/model_dsl.rb +61 -0
- data/lib/rom/mapper.rb +99 -0
- data/lib/rom/mapper_compiler.rb +84 -0
- data/lib/rom/memory/associations/many_to_many.rb +12 -0
- data/lib/rom/memory/associations/many_to_one.rb +12 -0
- data/lib/rom/memory/associations/one_to_many.rb +12 -0
- data/lib/rom/memory/associations/one_to_one.rb +12 -0
- data/lib/rom/memory/associations.rb +6 -0
- data/lib/rom/memory/commands.rb +60 -0
- data/lib/rom/memory/dataset.rb +127 -0
- data/lib/rom/memory/gateway.rb +66 -0
- data/lib/rom/memory/mapper_compiler.rb +10 -0
- data/lib/rom/memory/relation.rb +91 -0
- data/lib/rom/memory/schema.rb +32 -0
- data/lib/rom/memory/storage.rb +61 -0
- data/lib/rom/memory/types.rb +11 -0
- data/lib/rom/memory.rb +7 -0
- data/lib/rom/model_builder.rb +103 -0
- data/lib/rom/open_struct.rb +112 -0
- data/lib/rom/pipeline.rb +111 -0
- data/lib/rom/plugin.rb +130 -0
- data/lib/rom/plugins/class_methods.rb +37 -0
- data/lib/rom/plugins/command/schema.rb +45 -0
- data/lib/rom/plugins/command/timestamps.rb +149 -0
- data/lib/rom/plugins/dsl.rb +53 -0
- data/lib/rom/plugins/relation/changeset.rb +97 -0
- data/lib/rom/plugins/relation/instrumentation.rb +66 -0
- data/lib/rom/plugins/relation/registry_reader.rb +36 -0
- data/lib/rom/plugins/schema/timestamps.rb +59 -0
- data/lib/rom/plugins.rb +100 -0
- data/lib/rom/processor/composer.rb +37 -0
- data/lib/rom/processor/transformer.rb +415 -0
- data/lib/rom/processor.rb +30 -0
- data/lib/rom/registries/associations.rb +26 -0
- data/lib/rom/registries/commands.rb +11 -0
- data/lib/rom/registries/container.rb +12 -0
- data/lib/rom/registries/datasets.rb +21 -0
- data/lib/rom/registries/gateways.rb +8 -0
- data/lib/rom/registries/mappers.rb +21 -0
- data/lib/rom/registries/nestable.rb +32 -0
- data/lib/rom/registries/relations.rb +8 -0
- data/lib/rom/registries/root.rb +203 -0
- data/lib/rom/registries/schemas.rb +44 -0
- data/lib/rom/registries/views.rb +11 -0
- data/lib/rom/relation/class_interface.rb +61 -0
- data/lib/rom/relation/combined.rb +160 -0
- data/lib/rom/relation/commands.rb +65 -0
- data/lib/rom/relation/composite.rb +53 -0
- data/lib/rom/relation/curried.rb +129 -0
- data/lib/rom/relation/graph.rb +107 -0
- data/lib/rom/relation/loaded.rb +136 -0
- data/lib/rom/relation/materializable.rb +62 -0
- data/lib/rom/relation/name.rb +122 -0
- data/lib/rom/relation/wrap.rb +64 -0
- data/lib/rom/relation.rb +625 -0
- data/lib/rom/repository/class_interface.rb +162 -0
- data/lib/rom/repository/relation_reader.rb +48 -0
- data/lib/rom/repository/root.rb +75 -0
- data/lib/rom/repository/session.rb +60 -0
- data/lib/rom/repository.rb +179 -0
- data/lib/rom/schema/associations_dsl.rb +222 -0
- data/lib/rom/schema/inferrer.rb +106 -0
- data/lib/rom/schema.rb +471 -0
- data/lib/rom/settings.rb +141 -0
- data/lib/rom/setup.rb +297 -0
- data/lib/rom/struct.rb +99 -0
- data/lib/rom/struct_compiler.rb +114 -0
- data/lib/rom/support/configurable.rb +213 -0
- data/lib/rom/support/inflector.rb +31 -0
- data/lib/rom/support/memoizable.rb +61 -0
- data/lib/rom/support/notifications.rb +238 -0
- data/lib/rom/transaction.rb +26 -0
- data/lib/rom/transformer.rb +46 -0
- data/lib/rom/types.rb +74 -0
- data/lib/rom/version.rb +1 -1
- data/lib/rom-changeset.rb +4 -0
- data/lib/rom-core.rb +3 -0
- data/lib/rom-repository.rb +4 -0
- data/lib/rom.rb +3 -3
- metadata +302 -23
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "dry/inflector"
|
4
|
+
|
5
|
+
module ROM
|
6
|
+
module InflectorMethods
|
7
|
+
# ZeitwerkCompatibility
|
8
|
+
def camelize(name, *)
|
9
|
+
super(name)
|
10
|
+
end
|
11
|
+
|
12
|
+
# Default for inferring ids from class names or any string/symbol
|
13
|
+
def component_id(value)
|
14
|
+
name = (value.is_a?(Class) ? (value.name || value.superclass.name) : value).to_s
|
15
|
+
underscore(demodulize(name)).to_sym
|
16
|
+
end
|
17
|
+
|
18
|
+
# Default for inferring namespace from class names or any string/symbol
|
19
|
+
def namespace(value)
|
20
|
+
name = (value.is_a?(Class) ? (value.name || value.superclass.name) : value).to_s
|
21
|
+
pluralize(underscore(demodulize(name))).to_sym
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
Inflector = Dry::Inflector.new do |i|
|
26
|
+
i.plural(/people\z/i, "people")
|
27
|
+
i.plural(/schema\z/i, "schemas")
|
28
|
+
end
|
29
|
+
|
30
|
+
Inflector.extend(InflectorMethods)
|
31
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ROM
|
4
|
+
# @api private
|
5
|
+
module Memoizable
|
6
|
+
MEMOIZED_HASH = {}.freeze
|
7
|
+
|
8
|
+
module ClassInterface
|
9
|
+
# @api private
|
10
|
+
def memoize(*names)
|
11
|
+
prepend(Memoizer.new(self, names))
|
12
|
+
end
|
13
|
+
|
14
|
+
def new(*)
|
15
|
+
obj = super
|
16
|
+
obj.instance_variable_set(:@__memoized__, MEMOIZED_HASH.dup)
|
17
|
+
obj
|
18
|
+
end
|
19
|
+
ruby2_keywords(:new) if respond_to?(:ruby2_keywords, true)
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.included(klass)
|
23
|
+
super
|
24
|
+
klass.extend(ClassInterface)
|
25
|
+
end
|
26
|
+
|
27
|
+
attr_reader :__memoized__
|
28
|
+
|
29
|
+
# @api private
|
30
|
+
class Memoizer < Module
|
31
|
+
attr_reader :klass
|
32
|
+
attr_reader :names
|
33
|
+
|
34
|
+
# @api private
|
35
|
+
def initialize(klass, names)
|
36
|
+
@names = names
|
37
|
+
@klass = klass
|
38
|
+
define_memoizable_names!
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
# @api private
|
44
|
+
def define_memoizable_names!
|
45
|
+
names.each do |name|
|
46
|
+
meth = klass.instance_method(name)
|
47
|
+
|
48
|
+
if meth.parameters.empty?
|
49
|
+
define_method(name) do
|
50
|
+
__memoized__[name] ||= super()
|
51
|
+
end
|
52
|
+
else
|
53
|
+
define_method(name) do |*args|
|
54
|
+
__memoized__[:"#{name}_#{args.hash}"] ||= super(*args)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,238 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "dry/core/equalizer"
|
4
|
+
|
5
|
+
require "rom/constants"
|
6
|
+
|
7
|
+
module ROM
|
8
|
+
# Notification subsystem
|
9
|
+
#
|
10
|
+
# This is an abstract event bus that implements a simple pub/sub protocol.
|
11
|
+
# The Notifications module is used in the setup process to decouple
|
12
|
+
# different modules from each other.
|
13
|
+
#
|
14
|
+
# @example
|
15
|
+
# class Setup
|
16
|
+
# extend ROM::Notifications
|
17
|
+
#
|
18
|
+
# register_event('setup.before_setup')
|
19
|
+
# register_event('setup.after_setup')
|
20
|
+
#
|
21
|
+
# def initialize
|
22
|
+
# @bus = Notifications.event_bus(:setup)
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# def setup
|
26
|
+
# @bus.trigger('setup.before_setup', at: Time.now)
|
27
|
+
# # ...
|
28
|
+
# @bus.trigger('setup.after_setup', at: Time.now)
|
29
|
+
# end
|
30
|
+
# end
|
31
|
+
#
|
32
|
+
# class Plugin
|
33
|
+
# extend ROM::Notifications::Listener
|
34
|
+
#
|
35
|
+
# subscribe('setup.after_setup') do |event|
|
36
|
+
# puts "Loaded at #{event.at.iso8601}"
|
37
|
+
# end
|
38
|
+
# end
|
39
|
+
#
|
40
|
+
module Notifications
|
41
|
+
LISTENERS_HASH = Hash.new { |h, k| h[k] = [] }
|
42
|
+
|
43
|
+
# Extension used for classes that can trigger events
|
44
|
+
#
|
45
|
+
# @api public
|
46
|
+
module Publisher
|
47
|
+
# Subscribe to events.
|
48
|
+
# If the query parameter is provided, filters events by payload.
|
49
|
+
#
|
50
|
+
# @param [String] event_id The event key
|
51
|
+
# @param [Hash] query An optional event filter
|
52
|
+
# @yield [block] The callback
|
53
|
+
# @return [Object] self
|
54
|
+
#
|
55
|
+
# @api public
|
56
|
+
def subscribe(event_id, query = EMPTY_HASH, &block)
|
57
|
+
listeners[self] << [event_id, block, query]
|
58
|
+
self
|
59
|
+
end
|
60
|
+
|
61
|
+
# Trigger an event
|
62
|
+
#
|
63
|
+
# @param [String] event_id The event key
|
64
|
+
# @param [Hash] payload An optional payload
|
65
|
+
#
|
66
|
+
# @api public
|
67
|
+
def trigger(event_id, payload = EMPTY_HASH)
|
68
|
+
event = events[event_id]
|
69
|
+
|
70
|
+
event_listeners = listeners.values.flatten(1).group_by(&:first)
|
71
|
+
|
72
|
+
return unless event_listeners.key?(event_id)
|
73
|
+
|
74
|
+
event_listeners[event_id].each do |(_, listener, query)|
|
75
|
+
event.payload(payload).trigger(listener, query)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# Event object
|
81
|
+
#
|
82
|
+
# @api public
|
83
|
+
class Event
|
84
|
+
include Dry::Equalizer(:id, :payload)
|
85
|
+
|
86
|
+
# @!attribute [r] id
|
87
|
+
# @return [Symbol] The event identifier
|
88
|
+
attr_reader :id
|
89
|
+
|
90
|
+
# Initialize a new event
|
91
|
+
#
|
92
|
+
# @param [Symbol] id The event identifier
|
93
|
+
# @param [Hash] payload Optional payload
|
94
|
+
#
|
95
|
+
# @return [Event]
|
96
|
+
#
|
97
|
+
# @api private
|
98
|
+
def initialize(id, payload = EMPTY_HASH)
|
99
|
+
@id = id
|
100
|
+
@payload = payload
|
101
|
+
end
|
102
|
+
|
103
|
+
# Get data from the payload
|
104
|
+
#
|
105
|
+
# @param [String,Symbol] name
|
106
|
+
#
|
107
|
+
# @api public
|
108
|
+
def [](name)
|
109
|
+
@payload.fetch(name)
|
110
|
+
end
|
111
|
+
|
112
|
+
# Coerce an event to a hash
|
113
|
+
#
|
114
|
+
# @return [Hash]
|
115
|
+
#
|
116
|
+
# @api public
|
117
|
+
def to_h
|
118
|
+
@payload
|
119
|
+
end
|
120
|
+
alias_method :to_hash, :to_h
|
121
|
+
|
122
|
+
# Get or set a payload
|
123
|
+
#
|
124
|
+
# @overload
|
125
|
+
# @return [Hash] payload
|
126
|
+
#
|
127
|
+
# @overload payload(data)
|
128
|
+
# @param [Hash] data A new payload
|
129
|
+
# @return [Event] A copy of the event with the provided payload
|
130
|
+
#
|
131
|
+
# @api public
|
132
|
+
def payload(data = nil)
|
133
|
+
if data
|
134
|
+
self.class.new(id, @payload.merge(data))
|
135
|
+
else
|
136
|
+
@payload
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
# Trigger the event
|
141
|
+
#
|
142
|
+
# @param [#call] listener
|
143
|
+
# @param [Hash] query
|
144
|
+
#
|
145
|
+
# @api private
|
146
|
+
def trigger(listener, query = EMPTY_HASH)
|
147
|
+
listener.(self) if trigger?(query)
|
148
|
+
end
|
149
|
+
|
150
|
+
# @api private
|
151
|
+
def trigger?(query)
|
152
|
+
query.empty? || query.all? { |key, value| @payload[key] == value }
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
extend Publisher
|
157
|
+
|
158
|
+
# Register an event
|
159
|
+
#
|
160
|
+
# @param [String] id A unique event key
|
161
|
+
# @param [Hash] info
|
162
|
+
#
|
163
|
+
# @api public
|
164
|
+
def register_event(id, info = EMPTY_HASH)
|
165
|
+
Notifications.events[id] = Event.new(id, info)
|
166
|
+
end
|
167
|
+
|
168
|
+
# @api private
|
169
|
+
def self.events
|
170
|
+
@__events__ ||= {}
|
171
|
+
end
|
172
|
+
|
173
|
+
# @api private
|
174
|
+
def self.listeners
|
175
|
+
@__listeners__ ||= LISTENERS_HASH.dup
|
176
|
+
end
|
177
|
+
|
178
|
+
# Build an event bus
|
179
|
+
#
|
180
|
+
# @param [Symbol] id Bus key
|
181
|
+
# @return [Notifications::EventBus] A new bus
|
182
|
+
#
|
183
|
+
# @api public
|
184
|
+
def self.event_bus(id)
|
185
|
+
EventBus.new(id, events: events.dup)
|
186
|
+
end
|
187
|
+
|
188
|
+
# Extension for objects that can listen to events
|
189
|
+
#
|
190
|
+
# @api public
|
191
|
+
module Listener
|
192
|
+
# Subscribe to events
|
193
|
+
#
|
194
|
+
# @param [String] event_id The event key
|
195
|
+
# @param [Hash] query An optional event filter
|
196
|
+
# @return [Object] self
|
197
|
+
#
|
198
|
+
# @api public
|
199
|
+
def subscribe(event_id, query = EMPTY_HASH, &block)
|
200
|
+
Notifications.listeners[self] << [event_id, block, query]
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
# Event bus
|
205
|
+
#
|
206
|
+
# An event bus stores listeners (callbacks) and events
|
207
|
+
#
|
208
|
+
# @api public
|
209
|
+
class EventBus
|
210
|
+
include Publisher
|
211
|
+
|
212
|
+
# @!attribute [r] id
|
213
|
+
# @return [Symbol] The bus identifier
|
214
|
+
attr_reader :id
|
215
|
+
|
216
|
+
# @!attribute [r] events
|
217
|
+
# @return [Hash] A hash with events registered within a bus
|
218
|
+
attr_reader :events
|
219
|
+
|
220
|
+
# @!attribute [r] listeners
|
221
|
+
# @return [Hash] A hash with event listeners registered within a bus
|
222
|
+
attr_reader :listeners
|
223
|
+
|
224
|
+
# Initialize a new event bus
|
225
|
+
#
|
226
|
+
# @param [Symbol] id The bus identifier
|
227
|
+
# @param [Hash] events A hash with events
|
228
|
+
# @param [Hash] listeners A hash with listeners
|
229
|
+
#
|
230
|
+
# @api public
|
231
|
+
def initialize(id, events: EMPTY_HASH)
|
232
|
+
@id = id
|
233
|
+
@listeners = LISTENERS_HASH.dup
|
234
|
+
@events = events
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ROM
|
4
|
+
# @api private
|
5
|
+
class Transaction
|
6
|
+
# @api private
|
7
|
+
Rollback = Class.new(StandardError)
|
8
|
+
|
9
|
+
# @api private
|
10
|
+
def run(**)
|
11
|
+
yield(self)
|
12
|
+
rescue Rollback
|
13
|
+
# noop
|
14
|
+
end
|
15
|
+
|
16
|
+
# Unconditionally roll back the current transaction
|
17
|
+
#
|
18
|
+
# @api public
|
19
|
+
def rollback!
|
20
|
+
raise Rollback
|
21
|
+
end
|
22
|
+
|
23
|
+
# @api private
|
24
|
+
NoOp = Transaction.new.freeze
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "dry/transformer"
|
4
|
+
|
5
|
+
require "rom/plugins/class_methods"
|
6
|
+
|
7
|
+
require_relative "components/provider"
|
8
|
+
require_relative "processor/transformer"
|
9
|
+
|
10
|
+
module ROM
|
11
|
+
# Transformer is a data mapper which uses `Dry::Transformer`'s DSL to define transformations.
|
12
|
+
#
|
13
|
+
# @api public
|
14
|
+
class Transformer < Dry::Transformer[Processor::Transformer::Functions]
|
15
|
+
extend ROM::Provider(type: :mapper)
|
16
|
+
extend Plugins::ClassMethods
|
17
|
+
|
18
|
+
# Define transformation pipeline
|
19
|
+
#
|
20
|
+
# @example
|
21
|
+
# class UsersMapper < ROM::Transformer
|
22
|
+
# map do
|
23
|
+
# rename_keys user_id: :id
|
24
|
+
# deep_stringify_keys
|
25
|
+
# end
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# @return [self]
|
29
|
+
#
|
30
|
+
# @api public
|
31
|
+
def self.map(&block)
|
32
|
+
define! do
|
33
|
+
map_array(&block)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# Build a mapper instance
|
38
|
+
#
|
39
|
+
# @return [Transformer]
|
40
|
+
#
|
41
|
+
# @api public
|
42
|
+
def self.build
|
43
|
+
new
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/lib/rom/types.rb
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "dry-types"
|
4
|
+
require "json"
|
5
|
+
|
6
|
+
module ROM
|
7
|
+
# Default namespace with built-in attribute types
|
8
|
+
#
|
9
|
+
# @api public
|
10
|
+
#
|
11
|
+
module Types
|
12
|
+
include Dry::Types(default: :nominal)
|
13
|
+
|
14
|
+
# @api private
|
15
|
+
def self.included(other)
|
16
|
+
other.extend(Methods)
|
17
|
+
super
|
18
|
+
end
|
19
|
+
|
20
|
+
# Type extensions
|
21
|
+
#
|
22
|
+
# @api public
|
23
|
+
module Methods
|
24
|
+
# Shortcut for defining a foreign key attribute type
|
25
|
+
#
|
26
|
+
# @param [Symbol] relation The name of the target relation
|
27
|
+
# @param [Object] type The type of an attribute
|
28
|
+
#
|
29
|
+
# @return [Dry::Types::Nominal]
|
30
|
+
#
|
31
|
+
# @api public
|
32
|
+
def ForeignKey(relation, type = Types::Integer)
|
33
|
+
type.meta(foreign_key: true, target: relation)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# @!parse module Coercible;end
|
38
|
+
|
39
|
+
# Define a json-to-hash attribute type
|
40
|
+
#
|
41
|
+
# @return [Dry::Types::Constructor]
|
42
|
+
#
|
43
|
+
# @api public
|
44
|
+
def Coercible.JSONHash(symbol_keys: false, type: Types::Hash)
|
45
|
+
Types.Constructor(type) do |value|
|
46
|
+
::JSON.parse(value.to_s, symbolize_names: symbol_keys)
|
47
|
+
rescue ::JSON::ParserError
|
48
|
+
value
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# Define a hash-to-json attribute type
|
53
|
+
#
|
54
|
+
# @return [Dry::Types::Constructor]
|
55
|
+
#
|
56
|
+
# @api public
|
57
|
+
def Coercible.HashJSON(type: Types::String)
|
58
|
+
Types.Constructor(type) { |value| ::JSON.dump(value) }
|
59
|
+
end
|
60
|
+
|
61
|
+
# Define a json type with json-to-hash read type
|
62
|
+
#
|
63
|
+
# @return [Dry::Types::Constructor]
|
64
|
+
#
|
65
|
+
# @api public
|
66
|
+
def Coercible.JSON(symbol_keys: false)
|
67
|
+
self.HashJSON.meta(read: self.JSONHash(symbol_keys: symbol_keys))
|
68
|
+
end
|
69
|
+
|
70
|
+
Coercible::JSON = Coercible.JSON
|
71
|
+
Coercible::JSONHash = Coercible.JSONHash
|
72
|
+
Coercible::HashJSON = Coercible.HashJSON
|
73
|
+
end
|
74
|
+
end
|
data/lib/rom/version.rb
CHANGED
data/lib/rom-core.rb
ADDED
data/lib/rom.rb
CHANGED