rom 2.0.2 → 4.2.1
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 +5 -5
- data/CHANGELOG.md +35 -430
- data/LICENSE +1 -1
- data/README.md +83 -11
- data/lib/rom/version.rb +1 -1
- data/lib/rom.rb +3 -46
- metadata +30 -236
- data/.gitignore +0 -24
- data/.rspec +0 -3
- data/.rubocop.yml +0 -87
- data/.rubocop_todo.yml +0 -46
- data/.travis.yml +0 -28
- data/CODE_OF_CONDUCT.md +0 -13
- data/CONTRIBUTING.md +0 -1
- data/Gemfile +0 -41
- data/Guardfile +0 -24
- data/Rakefile +0 -22
- data/lib/rom/association_set.rb +0 -26
- data/lib/rom/command.rb +0 -173
- data/lib/rom/command_registry.rb +0 -153
- data/lib/rom/commands/class_interface.rb +0 -148
- data/lib/rom/commands/composite.rb +0 -54
- data/lib/rom/commands/create.rb +0 -13
- data/lib/rom/commands/delete.rb +0 -14
- data/lib/rom/commands/graph/builder.rb +0 -176
- data/lib/rom/commands/graph/class_interface.rb +0 -62
- data/lib/rom/commands/graph/input_evaluator.rb +0 -62
- data/lib/rom/commands/graph.rb +0 -103
- data/lib/rom/commands/lazy/create.rb +0 -23
- data/lib/rom/commands/lazy/delete.rb +0 -27
- data/lib/rom/commands/lazy/update.rb +0 -34
- data/lib/rom/commands/lazy.rb +0 -99
- data/lib/rom/commands/result.rb +0 -96
- data/lib/rom/commands/update.rb +0 -14
- data/lib/rom/commands.rb +0 -3
- data/lib/rom/configuration.rb +0 -88
- data/lib/rom/configuration_dsl/command.rb +0 -43
- data/lib/rom/configuration_dsl/command_dsl.rb +0 -35
- data/lib/rom/configuration_dsl/mapper.rb +0 -37
- data/lib/rom/configuration_dsl/mapper_dsl.rb +0 -44
- data/lib/rom/configuration_dsl/relation.rb +0 -26
- data/lib/rom/configuration_dsl.rb +0 -78
- data/lib/rom/configuration_plugin.rb +0 -17
- data/lib/rom/constants.rb +0 -30
- data/lib/rom/container.rb +0 -231
- data/lib/rom/create_container.rb +0 -61
- data/lib/rom/environment.rb +0 -70
- data/lib/rom/gateway.rb +0 -154
- data/lib/rom/global/plugin_dsl.rb +0 -49
- data/lib/rom/global.rb +0 -60
- data/lib/rom/lint/enumerable_dataset.rb +0 -54
- data/lib/rom/lint/gateway.rb +0 -94
- data/lib/rom/lint/linter.rb +0 -78
- data/lib/rom/lint/spec.rb +0 -20
- data/lib/rom/lint/test.rb +0 -98
- data/lib/rom/mapper_registry.rb +0 -35
- data/lib/rom/memory/commands.rb +0 -58
- data/lib/rom/memory/dataset.rb +0 -98
- data/lib/rom/memory/gateway.rb +0 -64
- data/lib/rom/memory/relation.rb +0 -49
- data/lib/rom/memory/storage.rb +0 -59
- data/lib/rom/memory/types.rb +0 -9
- data/lib/rom/memory.rb +0 -4
- data/lib/rom/pipeline.rb +0 -106
- data/lib/rom/plugin.rb +0 -17
- data/lib/rom/plugin_base.rb +0 -31
- data/lib/rom/plugin_registry.rb +0 -173
- data/lib/rom/plugins/command/schema.rb +0 -37
- data/lib/rom/plugins/configuration/configuration_dsl.rb +0 -17
- data/lib/rom/plugins/relation/key_inference.rb +0 -46
- data/lib/rom/plugins/relation/registry_reader.rb +0 -32
- data/lib/rom/plugins/relation/view/dsl.rb +0 -32
- data/lib/rom/plugins/relation/view.rb +0 -95
- data/lib/rom/relation/class_interface.rb +0 -230
- data/lib/rom/relation/composite.rb +0 -46
- data/lib/rom/relation/curried.rb +0 -104
- data/lib/rom/relation/graph.rb +0 -115
- data/lib/rom/relation/loaded.rb +0 -118
- data/lib/rom/relation/materializable.rb +0 -66
- data/lib/rom/relation/name.rb +0 -102
- data/lib/rom/relation.rb +0 -172
- data/lib/rom/relation_registry.rb +0 -9
- data/lib/rom/schema/dsl.rb +0 -58
- data/lib/rom/schema.rb +0 -89
- data/lib/rom/setup/auto_registration.rb +0 -69
- data/lib/rom/setup/auto_registration_strategies/base.rb +0 -11
- data/lib/rom/setup/auto_registration_strategies/custom_namespace.rb +0 -22
- data/lib/rom/setup/auto_registration_strategies/no_namespace.rb +0 -19
- data/lib/rom/setup/auto_registration_strategies/with_namespace.rb +0 -18
- data/lib/rom/setup/finalize/finalize_commands.rb +0 -47
- data/lib/rom/setup/finalize/finalize_mappers.rb +0 -36
- data/lib/rom/setup/finalize/finalize_relations.rb +0 -60
- data/lib/rom/setup/finalize.rb +0 -146
- data/lib/rom/setup.rb +0 -55
- data/lib/rom/support/configurable.rb +0 -80
- data/lib/rom/types.rb +0 -18
- data/log/.gitkeep +0 -0
- data/rakelib/benchmark.rake +0 -15
- data/rakelib/mutant.rake +0 -19
- data/rakelib/rubocop.rake +0 -18
- data/rom.gemspec +0 -26
- data/spec/fixtures/app/commands/create_user.rb +0 -2
- data/spec/fixtures/app/mappers/user_list.rb +0 -2
- data/spec/fixtures/app/my_commands/create_user.rb +0 -2
- data/spec/fixtures/app/my_mappers/user_list.rb +0 -2
- data/spec/fixtures/app/my_relations/users.rb +0 -2
- data/spec/fixtures/app/relations/users.rb +0 -2
- data/spec/fixtures/custom/commands/create_user.rb +0 -6
- data/spec/fixtures/custom/mappers/user_list.rb +0 -6
- data/spec/fixtures/custom/relations/users.rb +0 -6
- data/spec/fixtures/lib/persistence/commands/create_user.rb +0 -6
- data/spec/fixtures/lib/persistence/mappers/user_list.rb +0 -6
- data/spec/fixtures/lib/persistence/my_commands/create_user.rb +0 -6
- data/spec/fixtures/lib/persistence/my_mappers/user_list.rb +0 -6
- data/spec/fixtures/lib/persistence/my_relations/users.rb +0 -6
- data/spec/fixtures/lib/persistence/relations/users.rb +0 -6
- data/spec/integration/command_registry_spec.rb +0 -60
- data/spec/integration/commands/create_spec.rb +0 -177
- data/spec/integration/commands/delete_spec.rb +0 -67
- data/spec/integration/commands/error_handling_spec.rb +0 -25
- data/spec/integration/commands/graph_builder_spec.rb +0 -213
- data/spec/integration/commands/graph_spec.rb +0 -288
- data/spec/integration/commands/update_spec.rb +0 -109
- data/spec/integration/commands_spec.rb +0 -67
- data/spec/integration/mappers/combine_spec.rb +0 -117
- data/spec/integration/mappers/deep_embedded_spec.rb +0 -44
- data/spec/integration/mappers/definition_dsl_spec.rb +0 -206
- data/spec/integration/mappers/embedded_spec.rb +0 -62
- data/spec/integration/mappers/exclude_spec.rb +0 -27
- data/spec/integration/mappers/fold_spec.rb +0 -71
- data/spec/integration/mappers/group_spec.rb +0 -163
- data/spec/integration/mappers/overwrite_attributes_value_spec.rb +0 -51
- data/spec/integration/mappers/prefix_separator_spec.rb +0 -52
- data/spec/integration/mappers/prefix_spec.rb +0 -48
- data/spec/integration/mappers/prefixing_attributes_spec.rb +0 -37
- data/spec/integration/mappers/registering_custom_mappers_spec.rb +0 -28
- data/spec/integration/mappers/renaming_attributes_spec.rb +0 -125
- data/spec/integration/mappers/reusing_mappers_spec.rb +0 -43
- data/spec/integration/mappers/step_spec.rb +0 -119
- data/spec/integration/mappers/symbolizing_attributes_spec.rb +0 -77
- data/spec/integration/mappers/unfold_spec.rb +0 -92
- data/spec/integration/mappers/ungroup_spec.rb +0 -126
- data/spec/integration/mappers/unwrap_spec.rb +0 -93
- data/spec/integration/mappers/wrap_spec.rb +0 -155
- data/spec/integration/memory/commands/create_spec.rb +0 -23
- data/spec/integration/memory/commands/delete_spec.rb +0 -23
- data/spec/integration/memory/commands/update_spec.rb +0 -23
- data/spec/integration/multi_env_spec.rb +0 -69
- data/spec/integration/multi_repo_spec.rb +0 -46
- data/spec/integration/relations/default_dataset_spec.rb +0 -38
- data/spec/integration/relations/inheritance_spec.rb +0 -37
- data/spec/integration/relations/reading_spec.rb +0 -169
- data/spec/integration/relations/registry_dsl_spec.rb +0 -45
- data/spec/integration/repositories/extending_relations_spec.rb +0 -58
- data/spec/integration/repositories/setting_logger_spec.rb +0 -34
- data/spec/integration/setup_spec.rb +0 -160
- data/spec/shared/command_behavior.rb +0 -28
- data/spec/shared/command_graph.rb +0 -50
- data/spec/shared/container.rb +0 -9
- data/spec/shared/enumerable_dataset.rb +0 -52
- data/spec/shared/gateway_only.rb +0 -6
- data/spec/shared/materializable.rb +0 -36
- data/spec/shared/no_container.rb +0 -16
- data/spec/shared/one_behavior.rb +0 -26
- data/spec/shared/proxy.rb +0 -0
- data/spec/shared/users_and_tasks.rb +0 -10
- data/spec/spec_helper.rb +0 -52
- data/spec/support/constant_leak_finder.rb +0 -14
- data/spec/support/mutant.rb +0 -10
- data/spec/support/types.rb +0 -5
- data/spec/test/memory_repository_lint_test.rb +0 -27
- data/spec/unit/rom/association_set_spec.rb +0 -23
- data/spec/unit/rom/commands/graph_spec.rb +0 -191
- data/spec/unit/rom/commands/lazy_spec.rb +0 -307
- data/spec/unit/rom/commands/result_spec.rb +0 -70
- data/spec/unit/rom/commands_spec.rb +0 -165
- data/spec/unit/rom/configurable_spec.rb +0 -49
- data/spec/unit/rom/configuration_spec.rb +0 -61
- data/spec/unit/rom/container_spec.rb +0 -99
- data/spec/unit/rom/create_container_spec.rb +0 -151
- data/spec/unit/rom/environment_spec.rb +0 -123
- data/spec/unit/rom/gateway_spec.rb +0 -146
- data/spec/unit/rom/mapper_registry_spec.rb +0 -25
- data/spec/unit/rom/memory/commands_spec.rb +0 -43
- data/spec/unit/rom/memory/dataset_spec.rb +0 -31
- data/spec/unit/rom/memory/relation_spec.rb +0 -109
- data/spec/unit/rom/memory/repository_spec.rb +0 -12
- data/spec/unit/rom/memory/storage_spec.rb +0 -45
- data/spec/unit/rom/plugin_spec.rb +0 -150
- data/spec/unit/rom/plugins/command/schema_spec.rb +0 -66
- data/spec/unit/rom/plugins/relation/key_inference_spec.rb +0 -85
- data/spec/unit/rom/plugins/relation/view_spec.rb +0 -51
- data/spec/unit/rom/relation/composite_spec.rb +0 -89
- data/spec/unit/rom/relation/curried_spec.rb +0 -52
- data/spec/unit/rom/relation/graph_spec.rb +0 -92
- data/spec/unit/rom/relation/lazy/combine_spec.rb +0 -165
- data/spec/unit/rom/relation/lazy_spec.rb +0 -214
- data/spec/unit/rom/relation/loaded_spec.rb +0 -53
- data/spec/unit/rom/relation/name_spec.rb +0 -58
- data/spec/unit/rom/relation/schema_spec.rb +0 -117
- data/spec/unit/rom/relation_spec.rb +0 -237
- data/spec/unit/rom/schema_spec.rb +0 -10
- data/spec/unit/rom/setup/auto_registration_spec.rb +0 -152
|
@@ -1,230 +0,0 @@
|
|
|
1
|
-
require 'set'
|
|
2
|
-
|
|
3
|
-
require 'rom/support/auto_curry'
|
|
4
|
-
require 'rom/relation/curried'
|
|
5
|
-
require 'rom/relation/name'
|
|
6
|
-
require 'rom/schema'
|
|
7
|
-
|
|
8
|
-
module ROM
|
|
9
|
-
class Relation
|
|
10
|
-
module ClassInterface
|
|
11
|
-
# Register adapter relation subclasses during setup phase
|
|
12
|
-
#
|
|
13
|
-
# In adition those subclasses are extended with an interface for accessing
|
|
14
|
-
# relation registry and to define `register_as` setting
|
|
15
|
-
#
|
|
16
|
-
# @api private
|
|
17
|
-
def inherited(klass)
|
|
18
|
-
super
|
|
19
|
-
|
|
20
|
-
klass.extend ClassMacros
|
|
21
|
-
klass.defines :adapter
|
|
22
|
-
|
|
23
|
-
if respond_to?(:adapter) && adapter.nil?
|
|
24
|
-
raise MissingAdapterIdentifierError,
|
|
25
|
-
"relation class +#{self}+ is missing the adapter identifier"
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
# Extend with functionality required by adapters *only* if this is a direct
|
|
29
|
-
# descendant of an adapter-specific relation subclass
|
|
30
|
-
return unless respond_to?(:adapter) && klass.superclass == ROM::Relation[adapter]
|
|
31
|
-
|
|
32
|
-
klass.class_eval do
|
|
33
|
-
use :registry_reader
|
|
34
|
-
|
|
35
|
-
defines :gateway, :dataset, :dataset_proc, :register_as, :schema_dsl, :schema_inferrer
|
|
36
|
-
|
|
37
|
-
gateway :default
|
|
38
|
-
schema_dsl Schema::DSL
|
|
39
|
-
schema_inferrer nil
|
|
40
|
-
|
|
41
|
-
dataset default_name
|
|
42
|
-
|
|
43
|
-
# Relation's dataset name
|
|
44
|
-
#
|
|
45
|
-
# In example a table name in an SQL database
|
|
46
|
-
#
|
|
47
|
-
# @return [Symbol]
|
|
48
|
-
#
|
|
49
|
-
# @api public
|
|
50
|
-
attr_reader :name
|
|
51
|
-
|
|
52
|
-
# Set dataset name
|
|
53
|
-
#
|
|
54
|
-
# If a block is passed it will be evaluated in the context of the dataset
|
|
55
|
-
# to define the default dataset which will be injected into a relation
|
|
56
|
-
# when setting up relation registry
|
|
57
|
-
#
|
|
58
|
-
# @example
|
|
59
|
-
# class Relations::Users < ROM::Relation[:memory]
|
|
60
|
-
# dataset :users
|
|
61
|
-
# end
|
|
62
|
-
#
|
|
63
|
-
# class Users < ROM::Relation[:memory]
|
|
64
|
-
# dataset { sort_by(:id) }
|
|
65
|
-
# end
|
|
66
|
-
#
|
|
67
|
-
# @param [Symbol] value The name of the dataset
|
|
68
|
-
#
|
|
69
|
-
# @api public
|
|
70
|
-
def self.dataset(value = Undefined, &block)
|
|
71
|
-
dataset_proc(block) if block
|
|
72
|
-
super
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
# Set or get name under which a relation will be registered
|
|
76
|
-
#
|
|
77
|
-
# This defaults to `dataset` or `default_name` for descendant relations
|
|
78
|
-
#
|
|
79
|
-
# @return [Symbol]
|
|
80
|
-
#
|
|
81
|
-
# @api public
|
|
82
|
-
def self.register_as(value = Undefined)
|
|
83
|
-
if value == Undefined
|
|
84
|
-
return @register_as if defined?(@register_as)
|
|
85
|
-
|
|
86
|
-
super_val = super()
|
|
87
|
-
|
|
88
|
-
if superclass == ROM::Relation[adapter]
|
|
89
|
-
super_val || dataset
|
|
90
|
-
else
|
|
91
|
-
super_val == dataset ? default_name : super_val
|
|
92
|
-
end
|
|
93
|
-
else
|
|
94
|
-
super
|
|
95
|
-
end
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
# @api private
|
|
99
|
-
def initialize(dataset, options = EMPTY_HASH)
|
|
100
|
-
@name = Name.new(self.class.register_as, self.class.dataset)
|
|
101
|
-
super
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
# Return name of the source gateway of this relation
|
|
105
|
-
#
|
|
106
|
-
# @return [Symbol]
|
|
107
|
-
#
|
|
108
|
-
# @api private
|
|
109
|
-
def gateway
|
|
110
|
-
self.class.gateway
|
|
111
|
-
end
|
|
112
|
-
end
|
|
113
|
-
|
|
114
|
-
klass.extend(AutoCurry)
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
# Return adapter-specific relation subclass
|
|
118
|
-
#
|
|
119
|
-
# @example
|
|
120
|
-
# ROM::Relation[:memory]
|
|
121
|
-
# # => ROM::Memory::Relation
|
|
122
|
-
#
|
|
123
|
-
# @return [Class]
|
|
124
|
-
#
|
|
125
|
-
# @api public
|
|
126
|
-
def [](adapter)
|
|
127
|
-
ROM.adapters.fetch(adapter).const_get(:Relation)
|
|
128
|
-
rescue KeyError
|
|
129
|
-
raise AdapterNotPresentError.new(adapter, :relation)
|
|
130
|
-
end
|
|
131
|
-
|
|
132
|
-
# Specify canonical schema for a relation
|
|
133
|
-
#
|
|
134
|
-
# With a schema defined commands will set up a type-safe input handler
|
|
135
|
-
# automatically
|
|
136
|
-
#
|
|
137
|
-
# @example
|
|
138
|
-
# class Users < ROM::Relation[:sql]
|
|
139
|
-
# schema do
|
|
140
|
-
# attribute :id, Types::Serial
|
|
141
|
-
# attribute :name, Types::String
|
|
142
|
-
# end
|
|
143
|
-
# end
|
|
144
|
-
#
|
|
145
|
-
# # access schema
|
|
146
|
-
# Users.schema
|
|
147
|
-
#
|
|
148
|
-
# @return [Schema]
|
|
149
|
-
#
|
|
150
|
-
# @param [Symbol] dataset An optional dataset name
|
|
151
|
-
# @param [Boolean] infer Whether to do an automatic schema inferring
|
|
152
|
-
#
|
|
153
|
-
# @api public
|
|
154
|
-
def schema(dataset = nil, infer: false, &block)
|
|
155
|
-
if defined?(@schema)
|
|
156
|
-
@schema
|
|
157
|
-
elsif block || infer
|
|
158
|
-
self.dataset(dataset) if dataset
|
|
159
|
-
self.register_as(self.dataset) unless register_as
|
|
160
|
-
|
|
161
|
-
name = Name[register_as, self.dataset]
|
|
162
|
-
inferrer = infer ? schema_inferrer : nil
|
|
163
|
-
dsl = schema_dsl.new(name, inferrer, &block)
|
|
164
|
-
|
|
165
|
-
@schema = dsl.call
|
|
166
|
-
end
|
|
167
|
-
end
|
|
168
|
-
|
|
169
|
-
# Dynamically define a method that will forward to the dataset and wrap
|
|
170
|
-
# response in the relation itself
|
|
171
|
-
#
|
|
172
|
-
# @example
|
|
173
|
-
# class SomeAdapterRelation < ROM::Relation
|
|
174
|
-
# forward :super_query
|
|
175
|
-
# end
|
|
176
|
-
#
|
|
177
|
-
# @api public
|
|
178
|
-
def forward(*methods)
|
|
179
|
-
methods.each do |method|
|
|
180
|
-
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
|
181
|
-
def #{method}(*args, &block)
|
|
182
|
-
__new__(dataset.__send__(:#{method}, *args, &block))
|
|
183
|
-
end
|
|
184
|
-
RUBY
|
|
185
|
-
end
|
|
186
|
-
end
|
|
187
|
-
|
|
188
|
-
# Include a registered plugin in this relation class
|
|
189
|
-
#
|
|
190
|
-
# @param [Symbol] plugin
|
|
191
|
-
# @param [Hash] options
|
|
192
|
-
# @option options [Symbol] :adapter (:default) first adapter to check for plugin
|
|
193
|
-
#
|
|
194
|
-
# @api public
|
|
195
|
-
def use(plugin, _options = EMPTY_HASH)
|
|
196
|
-
ROM.plugin_registry.relations.fetch(plugin, adapter).apply_to(self)
|
|
197
|
-
end
|
|
198
|
-
|
|
199
|
-
# Return default relation name used for `register_as` setting
|
|
200
|
-
#
|
|
201
|
-
# @return [Symbol]
|
|
202
|
-
#
|
|
203
|
-
# @api private
|
|
204
|
-
def default_name
|
|
205
|
-
return unless name
|
|
206
|
-
Inflector.underscore(name).tr('/', '_').to_sym
|
|
207
|
-
end
|
|
208
|
-
|
|
209
|
-
# @api private
|
|
210
|
-
def curried
|
|
211
|
-
Curried
|
|
212
|
-
end
|
|
213
|
-
|
|
214
|
-
# @api private
|
|
215
|
-
def view_methods
|
|
216
|
-
ancestor_methods = ancestors.reject { |klass| klass == self }
|
|
217
|
-
.map(&:instance_methods).flatten
|
|
218
|
-
|
|
219
|
-
instance_methods - ancestor_methods + auto_curried_methods
|
|
220
|
-
end
|
|
221
|
-
|
|
222
|
-
# Hook to finalize a relation after its instance was created
|
|
223
|
-
#
|
|
224
|
-
# @api private
|
|
225
|
-
def finalize(_container, _relation)
|
|
226
|
-
# noop
|
|
227
|
-
end
|
|
228
|
-
end
|
|
229
|
-
end
|
|
230
|
-
end
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
require 'rom/relation/loaded'
|
|
2
|
-
require 'rom/relation/materializable'
|
|
3
|
-
require 'rom/pipeline'
|
|
4
|
-
|
|
5
|
-
module ROM
|
|
6
|
-
class Relation
|
|
7
|
-
# Left-to-right relation composition used for data-pipelining
|
|
8
|
-
#
|
|
9
|
-
# @api public
|
|
10
|
-
class Composite < Pipeline::Composite
|
|
11
|
-
include Materializable
|
|
12
|
-
|
|
13
|
-
# Call the pipeline by passing results from left to right
|
|
14
|
-
#
|
|
15
|
-
# Optional args are passed to the left object
|
|
16
|
-
#
|
|
17
|
-
# @return [Loaded]
|
|
18
|
-
#
|
|
19
|
-
# @api public
|
|
20
|
-
def call(*args)
|
|
21
|
-
relation = left.call(*args)
|
|
22
|
-
response = right.call(relation)
|
|
23
|
-
|
|
24
|
-
if response.is_a?(Loaded)
|
|
25
|
-
response
|
|
26
|
-
elsif relation.is_a?(Loaded)
|
|
27
|
-
relation.new(response)
|
|
28
|
-
else
|
|
29
|
-
Loaded.new(relation, response)
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
alias_method :[], :call
|
|
33
|
-
|
|
34
|
-
private
|
|
35
|
-
|
|
36
|
-
# @api private
|
|
37
|
-
#
|
|
38
|
-
# @see Pipeline::Proxy#decorate?
|
|
39
|
-
#
|
|
40
|
-
# @api private
|
|
41
|
-
def decorate?(response)
|
|
42
|
-
super || response.is_a?(Graph)
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
end
|
data/lib/rom/relation/curried.rb
DELETED
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
require 'rom/support/options'
|
|
2
|
-
|
|
3
|
-
require 'rom/pipeline'
|
|
4
|
-
require 'rom/relation/name'
|
|
5
|
-
require 'rom/relation/materializable'
|
|
6
|
-
|
|
7
|
-
module ROM
|
|
8
|
-
class Relation
|
|
9
|
-
class Curried
|
|
10
|
-
include Options
|
|
11
|
-
include Materializable
|
|
12
|
-
include Pipeline
|
|
13
|
-
|
|
14
|
-
option :name, type: Symbol
|
|
15
|
-
option :arity, type: Integer, reader: true, default: -1
|
|
16
|
-
option :curry_args, type: Array, reader: true, default: EMPTY_ARRAY
|
|
17
|
-
|
|
18
|
-
attr_reader :relation
|
|
19
|
-
|
|
20
|
-
attr_reader :name
|
|
21
|
-
|
|
22
|
-
# @api private
|
|
23
|
-
def initialize(relation, options = EMPTY_HASH)
|
|
24
|
-
@relation = relation
|
|
25
|
-
@name = relation.name.with(options[:name])
|
|
26
|
-
super
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
# Load relation if args match the arity
|
|
30
|
-
#
|
|
31
|
-
# @return [Loaded,Lazy,Curried]
|
|
32
|
-
# @see Lazy#call
|
|
33
|
-
#
|
|
34
|
-
# @api public
|
|
35
|
-
def call(*args)
|
|
36
|
-
if arity != -1
|
|
37
|
-
all_args = curry_args + args
|
|
38
|
-
|
|
39
|
-
if arity == all_args.size
|
|
40
|
-
Loaded.new(relation.__send__(name.relation, *all_args))
|
|
41
|
-
else
|
|
42
|
-
__new__(relation, curry_args: all_args)
|
|
43
|
-
end
|
|
44
|
-
else
|
|
45
|
-
super
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
alias_method :[], :call
|
|
49
|
-
|
|
50
|
-
# @api public
|
|
51
|
-
def to_a
|
|
52
|
-
raise(
|
|
53
|
-
ArgumentError,
|
|
54
|
-
"#{relation.class}##{name.relation} arity is #{arity} " \
|
|
55
|
-
"(#{curry_args.size} args given)"
|
|
56
|
-
)
|
|
57
|
-
end
|
|
58
|
-
alias_method :to_ary, :to_a
|
|
59
|
-
|
|
60
|
-
# Return if this lazy relation is curried
|
|
61
|
-
#
|
|
62
|
-
# @return [true]
|
|
63
|
-
#
|
|
64
|
-
# @api private
|
|
65
|
-
def curried?
|
|
66
|
-
true
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
# @api private
|
|
70
|
-
def respond_to_missing?(name, include_private = false)
|
|
71
|
-
super || relation.respond_to?(name, include_private)
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
private
|
|
75
|
-
|
|
76
|
-
# @api private
|
|
77
|
-
def __new__(relation, new_opts = EMPTY_HASH)
|
|
78
|
-
Curried.new(relation, options.merge(new_opts))
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
# @api private
|
|
82
|
-
def composite_class
|
|
83
|
-
Relation::Composite
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
# @api private
|
|
87
|
-
def method_missing(meth, *args, &block)
|
|
88
|
-
if relation.respond_to?(meth)
|
|
89
|
-
response = relation.__send__(meth, *args, &block)
|
|
90
|
-
|
|
91
|
-
super if response.is_a?(self.class)
|
|
92
|
-
|
|
93
|
-
if response.is_a?(Relation) || response.is_a?(Graph)
|
|
94
|
-
__new__(response)
|
|
95
|
-
else
|
|
96
|
-
response
|
|
97
|
-
end
|
|
98
|
-
else
|
|
99
|
-
super
|
|
100
|
-
end
|
|
101
|
-
end
|
|
102
|
-
end
|
|
103
|
-
end
|
|
104
|
-
end
|
data/lib/rom/relation/graph.rb
DELETED
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
require 'rom/relation/loaded'
|
|
2
|
-
require 'rom/relation/composite'
|
|
3
|
-
require 'rom/relation/materializable'
|
|
4
|
-
require 'rom/pipeline'
|
|
5
|
-
|
|
6
|
-
module ROM
|
|
7
|
-
class Relation
|
|
8
|
-
# Compose relations using join-keys
|
|
9
|
-
#
|
|
10
|
-
# @example
|
|
11
|
-
# class Users < ROM::Relation[:memory]
|
|
12
|
-
# end
|
|
13
|
-
#
|
|
14
|
-
# class Tasks < ROM::Relation[:memory]
|
|
15
|
-
# def for_users(users)
|
|
16
|
-
# restrict(user: users.map { |user| user[:name] })
|
|
17
|
-
# end
|
|
18
|
-
# end
|
|
19
|
-
#
|
|
20
|
-
# rom.relations[:users] << { name: 'Jane' }
|
|
21
|
-
# rom.relations[:tasks] << { user: 'Jane', title: 'Do something' }
|
|
22
|
-
#
|
|
23
|
-
# rom.relation(:users).combine(rom.relation(:tasks).for_users)
|
|
24
|
-
#
|
|
25
|
-
# @api public
|
|
26
|
-
class Graph
|
|
27
|
-
include Materializable
|
|
28
|
-
include Pipeline
|
|
29
|
-
include Pipeline::Proxy
|
|
30
|
-
|
|
31
|
-
# Root aka parent relation
|
|
32
|
-
#
|
|
33
|
-
# @return [Relation::Lazy]
|
|
34
|
-
#
|
|
35
|
-
# @api private
|
|
36
|
-
attr_reader :root
|
|
37
|
-
|
|
38
|
-
# Child relation nodes
|
|
39
|
-
#
|
|
40
|
-
# @return [Array<Relation::Lazy>]
|
|
41
|
-
#
|
|
42
|
-
# @api private
|
|
43
|
-
attr_reader :nodes
|
|
44
|
-
|
|
45
|
-
alias_method :left, :root
|
|
46
|
-
alias_method :right, :nodes
|
|
47
|
-
|
|
48
|
-
# @api private
|
|
49
|
-
def self.build(root, nodes)
|
|
50
|
-
if nodes.any? { |node| node.instance_of?(Composite) }
|
|
51
|
-
raise UnsupportedRelationError,
|
|
52
|
-
"Combining with composite relations is not supported"
|
|
53
|
-
else
|
|
54
|
-
new(root, nodes)
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
# @api private
|
|
59
|
-
def initialize(root, nodes)
|
|
60
|
-
@root = root
|
|
61
|
-
@nodes = nodes
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
# Return if this is a graph relation
|
|
65
|
-
#
|
|
66
|
-
# @return [true]
|
|
67
|
-
#
|
|
68
|
-
# @api private
|
|
69
|
-
def graph?
|
|
70
|
-
true
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
# Combine this graph with more nodes
|
|
74
|
-
#
|
|
75
|
-
# @param [Array<Relation::Lazy>]
|
|
76
|
-
#
|
|
77
|
-
# @return [Graph]
|
|
78
|
-
#
|
|
79
|
-
# @api public
|
|
80
|
-
def combine(*others)
|
|
81
|
-
self.class.new(root, nodes + others)
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
# Materialize this relation graph
|
|
85
|
-
#
|
|
86
|
-
# @return [Loaded]
|
|
87
|
-
#
|
|
88
|
-
# @api public
|
|
89
|
-
def call(*args)
|
|
90
|
-
left = root.call(*args)
|
|
91
|
-
|
|
92
|
-
right =
|
|
93
|
-
if left.count > 0
|
|
94
|
-
nodes.map { |node| node.call(left) }
|
|
95
|
-
else
|
|
96
|
-
nodes.map { |node| Loaded.new(node, []) }
|
|
97
|
-
end
|
|
98
|
-
|
|
99
|
-
Loaded.new(self, [left, right])
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
private
|
|
103
|
-
|
|
104
|
-
# @api private
|
|
105
|
-
def decorate?(other)
|
|
106
|
-
super || other.is_a?(Curried)
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
# @api private
|
|
110
|
-
def composite_class
|
|
111
|
-
Relation::Composite
|
|
112
|
-
end
|
|
113
|
-
end
|
|
114
|
-
end
|
|
115
|
-
end
|
data/lib/rom/relation/loaded.rb
DELETED
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
module ROM
|
|
2
|
-
class Relation
|
|
3
|
-
# Materializes a relation and exposes interface to access the data
|
|
4
|
-
#
|
|
5
|
-
# @api public
|
|
6
|
-
class Loaded
|
|
7
|
-
include Enumerable
|
|
8
|
-
|
|
9
|
-
# Coerce loaded relation to an array
|
|
10
|
-
#
|
|
11
|
-
# @return [Array]
|
|
12
|
-
#
|
|
13
|
-
# @api public
|
|
14
|
-
alias_method :to_ary, :to_a
|
|
15
|
-
|
|
16
|
-
# Source relation
|
|
17
|
-
#
|
|
18
|
-
# @return [Relation]
|
|
19
|
-
#
|
|
20
|
-
# @api private
|
|
21
|
-
attr_reader :source
|
|
22
|
-
|
|
23
|
-
# Materialized relation
|
|
24
|
-
#
|
|
25
|
-
# @return [Object]
|
|
26
|
-
#
|
|
27
|
-
# @api private
|
|
28
|
-
attr_reader :collection
|
|
29
|
-
|
|
30
|
-
# @api private
|
|
31
|
-
def initialize(source, collection = source.to_a)
|
|
32
|
-
@source = source
|
|
33
|
-
@collection = collection
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
# Yield relation tuples
|
|
37
|
-
#
|
|
38
|
-
# @yield [Hash]
|
|
39
|
-
#
|
|
40
|
-
# @api public
|
|
41
|
-
def each(&block)
|
|
42
|
-
return to_enum unless block
|
|
43
|
-
collection.each { |tuple| yield(tuple) }
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
# Returns a single tuple from the relation if there is one.
|
|
47
|
-
#
|
|
48
|
-
# @raise [ROM::TupleCountMismatchError] if the relation contains more than
|
|
49
|
-
# one tuple
|
|
50
|
-
#
|
|
51
|
-
# @api public
|
|
52
|
-
def one
|
|
53
|
-
if collection.count > 1
|
|
54
|
-
raise(
|
|
55
|
-
TupleCountMismatchError,
|
|
56
|
-
'The relation consists of more than one tuple'
|
|
57
|
-
)
|
|
58
|
-
else
|
|
59
|
-
collection.first
|
|
60
|
-
end
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
# Like [one], but additionally raises an error if the relation is empty.
|
|
64
|
-
#
|
|
65
|
-
# @raise [ROM::TupleCountMismatchError] if the relation does not contain
|
|
66
|
-
# exactly one tuple
|
|
67
|
-
#
|
|
68
|
-
# @api public
|
|
69
|
-
def one!
|
|
70
|
-
one || raise(
|
|
71
|
-
TupleCountMismatchError,
|
|
72
|
-
'The relation does not contain any tuples'
|
|
73
|
-
)
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
# Return a list of values under provided key
|
|
77
|
-
#
|
|
78
|
-
# @example
|
|
79
|
-
# all_users = rom.relations[:users].call
|
|
80
|
-
# all_users.pluck(:name)
|
|
81
|
-
# # ["Jane", "Joe"]
|
|
82
|
-
#
|
|
83
|
-
# @param [Symbol] key The key name
|
|
84
|
-
#
|
|
85
|
-
# @return [Array]
|
|
86
|
-
# @raises KeyError when provided key doesn't exist in any of the tuples
|
|
87
|
-
#
|
|
88
|
-
# @api public
|
|
89
|
-
def pluck(key)
|
|
90
|
-
map { |tuple| tuple.fetch(key) }
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
# Pluck primary key values
|
|
94
|
-
#
|
|
95
|
-
# This method *may not work* with adapters that don't provide relations
|
|
96
|
-
# that have primary key configured
|
|
97
|
-
#
|
|
98
|
-
# @example
|
|
99
|
-
# users = rom.relations[:users].call
|
|
100
|
-
# users.primary_keys
|
|
101
|
-
# # [1, 2, 3]
|
|
102
|
-
#
|
|
103
|
-
# @return [Array]
|
|
104
|
-
#
|
|
105
|
-
# @api public
|
|
106
|
-
def primary_keys
|
|
107
|
-
pluck(source.primary_key)
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
# Return a loaded relation with a new collection
|
|
111
|
-
#
|
|
112
|
-
# @api public
|
|
113
|
-
def new(collection)
|
|
114
|
-
self.class.new(source, collection)
|
|
115
|
-
end
|
|
116
|
-
end
|
|
117
|
-
end
|
|
118
|
-
end
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
module ROM
|
|
2
|
-
class Relation
|
|
3
|
-
# Interface for objects that can be materialized into a loaded relation
|
|
4
|
-
#
|
|
5
|
-
# @api public
|
|
6
|
-
module Materializable
|
|
7
|
-
# @abstract
|
|
8
|
-
#
|
|
9
|
-
# @api public
|
|
10
|
-
def call(*)
|
|
11
|
-
raise NotImplementedError, "#{self.class}#call must be implemented"
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
# Coerce the relation to an array
|
|
15
|
-
#
|
|
16
|
-
# @return [Array]
|
|
17
|
-
#
|
|
18
|
-
# @api public
|
|
19
|
-
def to_a
|
|
20
|
-
call.to_a
|
|
21
|
-
end
|
|
22
|
-
alias_method :to_ary, :to_a
|
|
23
|
-
|
|
24
|
-
# Yield relation tuples
|
|
25
|
-
#
|
|
26
|
-
# @yield [Hash,Object]
|
|
27
|
-
#
|
|
28
|
-
# @api public
|
|
29
|
-
def each(&block)
|
|
30
|
-
return to_enum unless block
|
|
31
|
-
to_a.each { |tuple| yield(tuple) }
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
# Delegate to loaded relation and return one object
|
|
35
|
-
#
|
|
36
|
-
# @return [Object]
|
|
37
|
-
#
|
|
38
|
-
# @see Loaded#one
|
|
39
|
-
#
|
|
40
|
-
# @api public
|
|
41
|
-
def one
|
|
42
|
-
call.one
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
# Delegate to loaded relation and return one object
|
|
46
|
-
#
|
|
47
|
-
# @return [Object]
|
|
48
|
-
#
|
|
49
|
-
# @see Loaded#one
|
|
50
|
-
#
|
|
51
|
-
# @api public
|
|
52
|
-
def one!
|
|
53
|
-
call.one!
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
# Return first tuple from a relation coerced to an array
|
|
57
|
-
#
|
|
58
|
-
# @return [Object]
|
|
59
|
-
#
|
|
60
|
-
# @api public
|
|
61
|
-
def first
|
|
62
|
-
to_a.first
|
|
63
|
-
end
|
|
64
|
-
end
|
|
65
|
-
end
|
|
66
|
-
end
|