rom-core 4.0.0.beta3 → 4.0.0.rc1

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.
Files changed (71) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +3 -1
  3. data/lib/rom/association_set.rb +3 -0
  4. data/lib/rom/associations/abstract.rb +72 -1
  5. data/lib/rom/associations/definitions/abstract.rb +22 -6
  6. data/lib/rom/associations/definitions/many_to_many.rb +3 -0
  7. data/lib/rom/associations/definitions/many_to_one.rb +1 -0
  8. data/lib/rom/associations/definitions/one_to_many.rb +1 -0
  9. data/lib/rom/associations/definitions/one_to_one.rb +1 -0
  10. data/lib/rom/associations/definitions/one_to_one_through.rb +1 -0
  11. data/lib/rom/associations/many_to_many.rb +44 -0
  12. data/lib/rom/associations/many_to_one.rb +26 -0
  13. data/lib/rom/associations/one_to_many.rb +26 -0
  14. data/lib/rom/associations/one_to_one.rb +3 -0
  15. data/lib/rom/associations/one_to_one_through.rb +3 -0
  16. data/lib/rom/attribute.rb +2 -2
  17. data/lib/rom/auto_curry.rb +11 -0
  18. data/lib/rom/cache.rb +29 -0
  19. data/lib/rom/command_compiler.rb +4 -4
  20. data/lib/rom/command_registry.rb +9 -5
  21. data/lib/rom/commands/class_interface.rb +7 -7
  22. data/lib/rom/commands/graph/input_evaluator.rb +33 -3
  23. data/lib/rom/commands/lazy.rb +4 -0
  24. data/lib/rom/commands/lazy/create.rb +10 -0
  25. data/lib/rom/commands/lazy/delete.rb +10 -0
  26. data/lib/rom/commands/lazy/update.rb +10 -0
  27. data/lib/rom/configuration.rb +34 -14
  28. data/lib/rom/configuration_dsl.rb +0 -2
  29. data/lib/rom/constants.rb +10 -0
  30. data/lib/rom/container.rb +16 -0
  31. data/lib/rom/create_container.rb +7 -0
  32. data/lib/rom/environment.rb +3 -2
  33. data/lib/rom/gateway.rb +16 -1
  34. data/lib/rom/global.rb +1 -1
  35. data/lib/rom/global/plugin_dsl.rb +3 -1
  36. data/lib/rom/initializer.rb +25 -13
  37. data/lib/rom/mapper_registry.rb +4 -1
  38. data/lib/rom/memory/dataset.rb +29 -2
  39. data/lib/rom/memory/schema.rb +7 -0
  40. data/lib/rom/plugin_base.rb +1 -1
  41. data/lib/rom/plugin_registry.rb +2 -2
  42. data/lib/rom/plugins/command/schema.rb +7 -0
  43. data/lib/rom/plugins/relation/instrumentation.rb +10 -0
  44. data/lib/rom/plugins/relation/registry_reader.rb +0 -3
  45. data/lib/rom/registry.rb +15 -3
  46. data/lib/rom/relation.rb +38 -23
  47. data/lib/rom/relation/class_interface.rb +15 -6
  48. data/lib/rom/relation/combined.rb +7 -2
  49. data/lib/rom/relation/curried.rb +23 -0
  50. data/lib/rom/relation/graph.rb +25 -14
  51. data/lib/rom/relation/loaded.rb +7 -4
  52. data/lib/rom/relation/materializable.rb +2 -2
  53. data/lib/rom/relation/view_dsl.rb +2 -1
  54. data/lib/rom/relation/wrap.rb +14 -0
  55. data/lib/rom/relation_registry.rb +2 -0
  56. data/lib/rom/schema.rb +25 -4
  57. data/lib/rom/schema/associations_dsl.rb +9 -0
  58. data/lib/rom/schema/dsl.rb +27 -4
  59. data/lib/rom/setup.rb +20 -7
  60. data/lib/rom/setup/auto_registration.rb +27 -0
  61. data/lib/rom/setup/auto_registration_strategies/base.rb +7 -2
  62. data/lib/rom/setup/auto_registration_strategies/custom_namespace.rb +17 -0
  63. data/lib/rom/setup/auto_registration_strategies/no_namespace.rb +11 -0
  64. data/lib/rom/setup/auto_registration_strategies/with_namespace.rb +9 -0
  65. data/lib/rom/setup/finalize/finalize_mappers.rb +4 -2
  66. data/lib/rom/setup/finalize/finalize_relations.rb +1 -1
  67. data/lib/rom/support/configurable.rb +19 -0
  68. data/lib/rom/support/notifications.rb +29 -2
  69. data/lib/rom/types.rb +53 -8
  70. data/lib/rom/version.rb +1 -1
  71. metadata +7 -13
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c8a152a49542a83c5195f02e61f08823c7207f23
4
- data.tar.gz: d4513f31be747f8f01e7c581084782afc3662a6a
3
+ metadata.gz: dd842da91b8eff4e935f9bc0064b7225fbc41d6a
4
+ data.tar.gz: b949c0798bbddfb9bb49b52b0e4137759accc1f7
5
5
  SHA512:
6
- metadata.gz: 652ebe10f678636a8dfe0dd78e1f31fbba58499a9e65eaf1589e46c3abc87e730ee773fdf60435146725e73ca7596e519bc3888dd5498a3d81a90783740a7b40
7
- data.tar.gz: 95f2e25a3eac0195a6d9d35697b619b52364255b7fefcbfd1c68a647f9aefecc21a489f9a945346f6834d2936d81235b447451c9131d2b86be40a5c834144e00
6
+ metadata.gz: c95c856d8c205db0013f905ad72e4e8bcecc243f227410d05607c8e2f1280e5d7cf8943c607cd6b45f5926e55e8febadab4e809cb847efe3e96c48e8c4873200
7
+ data.tar.gz: bf2277dae18e48950740d93a6478cf4d0d56eda97065b797edb5d88d8ab9327f871ab99d2207a909ae80663ae0a654b2495485be7ddf071ab5da6105737b9db8
data/CHANGELOG.md CHANGED
@@ -12,8 +12,10 @@ Previous `rom` gem was renamed to `rom-core`
12
12
  * `Relation#command` which automatically creates a command for a given relation, supports graphs too (solnic)
13
13
  * `Relation::to_ast` which returns an AST representation of a relation. This can be used to infer other objects based on relation information (solnic)
14
14
  * `Relation::Name#as` which returns an aliased relation name (solnic)
15
- * Association DSL supports `:override` option which will use configured `:view` as the relation used by association (solnic)
16
15
  * Associations are now part of core API and available to all adapters, cross-adapter associations are supported too via `:override` option (solnic)
16
+ * New settings in association DSL:
17
+ * `:override` option which will use configured `:view` as the relation used by association (solnic)
18
+ * `:combine_keys` option which overriddes default combine keys that are based on join keys (solnic)
17
19
  * `Schema#primary_key_name` and `Schema#primary_key_names` are now part of core schema API (solnic)
18
20
  * `Schema#to_ast` which returns an AST representation of a relation schema (flash-gordon)
19
21
  * Plugin system supports schema plugins (flash-gordon)
@@ -1,6 +1,9 @@
1
1
  require 'rom/registry'
2
2
 
3
3
  module ROM
4
+ # Association set contains a registry with associations defined
5
+ # in schema DSL
6
+ #
4
7
  # @api public
5
8
  class AssociationSet < ROM::Registry
6
9
  # @api private
@@ -32,6 +32,11 @@ module ROM
32
32
  # @return [ROM::SQL::Relation::Name] the target relation
33
33
  option :target, reader: true
34
34
 
35
+ # Create an association object
36
+ #
37
+ # @param [Definition] definition The association definition object
38
+ # @param [RelationRegistry] relations The relation registry
39
+ #
35
40
  # @api public
36
41
  def self.new(definition, relations)
37
42
  super(
@@ -42,62 +47,116 @@ module ROM
42
47
  )
43
48
  end
44
49
 
50
+ # Return if an association has an alias
51
+ #
52
+ # @return [Boolean]
53
+ #
45
54
  # @api public
46
55
  def aliased?
47
56
  definition.aliased?
48
57
  end
49
58
 
59
+ # Return association alias
60
+ #
61
+ # @return [Symbol]
62
+ #
50
63
  # @api public
51
64
  def as
52
65
  definition.as
53
66
  end
54
67
 
68
+ # Return association canonical name
69
+ #
70
+ # @return [Symbol]
71
+ #
55
72
  # @api public
56
73
  def name
57
74
  definition.name
58
75
  end
59
76
 
77
+ # Return the name of a custom relation view that should be use to
78
+ # extend or override default association view
79
+ #
80
+ # @return [Symbol]
81
+ #
60
82
  # @api public
61
83
  def view
62
84
  definition.view
63
85
  end
64
86
 
87
+ # Return association foreign key name
88
+ #
89
+ # @return [Symbol]
90
+ #
65
91
  # @api public
66
92
  def foreign_key
67
93
  definition.foreign_key
68
94
  end
69
95
 
96
+ # Return result type
97
+ #
98
+ # This can be either :one or :many
99
+ #
100
+ # @return [Symbol]
101
+ #
70
102
  # @api public
71
103
  def result
72
104
  definition.result
73
105
  end
74
106
 
107
+ # Return if a custom view should override default association view
108
+ #
109
+ # @return [Boolean]
110
+ #
75
111
  # @api public
76
112
  def override?
77
113
  definition.override
78
114
  end
79
115
 
116
+ # Return the name of a key in tuples under which loaded association data are returned
117
+ #
118
+ # @return [Symbol]
119
+ #
80
120
  # @api public
81
121
  def key
82
122
  as || name
83
123
  end
84
124
 
125
+ # Applies custom view to the default association view
126
+ #
127
+ # @return [Relation]
128
+ #
85
129
  # @api protected
86
130
  def apply_view(schema, relation)
87
131
  view_rel = relation.public_send(view)
88
132
  schema.merge(view_rel.schema).uniq(&:key).(view_rel)
89
133
  end
90
134
 
135
+ # Return combine keys hash
136
+ #
137
+ # Combine keys are used for merging associated data together, typically these
138
+ # are the same as fk<=>pk mapping
139
+ #
140
+ # @return [Hash<Symbol=>Symbol>]
141
+ #
91
142
  # @api public
92
143
  def combine_keys
93
- { source_key => target_key }
144
+ definition.combine_keys || { source_key => target_key }
94
145
  end
95
146
 
147
+ # Return names of source PKs and target FKs
148
+ #
149
+ # @return [Array<Symbol>]
150
+ #
96
151
  # @api private
97
152
  def join_key_map
98
153
  join_keys.to_a.flatten(1).map(&:key)
99
154
  end
100
155
 
156
+ # Return target relation configured as a combine node
157
+ #
158
+ # @return [Relation]
159
+ #
101
160
  # @api private
102
161
  def node
103
162
  target.with(
@@ -106,6 +165,10 @@ module ROM
106
165
  )
107
166
  end
108
167
 
168
+ # Return target relation as a wrap node
169
+ #
170
+ # @return [Relation]
171
+ #
109
172
  # @api private
110
173
  def wrap
111
174
  target.with(
@@ -115,6 +178,10 @@ module ROM
115
178
  )
116
179
  end
117
180
 
181
+ # Prepare association's target relation for composition
182
+ #
183
+ # @return [Relation]
184
+ #
118
185
  # @api private
119
186
  def prepare(target)
120
187
  if override?
@@ -124,6 +191,10 @@ module ROM
124
191
  end
125
192
  end
126
193
 
194
+ # Return if this association's source relation is the same as the target
195
+ #
196
+ # @return [Boolean]
197
+ #
127
198
  # @api private
128
199
  def self_ref?
129
200
  source.name.dataset == target.name.dataset
@@ -55,16 +55,20 @@ module ROM
55
55
  # @return [TrueClass,FalseClass] Whether custom view should override default one or not
56
56
  option :override, optional: true, default: -> { false }
57
57
 
58
+ # @!attribute [r] combine_keys
59
+ # @return [Hash<Symbol=>Symbol>] Override inferred combine keys
60
+ option :combine_keys, optional: true
61
+
58
62
  # Instantiate a new association definition
59
63
  #
60
64
  # @param [Symbol] source The name of the source dataset
61
65
  # @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
66
+ # @param [Hash] opts The option hash
67
+ # @option opts [Symbol] :as The name of the association (defaults to target)
68
+ # @option opts [Symbol] :relation The name of the target relation (defaults to target)
69
+ # @option opts [Symbol] :foreign_key The name of a custom foreign key
70
+ # @option opts [Symbol] :view The name of a custom relation view on the target's relation side
71
+ # @option opts [TrueClass,FalseClass] :override Whether provided :view should override association's default view
68
72
  #
69
73
  # @api public
70
74
  def self.new(source, target, opts = EMPTY_HASH)
@@ -96,16 +100,28 @@ module ROM
96
100
  options
97
101
  end
98
102
 
103
+ # Return true if association's default relation view should be overridden by a custom one
104
+ #
105
+ # @return [Boolean]
106
+ #
99
107
  # @api public
100
108
  def override?
101
109
  options[:override].equal?(true)
102
110
  end
103
111
 
112
+ # Return true if association is aliased
113
+ #
114
+ # @return [Boolean]
115
+ #
104
116
  # @api public
105
117
  def aliased?
106
118
  options.key?(:as)
107
119
  end
108
120
 
121
+ # Return association class for a given definition object
122
+ #
123
+ # @return [Class]
124
+ #
109
125
  # @api public
110
126
  def type
111
127
  Dry::Core::Inflector.demodulize(self.class.name).to_sym
@@ -4,9 +4,12 @@ require 'rom/associations/definitions/abstract'
4
4
  module ROM
5
5
  module Associations
6
6
  module Definitions
7
+ # @api private
7
8
  class ManyToMany < Abstract
8
9
  result :many
9
10
 
11
+ # @!attribute [r] through
12
+ # @return [ThroughIdentifier] The name of the "through" relation
10
13
  option :through, reader: true
11
14
 
12
15
  # @api private
@@ -3,6 +3,7 @@ require 'rom/associations/definitions/abstract'
3
3
  module ROM
4
4
  module Associations
5
5
  module Definitions
6
+ # @api private
6
7
  class ManyToOne < Abstract
7
8
  result :one
8
9
  end
@@ -3,6 +3,7 @@ require 'rom/associations/definitions/abstract'
3
3
  module ROM
4
4
  module Associations
5
5
  module Definitions
6
+ # @api private
6
7
  class OneToMany < Abstract
7
8
  result :many
8
9
  end
@@ -3,6 +3,7 @@ require 'rom/associations/definitions/abstract'
3
3
  module ROM
4
4
  module Associations
5
5
  module Definitions
6
+ # @api private
6
7
  class OneToOne < Abstract
7
8
  result :one
8
9
  end
@@ -3,6 +3,7 @@ require 'rom/associations/definitions/abstract'
3
3
  module ROM
4
4
  module Associations
5
5
  module Definitions
6
+ # @api private
6
7
  class OneToOneThrough < ManyToMany
7
8
  result :one
8
9
  end
@@ -3,7 +3,12 @@ require 'rom/associations/abstract'
3
3
 
4
4
  module ROM
5
5
  module Associations
6
+ # Abstract many-to-many association type
7
+ #
8
+ # @api public
6
9
  class ManyToMany < Abstract
10
+ # @!attribute [r] join_relation
11
+ # @return [Relation] Intermediate join relation
7
12
  attr_reader :join_relation
8
13
 
9
14
  # @api private
@@ -12,26 +17,49 @@ module ROM
12
17
  @join_relation = relations[through]
13
18
  end
14
19
 
20
+ # Adapters should implement this method
21
+ #
22
+ # @abstract
23
+ #
15
24
  # @api public
16
25
  def call(*)
17
26
  raise NotImplementedError
18
27
  end
19
28
 
29
+ # Return configured or inferred FK name
30
+ #
31
+ # @return [Symbol]
32
+ #
20
33
  # @api public
21
34
  def foreign_key
22
35
  definition.foreign_key || join_relation.foreign_key(source.name)
23
36
  end
24
37
 
38
+ # Return join-relation name
39
+ #
40
+ # @return [Symbol]
41
+ #
25
42
  # @api public
26
43
  def through
27
44
  definition.through
28
45
  end
29
46
 
47
+ # Return parent's relation combine keys
48
+ #
49
+ # @return [Hash<Symbol=>Symbol>]
50
+ #
30
51
  # @api private
31
52
  def parent_combine_keys
32
53
  target.associations[source.name].combine_keys.to_a.flatten(1)
33
54
  end
34
55
 
56
+ # Associate child tuples with the provided parent
57
+ #
58
+ # @param [Array<Hash>] children An array with child tuples
59
+ # @param [Array,Hash] parent An array with parent tuples or a single tuple
60
+ #
61
+ # @return [Array<Hash>]
62
+ #
35
63
  # @api private
36
64
  def associate(children, parent)
37
65
  ((spk, sfk), (tfk, tpk)) = join_key_map
@@ -48,16 +76,28 @@ module ROM
48
76
 
49
77
  protected
50
78
 
79
+ # Primary key name on the source side
80
+ #
81
+ # @return [Symbol]
82
+ #
51
83
  # @api protected
52
84
  def source_key
53
85
  source.primary_key
54
86
  end
55
87
 
88
+ # Foreign key name on the target side
89
+ #
90
+ # @return [Symbol]
91
+ #
56
92
  # @api protected
57
93
  def target_key
58
94
  foreign_key
59
95
  end
60
96
 
97
+ # Return association for many-to-many-through
98
+ #
99
+ # @return [Association]
100
+ #
61
101
  # @api protected
62
102
  def join_assoc
63
103
  if join_relation.associations.key?(through.assoc_name)
@@ -67,6 +107,10 @@ module ROM
67
107
  end
68
108
  end
69
109
 
110
+ # Return a [pk, fk] mapping for source/target relations
111
+ #
112
+ # @return [Array<Symbol>]
113
+ #
70
114
  # @api protected
71
115
  def join_key_map
72
116
  left = super
@@ -2,17 +2,35 @@ require 'rom/associations/abstract'
2
2
 
3
3
  module ROM
4
4
  module Associations
5
+ # Abstract many-to-one association type
6
+ #
7
+ # @api public
5
8
  class ManyToOne < Abstract
9
+ # Adapters must implement this method
10
+ #
11
+ # @abstract
12
+ #
6
13
  # @api public
7
14
  def call(*)
8
15
  raise NotImplementedError
9
16
  end
10
17
 
18
+ # Return configured or inferred FK name
19
+ #
20
+ # @return [Symbol]
21
+ #
11
22
  # @api public
12
23
  def foreign_key
13
24
  definition.foreign_key || source.foreign_key(target.name)
14
25
  end
15
26
 
27
+ # Associate child with a parent
28
+ #
29
+ # @param [Hash] child The child tuple
30
+ # @param [Hash] parent The parent tuple
31
+ #
32
+ # @return [Hash]
33
+ #
16
34
  # @api private
17
35
  def associate(child, parent)
18
36
  fk, pk = join_key_map
@@ -21,11 +39,19 @@ module ROM
21
39
 
22
40
  protected
23
41
 
42
+ # Return foreign key on the source side
43
+ #
44
+ # @return [Symbol]
45
+ #
24
46
  # @api protected
25
47
  def source_key
26
48
  foreign_key
27
49
  end
28
50
 
51
+ # Return primary key on the target side
52
+ #
53
+ # @return [Symbol]
54
+ #
29
55
  # @api protected
30
56
  def target_key
31
57
  target.schema.primary_key_name