rom-core 4.0.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- 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
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2013-2017 rom-rb team
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
[gem]: https://rubygems.org/gems/rom-core
|
2
|
+
[gemnasium]: https://gemnasium.com/rom-rb/rom-core
|
3
|
+
|
4
|
+
# rom-core [![Gitter chat](https://badges.gitter.im/rom-rb/chat.svg)](https://gitter.im/rom-rb/chat)
|
5
|
+
|
6
|
+
[![Gem Version](https://badge.fury.io/rb/rom-core.svg)][gem]
|
7
|
+
[![Dependency Status](https://gemnasium.com/rom-rb/rom-core.svg)][gemnasium]
|
8
|
+
|
9
|
+
Core API for rom-rb and its adapters and extensions.
|
10
|
+
|
11
|
+
Resources:
|
12
|
+
|
13
|
+
* [User documentation](http://rom-rb.org/learn/core)
|
14
|
+
* [API documentation](http://rubydoc.info/gems/rom-core)
|
15
|
+
|
16
|
+
## License
|
17
|
+
|
18
|
+
See `LICENSE` file.
|
data/lib/rom-core.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'rom/core'
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'rom/initializer'
|
2
|
+
require 'rom/enumerable_dataset'
|
3
|
+
|
4
|
+
module ROM
|
5
|
+
# A helper module that adds data-proxy behavior to an array-like object
|
6
|
+
#
|
7
|
+
# @see EnumerableDataset
|
8
|
+
#
|
9
|
+
# @api public
|
10
|
+
module ArrayDataset
|
11
|
+
extend DataProxy::ClassMethods
|
12
|
+
include EnumerableDataset
|
13
|
+
|
14
|
+
# Extends the class with data-proxy behavior
|
15
|
+
#
|
16
|
+
# @api private
|
17
|
+
def self.included(klass)
|
18
|
+
klass.class_eval do
|
19
|
+
extend Initializer
|
20
|
+
include DataProxy
|
21
|
+
|
22
|
+
param :data
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
forward(
|
27
|
+
:*, :+, :-, :compact, :compact!, :flatten, :flatten!, :length, :pop,
|
28
|
+
:reverse, :reverse!, :sample, :size, :shift, :shuffle, :shuffle!,
|
29
|
+
:slice, :slice!, :sort!, :uniq, :uniq!, :unshift, :values_at
|
30
|
+
)
|
31
|
+
|
32
|
+
[
|
33
|
+
:map!, :combination, :cycle, :delete_if, :keep_if, :permutation, :reject!,
|
34
|
+
:select!, :sort_by!
|
35
|
+
].each do |method|
|
36
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
37
|
+
def #{method}(*args, &block)
|
38
|
+
return to_enum unless block
|
39
|
+
self.class.new(data.send(:#{method}, *args, &block), options)
|
40
|
+
end
|
41
|
+
RUBY
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'rom/registry'
|
2
|
+
|
3
|
+
module ROM
|
4
|
+
# @api public
|
5
|
+
class AssociationSet < ROM::Registry
|
6
|
+
# @api private
|
7
|
+
def initialize(*)
|
8
|
+
super
|
9
|
+
elements.values.each do |assoc|
|
10
|
+
if assoc.aliased? && !key?(assoc.name)
|
11
|
+
elements[assoc.name] = assoc
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,135 @@
|
|
1
|
+
require 'dry/core/constants'
|
2
|
+
require 'dry/core/class_attributes'
|
3
|
+
|
4
|
+
require 'rom/types'
|
5
|
+
require 'rom/initializer'
|
6
|
+
require 'rom/support/memoizable'
|
7
|
+
|
8
|
+
module ROM
|
9
|
+
module Associations
|
10
|
+
# Abstract association class
|
11
|
+
#
|
12
|
+
# @api public
|
13
|
+
class Abstract
|
14
|
+
extend Initializer
|
15
|
+
|
16
|
+
include Memoizable
|
17
|
+
include Dry::Equalizer(:definition, :source, :target)
|
18
|
+
|
19
|
+
# @!attribute [r] definition
|
20
|
+
# @return [ROM::Associations::Definition] Association configuration object
|
21
|
+
param :definition
|
22
|
+
|
23
|
+
# @!attribute [r] relations
|
24
|
+
# @return [ROM::RelationRegistry] Relation registry
|
25
|
+
option :relations, reader: true
|
26
|
+
|
27
|
+
# @!attribute [r] source
|
28
|
+
# @return [ROM::SQL::Relation] the source relation
|
29
|
+
option :source, reader: true
|
30
|
+
|
31
|
+
# @!attribute [r] target
|
32
|
+
# @return [ROM::SQL::Relation::Name] the target relation
|
33
|
+
option :target, reader: true
|
34
|
+
|
35
|
+
# @api public
|
36
|
+
def self.new(definition, relations)
|
37
|
+
super(
|
38
|
+
definition,
|
39
|
+
relations: relations,
|
40
|
+
source: relations[definition.source.relation],
|
41
|
+
target: relations[definition.target.relation]
|
42
|
+
)
|
43
|
+
end
|
44
|
+
|
45
|
+
# @api public
|
46
|
+
def aliased?
|
47
|
+
definition.aliased?
|
48
|
+
end
|
49
|
+
|
50
|
+
# @api public
|
51
|
+
def as
|
52
|
+
definition.as
|
53
|
+
end
|
54
|
+
|
55
|
+
# @api public
|
56
|
+
def name
|
57
|
+
definition.name
|
58
|
+
end
|
59
|
+
|
60
|
+
# @api public
|
61
|
+
def view
|
62
|
+
definition.view
|
63
|
+
end
|
64
|
+
|
65
|
+
# @api public
|
66
|
+
def foreign_key
|
67
|
+
definition.foreign_key
|
68
|
+
end
|
69
|
+
|
70
|
+
# @api public
|
71
|
+
def result
|
72
|
+
definition.result
|
73
|
+
end
|
74
|
+
|
75
|
+
# @api public
|
76
|
+
def override?
|
77
|
+
definition.override
|
78
|
+
end
|
79
|
+
|
80
|
+
# @api public
|
81
|
+
def key
|
82
|
+
as || name
|
83
|
+
end
|
84
|
+
|
85
|
+
# @api protected
|
86
|
+
def apply_view(schema, relation)
|
87
|
+
view_rel = relation.public_send(view)
|
88
|
+
schema.merge(view_rel.schema).uniq(&:key).(view_rel)
|
89
|
+
end
|
90
|
+
|
91
|
+
# @api public
|
92
|
+
def combine_keys
|
93
|
+
{ source_key => target_key }
|
94
|
+
end
|
95
|
+
|
96
|
+
# @api private
|
97
|
+
def join_key_map
|
98
|
+
join_keys.to_a.flatten(1).map(&:key)
|
99
|
+
end
|
100
|
+
|
101
|
+
# @api private
|
102
|
+
def node
|
103
|
+
target.with(
|
104
|
+
name: target.name.as(key),
|
105
|
+
meta: { keys: combine_keys, combine_type: result, combine_name: key }
|
106
|
+
)
|
107
|
+
end
|
108
|
+
|
109
|
+
# @api private
|
110
|
+
def wrap
|
111
|
+
target.with(
|
112
|
+
name: target.name.as(key),
|
113
|
+
schema: target.schema.wrap,
|
114
|
+
meta: { wrap: true, combine_name: key }
|
115
|
+
)
|
116
|
+
end
|
117
|
+
|
118
|
+
# @api private
|
119
|
+
def prepare(target)
|
120
|
+
if override?
|
121
|
+
target.public_send(view)
|
122
|
+
else
|
123
|
+
call(target: target)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
# @api private
|
128
|
+
def self_ref?
|
129
|
+
source.name.dataset == target.name.dataset
|
130
|
+
end
|
131
|
+
|
132
|
+
memoize :combine_keys, :join_key_map
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
require 'dry/core/class_attributes'
|
2
|
+
|
3
|
+
require 'rom/constants'
|
4
|
+
require 'rom/types'
|
5
|
+
require 'rom/initializer'
|
6
|
+
require 'rom/relation/name'
|
7
|
+
require 'rom/associations/through_identifier'
|
8
|
+
|
9
|
+
module ROM
|
10
|
+
module Associations
|
11
|
+
module Definitions
|
12
|
+
# Abstract association definition object
|
13
|
+
#
|
14
|
+
# @api public
|
15
|
+
class Abstract
|
16
|
+
include Dry::Equalizer(:source, :target, :result)
|
17
|
+
extend Initializer
|
18
|
+
extend Dry::Core::ClassAttributes
|
19
|
+
|
20
|
+
defines :result
|
21
|
+
|
22
|
+
# @!attribute [r] source
|
23
|
+
# @return [Relation::Name] the source relation name
|
24
|
+
param :source
|
25
|
+
|
26
|
+
# @!attribute [r] target
|
27
|
+
# @return [Relation::Name] the target relation name
|
28
|
+
param :target
|
29
|
+
|
30
|
+
# @!attribute [r] relation
|
31
|
+
# @return [Symbol] an optional relation identifier for the target
|
32
|
+
option :relation, Types::Strict::Symbol, optional: true
|
33
|
+
|
34
|
+
# @!attribute [r] result
|
35
|
+
# @return [Symbol] either :one or :many
|
36
|
+
option :result, Types::Strict::Symbol, default: -> { self.class.result }
|
37
|
+
|
38
|
+
# @!attribute [r] name
|
39
|
+
# @return [Symbol] The name of an association
|
40
|
+
option :name, Types::Strict::Symbol, default: -> { target.to_sym }
|
41
|
+
|
42
|
+
# @!attribute [r] alias
|
43
|
+
# @return [Symbol] An optional association alias
|
44
|
+
option :as, Types::Strict::Symbol.optional, optional: true
|
45
|
+
|
46
|
+
# @!attribute [r] foreign_key
|
47
|
+
# @return [Symbol] an optional association alias name
|
48
|
+
option :foreign_key, Types::Optional::Strict::Symbol, optional: true
|
49
|
+
|
50
|
+
# @!attribute [r] view
|
51
|
+
# @return [Symbol] An optional view that should be used to extend assoc relation
|
52
|
+
option :view, optional: true
|
53
|
+
|
54
|
+
# @!attribute [r] override
|
55
|
+
# @return [TrueClass,FalseClass] Whether custom view should override default one or not
|
56
|
+
option :override, optional: true, default: -> { false }
|
57
|
+
|
58
|
+
# Instantiate a new association definition
|
59
|
+
#
|
60
|
+
# @param [Symbol] source The name of the source dataset
|
61
|
+
# @param [Symbol] target The name of the target dataset
|
62
|
+
# @param [Hash] options The option hash
|
63
|
+
# @option options [Symbol] :as The name of the association (defaults to target)
|
64
|
+
# @option options [Symbol] :relation The name of the target relation (defaults to target)
|
65
|
+
# @option options [Symbol] :foreign_key The name of a custom foreign key
|
66
|
+
# @option options [Symbol] :view The name of a custom relation view on the target's relation side
|
67
|
+
# @option options [TrueClass,FalseClass] :override Whether provided :view should override association's default view
|
68
|
+
#
|
69
|
+
# @api public
|
70
|
+
def self.new(source, target, opts = EMPTY_HASH)
|
71
|
+
source_name = Relation::Name[source]
|
72
|
+
target_name = resolve_target_name(target, opts)
|
73
|
+
options = process_options(target_name, Hash[opts])
|
74
|
+
|
75
|
+
super(source_name, target_name, options)
|
76
|
+
end
|
77
|
+
|
78
|
+
# @api private
|
79
|
+
def self.resolve_target_name(target, options)
|
80
|
+
dataset = target
|
81
|
+
relation = options.fetch(:relation, target)
|
82
|
+
|
83
|
+
Relation::Name[relation, dataset, options[:as]]
|
84
|
+
end
|
85
|
+
|
86
|
+
# @api private
|
87
|
+
def self.process_options(target, options)
|
88
|
+
through = options[:through]
|
89
|
+
|
90
|
+
if through
|
91
|
+
options[:through] = ThroughIdentifier[through, target.relation, options[:assoc]]
|
92
|
+
end
|
93
|
+
|
94
|
+
options[:name] = target.relation
|
95
|
+
|
96
|
+
options
|
97
|
+
end
|
98
|
+
|
99
|
+
# @api public
|
100
|
+
def override?
|
101
|
+
options[:override].equal?(true)
|
102
|
+
end
|
103
|
+
|
104
|
+
# @api public
|
105
|
+
def aliased?
|
106
|
+
options.key?(:as)
|
107
|
+
end
|
108
|
+
|
109
|
+
# @api public
|
110
|
+
def type
|
111
|
+
Dry::Core::Inflector.demodulize(self.class.name).to_sym
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'rom/types'
|
2
|
+
require 'rom/associations/definitions/abstract'
|
3
|
+
|
4
|
+
module ROM
|
5
|
+
module Associations
|
6
|
+
module Definitions
|
7
|
+
class ManyToMany < Abstract
|
8
|
+
result :many
|
9
|
+
|
10
|
+
option :through, reader: true
|
11
|
+
|
12
|
+
# @api private
|
13
|
+
def through_relation
|
14
|
+
through.relation
|
15
|
+
end
|
16
|
+
|
17
|
+
# @api private
|
18
|
+
def through_assoc_name
|
19
|
+
through.assoc_name
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|