rom-core 4.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 +7 -0
- data/CHANGELOG.md +603 -0
- data/LICENSE +20 -0
- data/README.md +18 -0
- data/lib/rom-core.rb +1 -0
- data/lib/rom/array_dataset.rb +44 -0
- data/lib/rom/association_set.rb +16 -0
- data/lib/rom/associations/abstract.rb +135 -0
- data/lib/rom/associations/definitions.rb +5 -0
- data/lib/rom/associations/definitions/abstract.rb +116 -0
- data/lib/rom/associations/definitions/many_to_many.rb +24 -0
- data/lib/rom/associations/definitions/many_to_one.rb +11 -0
- data/lib/rom/associations/definitions/one_to_many.rb +11 -0
- data/lib/rom/associations/definitions/one_to_one.rb +11 -0
- data/lib/rom/associations/definitions/one_to_one_through.rb +11 -0
- data/lib/rom/associations/many_to_many.rb +81 -0
- data/lib/rom/associations/many_to_one.rb +37 -0
- data/lib/rom/associations/one_to_many.rb +37 -0
- data/lib/rom/associations/one_to_one.rb +8 -0
- data/lib/rom/associations/one_to_one_through.rb +8 -0
- data/lib/rom/associations/through_identifier.rb +39 -0
- data/lib/rom/auto_curry.rb +55 -0
- data/lib/rom/cache.rb +46 -0
- data/lib/rom/command.rb +488 -0
- data/lib/rom/command_compiler.rb +239 -0
- data/lib/rom/command_proxy.rb +24 -0
- data/lib/rom/command_registry.rb +141 -0
- data/lib/rom/commands.rb +3 -0
- data/lib/rom/commands/class_interface.rb +270 -0
- data/lib/rom/commands/composite.rb +53 -0
- data/lib/rom/commands/create.rb +13 -0
- data/lib/rom/commands/delete.rb +14 -0
- data/lib/rom/commands/graph.rb +88 -0
- data/lib/rom/commands/graph/class_interface.rb +62 -0
- data/lib/rom/commands/graph/input_evaluator.rb +62 -0
- data/lib/rom/commands/lazy.rb +99 -0
- data/lib/rom/commands/lazy/create.rb +23 -0
- data/lib/rom/commands/lazy/delete.rb +27 -0
- data/lib/rom/commands/lazy/update.rb +34 -0
- data/lib/rom/commands/result.rb +96 -0
- data/lib/rom/commands/update.rb +14 -0
- data/lib/rom/configuration.rb +114 -0
- data/lib/rom/configuration_dsl.rb +87 -0
- data/lib/rom/configuration_dsl/command.rb +41 -0
- data/lib/rom/configuration_dsl/command_dsl.rb +35 -0
- data/lib/rom/configuration_dsl/relation.rb +26 -0
- data/lib/rom/configuration_plugin.rb +17 -0
- data/lib/rom/constants.rb +64 -0
- data/lib/rom/container.rb +147 -0
- data/lib/rom/core.rb +46 -0
- data/lib/rom/create_container.rb +60 -0
- data/lib/rom/data_proxy.rb +94 -0
- data/lib/rom/enumerable_dataset.rb +68 -0
- data/lib/rom/environment.rb +70 -0
- data/lib/rom/gateway.rb +184 -0
- data/lib/rom/global.rb +58 -0
- data/lib/rom/global/plugin_dsl.rb +47 -0
- data/lib/rom/initializer.rb +64 -0
- data/lib/rom/lint/enumerable_dataset.rb +54 -0
- data/lib/rom/lint/gateway.rb +120 -0
- data/lib/rom/lint/linter.rb +78 -0
- data/lib/rom/lint/spec.rb +20 -0
- data/lib/rom/lint/test.rb +98 -0
- data/lib/rom/mapper_registry.rb +24 -0
- data/lib/rom/memory.rb +4 -0
- data/lib/rom/memory/associations.rb +4 -0
- data/lib/rom/memory/associations/many_to_many.rb +10 -0
- data/lib/rom/memory/associations/many_to_one.rb +10 -0
- data/lib/rom/memory/associations/one_to_many.rb +10 -0
- data/lib/rom/memory/associations/one_to_one.rb +10 -0
- data/lib/rom/memory/commands.rb +56 -0
- data/lib/rom/memory/dataset.rb +97 -0
- data/lib/rom/memory/gateway.rb +64 -0
- data/lib/rom/memory/relation.rb +62 -0
- data/lib/rom/memory/schema.rb +23 -0
- data/lib/rom/memory/storage.rb +59 -0
- data/lib/rom/memory/types.rb +9 -0
- data/lib/rom/pipeline.rb +105 -0
- data/lib/rom/plugin.rb +25 -0
- data/lib/rom/plugin_base.rb +45 -0
- data/lib/rom/plugin_registry.rb +197 -0
- data/lib/rom/plugins/command/schema.rb +37 -0
- data/lib/rom/plugins/configuration/configuration_dsl.rb +21 -0
- data/lib/rom/plugins/relation/instrumentation.rb +51 -0
- data/lib/rom/plugins/relation/registry_reader.rb +44 -0
- data/lib/rom/plugins/schema/timestamps.rb +58 -0
- data/lib/rom/registry.rb +71 -0
- data/lib/rom/relation.rb +548 -0
- data/lib/rom/relation/class_interface.rb +282 -0
- data/lib/rom/relation/commands.rb +23 -0
- data/lib/rom/relation/composite.rb +46 -0
- data/lib/rom/relation/curried.rb +103 -0
- data/lib/rom/relation/graph.rb +197 -0
- data/lib/rom/relation/loaded.rb +127 -0
- data/lib/rom/relation/materializable.rb +66 -0
- data/lib/rom/relation/name.rb +111 -0
- data/lib/rom/relation/view_dsl.rb +64 -0
- data/lib/rom/relation/wrap.rb +83 -0
- data/lib/rom/relation_registry.rb +10 -0
- data/lib/rom/schema.rb +437 -0
- data/lib/rom/schema/associations_dsl.rb +195 -0
- data/lib/rom/schema/attribute.rb +419 -0
- data/lib/rom/schema/dsl.rb +164 -0
- data/lib/rom/schema/inferrer.rb +66 -0
- data/lib/rom/schema_plugin.rb +27 -0
- data/lib/rom/setup.rb +68 -0
- data/lib/rom/setup/auto_registration.rb +74 -0
- data/lib/rom/setup/auto_registration_strategies/base.rb +16 -0
- data/lib/rom/setup/auto_registration_strategies/custom_namespace.rb +63 -0
- data/lib/rom/setup/auto_registration_strategies/no_namespace.rb +20 -0
- data/lib/rom/setup/auto_registration_strategies/with_namespace.rb +18 -0
- data/lib/rom/setup/finalize.rb +103 -0
- data/lib/rom/setup/finalize/finalize_commands.rb +60 -0
- data/lib/rom/setup/finalize/finalize_mappers.rb +56 -0
- data/lib/rom/setup/finalize/finalize_relations.rb +135 -0
- data/lib/rom/support/configurable.rb +85 -0
- data/lib/rom/support/memoizable.rb +58 -0
- data/lib/rom/support/notifications.rb +103 -0
- data/lib/rom/transaction.rb +24 -0
- data/lib/rom/types.rb +26 -0
- data/lib/rom/version.rb +5 -0
- metadata +289 -0
@@ -0,0 +1,282 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
3
|
+
require 'dry/core/inflector'
|
4
|
+
|
5
|
+
require 'rom/constants'
|
6
|
+
require 'rom/relation/name'
|
7
|
+
require 'rom/relation/view_dsl'
|
8
|
+
require 'rom/schema'
|
9
|
+
require 'rom/support/notifications'
|
10
|
+
|
11
|
+
module ROM
|
12
|
+
class Relation
|
13
|
+
# @api public
|
14
|
+
module ClassInterface
|
15
|
+
extend Notifications::Listener
|
16
|
+
|
17
|
+
subscribe('configuration.relations.object.registered') do |event|
|
18
|
+
relation = event[:relation]
|
19
|
+
registry = event[:registry]
|
20
|
+
|
21
|
+
schemas = relation.schemas.reduce({}) do |h, (a, e)|
|
22
|
+
h.update(a => e.is_a?(Proc) ? relation.class.instance_exec(registry, &e) : e)
|
23
|
+
end
|
24
|
+
|
25
|
+
relation.schemas.update(schemas)
|
26
|
+
relation
|
27
|
+
end
|
28
|
+
|
29
|
+
DEFAULT_DATASET_PROC = -> * { self }.freeze
|
30
|
+
|
31
|
+
# Return adapter-specific relation subclass
|
32
|
+
#
|
33
|
+
# @example
|
34
|
+
# ROM::Relation[:memory]
|
35
|
+
# # => ROM::Memory::Relation
|
36
|
+
#
|
37
|
+
# @return [Class]
|
38
|
+
#
|
39
|
+
# @api public
|
40
|
+
def [](adapter)
|
41
|
+
ROM.adapters.fetch(adapter).const_get(:Relation)
|
42
|
+
rescue KeyError
|
43
|
+
raise AdapterNotPresentError.new(adapter, :relation)
|
44
|
+
end
|
45
|
+
|
46
|
+
# Set or get custom dataset block
|
47
|
+
#
|
48
|
+
# This block will be evaluated when a relation is instantiated and registered
|
49
|
+
# in a relation registry.
|
50
|
+
#
|
51
|
+
# @example
|
52
|
+
# class Users < ROM::Relation[:memory]
|
53
|
+
# dataset { sort_by(:id) }
|
54
|
+
# end
|
55
|
+
#
|
56
|
+
# @api public
|
57
|
+
def dataset(&block)
|
58
|
+
if defined?(@dataset)
|
59
|
+
@dataset
|
60
|
+
else
|
61
|
+
@dataset = block || DEFAULT_DATASET_PROC
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# Specify canonical schema for a relation
|
66
|
+
#
|
67
|
+
# With a schema defined commands will set up a type-safe input handler
|
68
|
+
# automatically
|
69
|
+
#
|
70
|
+
# @example
|
71
|
+
# class Users < ROM::Relation[:sql]
|
72
|
+
# schema do
|
73
|
+
# attribute :id, Types::Serial
|
74
|
+
# attribute :name, Types::String
|
75
|
+
# end
|
76
|
+
# end
|
77
|
+
#
|
78
|
+
# # access schema
|
79
|
+
# Users.schema
|
80
|
+
#
|
81
|
+
# @return [Schema]
|
82
|
+
#
|
83
|
+
# @param [Symbol] dataset An optional dataset name
|
84
|
+
# @param [Boolean] infer Whether to do an automatic schema inferring
|
85
|
+
#
|
86
|
+
# @api public
|
87
|
+
def schema(dataset = nil, as: nil, infer: false, &block)
|
88
|
+
if defined?(@schema) && !block && !infer
|
89
|
+
@schema
|
90
|
+
elsif block || infer
|
91
|
+
raise MissingSchemaClassError.new(self) unless schema_class
|
92
|
+
|
93
|
+
ds_name = dataset || schema_opts.fetch(:dataset, default_name.dataset)
|
94
|
+
relation = as || schema_opts.fetch(:relation, ds_name)
|
95
|
+
|
96
|
+
@relation_name = Name[relation, ds_name]
|
97
|
+
|
98
|
+
dsl = schema_dsl.new(
|
99
|
+
relation_name,
|
100
|
+
schema_class: schema_class,
|
101
|
+
attr_class: schema_attr_class,
|
102
|
+
inferrer: schema_inferrer.with(enabled: infer),
|
103
|
+
&block
|
104
|
+
)
|
105
|
+
|
106
|
+
@schema_proc = dsl.method(:call).to_proc
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
# @api private
|
111
|
+
def set_schema!(schema)
|
112
|
+
@schema = schema
|
113
|
+
end
|
114
|
+
|
115
|
+
# @api private
|
116
|
+
attr_reader :schema_proc
|
117
|
+
|
118
|
+
# !@attribute [r] relation_name
|
119
|
+
# @return [Name] Qualified relation name
|
120
|
+
def relation_name
|
121
|
+
raise MissingSchemaError.new(self) unless defined?(@relation_name)
|
122
|
+
@relation_name
|
123
|
+
end
|
124
|
+
|
125
|
+
# Define a relation view with a specific schema
|
126
|
+
#
|
127
|
+
# Explicit relation views allow relation composition with auto-mapping
|
128
|
+
# in repositories. It's useful for cases like defining custom views
|
129
|
+
# for associations where relations (even from different databases) can
|
130
|
+
# be composed together and automatically mapped in memory to structs.
|
131
|
+
#
|
132
|
+
# @overload view(name, schema, &block)
|
133
|
+
# @example View with the canonical schema
|
134
|
+
# class Users < ROM::Relation[:sql]
|
135
|
+
# view(:listing, schema) do
|
136
|
+
# order(:name)
|
137
|
+
# end
|
138
|
+
# end
|
139
|
+
#
|
140
|
+
# @example View with a projected schema
|
141
|
+
# class Users < ROM::Relation[:sql]
|
142
|
+
# view(:listing, schema.project(:id, :name)) do
|
143
|
+
# order(:name)
|
144
|
+
# end
|
145
|
+
# end
|
146
|
+
#
|
147
|
+
# @overload view(name, &block)
|
148
|
+
# @example View with the canonical schema and arguments
|
149
|
+
# class Users < ROM::Relation[:sql]
|
150
|
+
# view(:by_name) do |name|
|
151
|
+
# where(name: name)
|
152
|
+
# end
|
153
|
+
# end
|
154
|
+
#
|
155
|
+
# @example View with projected schema and arguments
|
156
|
+
# class Users < ROM::Relation[:sql]
|
157
|
+
# view(:by_name) do
|
158
|
+
# schema { project(:id, :name) }
|
159
|
+
# relation { |name| where(name: name) }
|
160
|
+
# end
|
161
|
+
# end
|
162
|
+
#
|
163
|
+
# @example View with a schema extended with foreign attributes
|
164
|
+
# class Users < ROM::Relation[:sql]
|
165
|
+
# view(:index) do
|
166
|
+
# schema { append(relations[:tasks][:title]) }
|
167
|
+
# relation { |name| where(name: name) }
|
168
|
+
# end
|
169
|
+
# end
|
170
|
+
#
|
171
|
+
# @return [Symbol] view method name
|
172
|
+
#
|
173
|
+
# @api public
|
174
|
+
def view(*args, &block)
|
175
|
+
if args.size == 1 && block.arity > 0
|
176
|
+
raise ArgumentError, "header must be set as second argument"
|
177
|
+
end
|
178
|
+
|
179
|
+
name, new_schema_fn, relation_block =
|
180
|
+
if args.size == 1
|
181
|
+
ViewDSL.new(*args, schema, &block).call
|
182
|
+
else
|
183
|
+
[*args, block]
|
184
|
+
end
|
185
|
+
|
186
|
+
schemas[name] =
|
187
|
+
if args.size == 2
|
188
|
+
-> _ { schema.project(*args[1]) }
|
189
|
+
else
|
190
|
+
new_schema_fn
|
191
|
+
end
|
192
|
+
|
193
|
+
if relation_block.arity > 0
|
194
|
+
auto_curry_guard do
|
195
|
+
define_method(name, &relation_block)
|
196
|
+
|
197
|
+
auto_curry(name) do
|
198
|
+
schemas[name].(self)
|
199
|
+
end
|
200
|
+
end
|
201
|
+
else
|
202
|
+
define_method(name) do
|
203
|
+
schemas[name].(instance_exec(&relation_block))
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
name
|
208
|
+
end
|
209
|
+
|
210
|
+
# Dynamically define a method that will forward to the dataset and wrap
|
211
|
+
# response in the relation itself
|
212
|
+
#
|
213
|
+
# @example
|
214
|
+
# class SomeAdapterRelation < ROM::Relation
|
215
|
+
# forward :super_query
|
216
|
+
# end
|
217
|
+
#
|
218
|
+
# @api public
|
219
|
+
def forward(*methods)
|
220
|
+
methods.each do |method|
|
221
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
222
|
+
def #{method}(*args, &block)
|
223
|
+
new(dataset.__send__(:#{method}, *args, &block))
|
224
|
+
end
|
225
|
+
RUBY
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
# Include a registered plugin in this relation class
|
230
|
+
#
|
231
|
+
# @param [Symbol] plugin
|
232
|
+
# @param [Hash] options
|
233
|
+
# @option options [Symbol] :adapter (:default) first adapter to check for plugin
|
234
|
+
#
|
235
|
+
# @api public
|
236
|
+
def use(plugin, options = EMPTY_HASH)
|
237
|
+
ROM.plugin_registry.relations.fetch(plugin, adapter).apply_to(self, options)
|
238
|
+
end
|
239
|
+
|
240
|
+
# @api private
|
241
|
+
def curried
|
242
|
+
Curried
|
243
|
+
end
|
244
|
+
|
245
|
+
# @api private
|
246
|
+
def view_methods
|
247
|
+
ancestor_methods = ancestors.reject { |klass| klass == self }
|
248
|
+
.map(&:instance_methods).flatten(1)
|
249
|
+
|
250
|
+
instance_methods - ancestor_methods + auto_curried_methods
|
251
|
+
end
|
252
|
+
|
253
|
+
# @api private
|
254
|
+
def schemas
|
255
|
+
@schemas ||= {}
|
256
|
+
end
|
257
|
+
|
258
|
+
# Return default relation name used in schemas
|
259
|
+
#
|
260
|
+
# @return [Name]
|
261
|
+
#
|
262
|
+
# @api private
|
263
|
+
def default_name
|
264
|
+
Name[Dry::Core::Inflector.underscore(name).tr('/', '_').to_sym]
|
265
|
+
end
|
266
|
+
|
267
|
+
# @api private
|
268
|
+
def default_schema(klass = self)
|
269
|
+
klass.schema ||
|
270
|
+
if klass.schema_proc
|
271
|
+
klass.set_schema!(klass.schema_proc.call)
|
272
|
+
else
|
273
|
+
klass.schema_class.define(klass.default_name)
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
277
|
+
def name
|
278
|
+
super || superclass.name
|
279
|
+
end
|
280
|
+
end
|
281
|
+
end
|
282
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module ROM
|
2
|
+
class Relation
|
3
|
+
# Extensions for relation classes which provide access to commands
|
4
|
+
#
|
5
|
+
# @api private
|
6
|
+
module Commands
|
7
|
+
# @api public
|
8
|
+
def command(type, mapper: nil, use: EMPTY_ARRAY, **opts)
|
9
|
+
command = commands[type, adapter, to_ast, use, opts]
|
10
|
+
|
11
|
+
if mapper
|
12
|
+
command >> mappers[mapper]
|
13
|
+
elsif mappers.any? && !command.is_a?(CommandProxy)
|
14
|
+
mappers.reduce(command) { |a, (_, e)| a >> e }
|
15
|
+
elsif auto_struct? || auto_map?
|
16
|
+
command >> self.mapper
|
17
|
+
else
|
18
|
+
command
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,46 @@
|
|
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
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require 'rom/types'
|
2
|
+
require 'rom/initializer'
|
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
|
+
extend Initializer
|
11
|
+
|
12
|
+
include Materializable
|
13
|
+
include Pipeline
|
14
|
+
|
15
|
+
undef :map_with
|
16
|
+
|
17
|
+
param :relation
|
18
|
+
|
19
|
+
option :view, type: Types::Strict::Symbol
|
20
|
+
option :arity, type: Types::Strict::Int, default: -> { -1 }
|
21
|
+
option :curry_args, default: -> { EMPTY_ARRAY }
|
22
|
+
|
23
|
+
# Load relation if args match the arity
|
24
|
+
#
|
25
|
+
# @return [Loaded,Curried]
|
26
|
+
#
|
27
|
+
# @api public
|
28
|
+
def call(*args)
|
29
|
+
if arity != -1
|
30
|
+
all_args = curry_args + args
|
31
|
+
|
32
|
+
if all_args.empty?
|
33
|
+
raise ArgumentError, "curried #{relation.class}##{view} relation was called without any arguments"
|
34
|
+
end
|
35
|
+
|
36
|
+
if args.empty?
|
37
|
+
self
|
38
|
+
elsif arity == all_args.size
|
39
|
+
Loaded.new(relation.__send__(view, *all_args))
|
40
|
+
else
|
41
|
+
__new__(relation, curry_args: all_args)
|
42
|
+
end
|
43
|
+
else
|
44
|
+
super
|
45
|
+
end
|
46
|
+
end
|
47
|
+
alias_method :[], :call
|
48
|
+
|
49
|
+
# @api public
|
50
|
+
def to_a
|
51
|
+
raise(
|
52
|
+
ArgumentError,
|
53
|
+
"#{relation.class}##{view} arity is #{arity} " \
|
54
|
+
"(#{curry_args.size} args given)"
|
55
|
+
)
|
56
|
+
end
|
57
|
+
alias_method :to_ary, :to_a
|
58
|
+
|
59
|
+
# Return if this lazy relation is curried
|
60
|
+
#
|
61
|
+
# @return [true]
|
62
|
+
#
|
63
|
+
# @api private
|
64
|
+
def curried?
|
65
|
+
true
|
66
|
+
end
|
67
|
+
|
68
|
+
# @api private
|
69
|
+
def respond_to_missing?(name, include_private = false)
|
70
|
+
super || relation.respond_to?(name, include_private)
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
# @api private
|
76
|
+
def __new__(relation, new_opts = EMPTY_HASH)
|
77
|
+
self.class.new(relation, new_opts.empty? ? options : options.merge(new_opts))
|
78
|
+
end
|
79
|
+
|
80
|
+
# @api private
|
81
|
+
def composite_class
|
82
|
+
Relation::Composite
|
83
|
+
end
|
84
|
+
|
85
|
+
# @api private
|
86
|
+
def method_missing(meth, *args, &block)
|
87
|
+
if relation.respond_to?(meth)
|
88
|
+
response = relation.__send__(meth, *args, &block)
|
89
|
+
|
90
|
+
super if response.is_a?(self.class)
|
91
|
+
|
92
|
+
if response.is_a?(Relation) || response.is_a?(Graph) || response.is_a?(Wrap) || response.is_a?(Composite)
|
93
|
+
__new__(response)
|
94
|
+
else
|
95
|
+
response
|
96
|
+
end
|
97
|
+
else
|
98
|
+
super
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|