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
@@ -9,7 +9,6 @@ module ROM
9
9
  # Relation definition DSL
10
10
  #
11
11
  # @example
12
- #
13
12
  # setup.relation(:users) do
14
13
  # def names
15
14
  # project(:name)
@@ -29,7 +28,6 @@ module ROM
29
28
  # Command definition DSL
30
29
  #
31
30
  # @example
32
- #
33
31
  # setup.commands(:users) do
34
32
  # define(:create) do
35
33
  # input NewUserParams
data/lib/rom/constants.rb CHANGED
@@ -6,7 +6,9 @@ module ROM
6
6
 
7
7
  AdapterLoadError = Class.new(StandardError)
8
8
 
9
+ # Exception raised when a component is configured with an adapter that's not loaded
9
10
  class AdapterNotPresentError < StandardError
11
+ # @api private
10
12
  def initialize(adapter, component)
11
13
  super(
12
14
  "Failed to find #{component} class for #{adapter} adapter. " \
@@ -28,17 +30,22 @@ module ROM
28
30
  MissingAdapterIdentifierError = Class.new(StandardError)
29
31
  AttributeAlreadyDefinedError = Class.new(StandardError)
30
32
 
33
+ # Exception raised when a reserved keyword is used as a relation name
31
34
  class InvalidRelationName < StandardError
35
+ # @api private
32
36
  def initialize(relation)
33
37
  super("Relation name: #{relation} is a protected word, please use another relation name")
34
38
  end
35
39
  end
36
40
 
41
+ # Exception raised when an element inside a component registry is not found
37
42
  class ElementNotFoundError < KeyError
43
+ # @api private
38
44
  def initialize(key, registry)
39
45
  super(set_message(key, registry))
40
46
  end
41
47
 
48
+ # @api private
42
49
  def set_message(key, registry)
43
50
  "#{key.inspect} doesn't exist in #{registry.class.name} registry"
44
51
  end
@@ -47,18 +54,21 @@ module ROM
47
54
  MapperMissingError = Class.new(ElementNotFoundError)
48
55
 
49
56
  CommandNotFoundError = Class.new(ElementNotFoundError) do
57
+ # @api private
50
58
  def set_message(key, registry)
51
59
  "There is no :#{key} command for :#{registry.relation_name} relation"
52
60
  end
53
61
  end
54
62
 
55
63
  MissingSchemaClassError = Class.new(StandardError) do
64
+ # @api private
56
65
  def initialize(klass)
57
66
  super("#{klass.inspect} relation is missing schema_class")
58
67
  end
59
68
  end
60
69
 
61
70
  MissingSchemaError = Class.new(StandardError) do
71
+ # @api private
62
72
  def initialize(klass)
63
73
  super("#{klass.inspect} relation is missing schema definition")
64
74
  end
data/lib/rom/container.rb CHANGED
@@ -110,21 +110,37 @@ module ROM
110
110
  end
111
111
  end
112
112
 
113
+ # Return registered gateways
114
+ #
115
+ # @return [Hash<Symbol=>Gateway>]
116
+ #
113
117
  # @api public
114
118
  def gateways
115
119
  self[:gateways]
116
120
  end
117
121
 
122
+ # Return mapper registry for all relations
123
+ #
124
+ # @return [Hash<Symbol=>MapperRegistry]
125
+ #
118
126
  # @api public
119
127
  def mappers
120
128
  self[:mappers]
121
129
  end
122
130
 
131
+ # Return relation registry
132
+ #
133
+ # @return [RelationRegistry]
134
+ #
123
135
  # @api public
124
136
  def relations
125
137
  self[:relations]
126
138
  end
127
139
 
140
+ # Return command registry
141
+ #
142
+ # @return [Hash<Symbol=>CommandRegistry]
143
+ #
128
144
  # @api public
129
145
  def commands
130
146
  self[:commands]
@@ -4,15 +4,19 @@ require 'rom/setup'
4
4
  require 'rom/setup/finalize'
5
5
 
6
6
  module ROM
7
+ # @api private
7
8
  class CreateContainer
9
+ # @api private
8
10
  attr_reader :container
9
11
 
12
+ # @api private
10
13
  def initialize(environment, setup)
11
14
  @container = finalize(environment, setup)
12
15
  end
13
16
 
14
17
  private
15
18
 
19
+ # @api private
16
20
  def finalize(environment, setup)
17
21
  environment.configure do |config|
18
22
  environment.gateways.each_key do |key|
@@ -35,7 +39,9 @@ module ROM
35
39
  end
36
40
  end
37
41
 
42
+ # @api private
38
43
  class InlineCreateContainer < CreateContainer
44
+ # @api private
39
45
  def initialize(*args, &block)
40
46
  case args.first
41
47
  when Configuration
@@ -54,6 +60,7 @@ module ROM
54
60
  end
55
61
  end
56
62
 
63
+ # @api private
57
64
  def self.container(*args, &block)
58
65
  InlineCreateContainer.new(*args, &block).container
59
66
  end
@@ -4,13 +4,13 @@ require 'rom/gateway'
4
4
  module ROM
5
5
  # Core gateway configuration interface
6
6
  #
7
- # @api public
7
+ # @api private
8
8
  class Environment
9
9
  include Configurable
10
10
 
11
11
  attr_reader :gateways, :gateways_map
12
12
 
13
- # @api public
13
+ # @api private
14
14
  def initialize(*args)
15
15
  @gateways = {}
16
16
  @gateways_map = {}
@@ -20,6 +20,7 @@ module ROM
20
20
 
21
21
  private
22
22
 
23
+ # @api private
23
24
  def configure_gateways(*args)
24
25
  normalized_gateway_args = normalize_gateway_args(*args)
25
26
  normalized_gateways = normalize_gateways(normalized_gateway_args)
data/lib/rom/gateway.rb CHANGED
@@ -16,6 +16,20 @@ module ROM
16
16
  extend Dry::Core::ClassAttributes
17
17
  extend Notifications::Listener
18
18
 
19
+ # @!method self.adapter
20
+ # Get or set gateway's adapter identifier
21
+ #
22
+ # @overload adapter
23
+ # Return adapter identifier
24
+ # @return [Symbol]
25
+ #
26
+ # @overload gateway(adapter)
27
+ # @example
28
+ # class MyGateway < ROM::Gateway
29
+ # adapter :my_adapter
30
+ # end
31
+ #
32
+ # @param [Symbol] adapter The adapter identifier
19
33
  defines :adapter
20
34
 
21
35
  # @!attribute [r] connection
@@ -154,7 +168,8 @@ module ROM
154
168
  # Runs a block inside a transaction. The underlying transaction engine
155
169
  # is adapter-specific
156
170
  #
157
- # @param [Hash] Transaction options
171
+ # @param [Hash] opts Transaction options
172
+ #
158
173
  # @return The result of yielding the block or +nil+ if
159
174
  # the transaction was rolled back
160
175
  #
data/lib/rom/global.rb CHANGED
@@ -37,7 +37,7 @@ module ROM
37
37
  # register :publisher, Plugin::Publisher, type: :command
38
38
  # end
39
39
  #
40
- # @example
40
+ # @api public
41
41
  def plugins(*args, &block)
42
42
  PluginDSL.new(plugin_registry, *args, &block)
43
43
  end
@@ -38,7 +38,9 @@ module ROM
38
38
 
39
39
  # Register plugins for a specific adapter
40
40
  #
41
- # @param [Symbol] adapter type
41
+ # @param [Symbol] type The adapter identifier
42
+ #
43
+ # @api public
42
44
  def adapter(type, &block)
43
45
  self.class.new(registry, adapter: type, &block)
44
46
  end
@@ -1,29 +1,28 @@
1
1
  require 'dry-initializer'
2
2
 
3
3
  module ROM
4
-
5
4
  # @api private
6
5
  module Initializer
7
6
  # @api private
8
7
  module DefineWithHook
8
+ # @api private
9
9
  def param(*)
10
- super
11
-
12
- __define_with__
10
+ super.tap { __define_with__ }
13
11
  end
14
12
 
13
+ # @api private
15
14
  def option(*)
16
- super
17
-
18
- __define_with__ unless method_defined?(:with)
15
+ super.tap do
16
+ __define_with__ unless method_defined?(:with)
17
+ end
19
18
  end
20
19
 
20
+ # @api private
21
21
  def __define_with__
22
- seq_names = __initializer_mixin__.
23
- instance_method(:__initialize__).
24
- parameters.
25
- select { |type, _| type == :req }.
26
- map { |_, name| name }.
22
+ seq_names = dry_initializer.
23
+ definitions.
24
+ reject { |_, d| d.option }.
25
+ keys.
27
26
  join(', ')
28
27
 
29
28
  seq_names << ', ' unless seq_names.empty?
@@ -57,7 +56,20 @@ module ROM
57
56
  #
58
57
  # @api public
59
58
  def options
60
- @__options__
59
+ @__options__ ||= self.class.dry_initializer.definitions.values.each_with_object({}) do |item, obj|
60
+ obj[item.target] = instance_variable_get(item.ivar)
61
+ end
62
+ end
63
+
64
+ define_method(:class, Kernel.instance_method(:class))
65
+ define_method(:instance_variable_get, Kernel.instance_method(:instance_variable_get))
66
+
67
+ # This makes sure we memoize options before an object becomes frozen
68
+ #
69
+ # @api public
70
+ def freeze
71
+ options
72
+ super
61
73
  end
62
74
  end
63
75
  end
@@ -5,11 +5,14 @@ require 'rom/mapper_compiler'
5
5
  module ROM
6
6
  # @private
7
7
  class MapperRegistry < Registry
8
+ # @api private
8
9
  def self.element_not_found_error
9
10
  MapperMissingError
10
11
  end
11
12
 
12
- option :compiler, default: -> { MapperCompiler.new }
13
+ # @!attribute [r] compiler
14
+ # @return [MapperCompiler] A mapper compiler instance
15
+ option :compiler, default: -> { MapperCompiler.new(cache: cache) }
13
16
 
14
17
  # @see Registry
15
18
  # @api public
@@ -4,11 +4,17 @@ module ROM
4
4
  module Memory
5
5
  # In-memory dataset
6
6
  #
7
+ # This class can be used as a base class for other adapters.
8
+ #
7
9
  # @api public
8
10
  class Dataset
9
11
  include ArrayDataset
10
12
 
11
- # Join two datasets
13
+ # Join with other datasets
14
+ #
15
+ # @param [Array<Dataset>] args A list of dataset to join with
16
+ #
17
+ # @return [Dataset]
12
18
  #
13
19
  # @api public
14
20
  def join(*args)
@@ -28,9 +34,14 @@ module ROM
28
34
 
29
35
  # Restrict a dataset
30
36
  #
37
+ # @param [Hash] criteria A hash with conditions
38
+ #
39
+ # @return [Dataset]
40
+ #
31
41
  # @api public
32
42
  def restrict(criteria = nil)
33
43
  return find_all { |tuple| yield(tuple) } unless criteria
44
+
34
45
  find_all do |tuple|
35
46
  criteria.all? do |k, v|
36
47
  case v
@@ -44,6 +55,10 @@ module ROM
44
55
 
45
56
  # Project a dataset
46
57
  #
58
+ # @param [Array<Symbol>] names A list of attribute names
59
+ #
60
+ # @return [Dataset]
61
+ #
47
62
  # @api public
48
63
  def project(*names)
49
64
  map { |tuple| tuple.reject { |key| !names.include?(key) } }
@@ -51,12 +66,14 @@ module ROM
51
66
 
52
67
  # Sort a dataset
53
68
  #
54
- # @param [Array<Symbol>] names
69
+ # @param [Array<Symbol>] fields
55
70
  # Names of fields to order tuples by
56
71
  #
57
72
  # @option [Boolean] :nils_first (false)
58
73
  # Whether `nil` values should be placed before others
59
74
  #
75
+ # @return [Dataset]
76
+ #
60
77
  # @api public
61
78
  def order(*fields)
62
79
  nils_first = fields.pop[:nils_first] if fields.last.is_a?(Hash)
@@ -70,7 +87,11 @@ module ROM
70
87
 
71
88
  # Insert tuple into a dataset
72
89
  #
90
+ # @param [Hash] tuple A new tuple for insertion
91
+ #
73
92
  # @api public
93
+ #
94
+ # @return [Dataset]
74
95
  def insert(tuple)
75
96
  data << tuple
76
97
  self
@@ -79,6 +100,10 @@ module ROM
79
100
 
80
101
  # Delete tuples from a dataset
81
102
  #
103
+ # @param [Hash] tuple A new tuple for deletion
104
+ #
105
+ # @return [Dataset]
106
+ #
82
107
  # @api public
83
108
  def delete(tuple)
84
109
  data.delete(tuple)
@@ -88,6 +113,8 @@ module ROM
88
113
  private
89
114
 
90
115
  # Compares two values, that are either comparable, or can be nils
116
+ #
117
+ # @api private
91
118
  def __compare__(a, b, nils_first)
92
119
  return a <=> b unless a.nil? ^ b.nil?
93
120
  (nils_first ^ b.nil?) ? -1 : 1
@@ -3,6 +3,9 @@ require 'rom/memory/associations'
3
3
 
4
4
  module ROM
5
5
  module Memory
6
+ # Specialized schema for memory adapter
7
+ #
8
+ # @api public
6
9
  class Schema < ROM::Schema
7
10
  # @see Schema#call
8
11
  # @api public
@@ -10,6 +13,10 @@ module ROM
10
13
  relation.new(relation.dataset.project(*map(&:name)), schema: self)
11
14
  end
12
15
 
16
+ # Internal hook used during setup process
17
+ #
18
+ # @see Schema#finalize_associations!
19
+ #
13
20
  # @api private
14
21
  def finalize_associations!(relations:)
15
22
  super do
@@ -35,7 +35,7 @@ module ROM
35
35
 
36
36
  # Apply this plugin to the provided class
37
37
  #
38
- # @param [Mixed] base
38
+ # @param [Mixed] _base
39
39
  #
40
40
  # @api private
41
41
  def apply_to(_base)
@@ -137,7 +137,7 @@ module ROM
137
137
  #
138
138
  # @param [Symbol] name The name of the environment plugin
139
139
  #
140
- # @raises [UnknownPluginError] if no plugin is found with the given name
140
+ # @raise [UnknownPluginError] if no plugin is found with the given name
141
141
  #
142
142
  # @api public
143
143
  def fetch(name)
@@ -184,7 +184,7 @@ module ROM
184
184
  # @param [Symbol] name The name of the plugin
185
185
  # @param [Symbol] adapter_name (:default) The name of the adapter used
186
186
  #
187
- # @raises [UnknownPluginError] if no plugin is found with the given name
187
+ # @raise [UnknownPluginError] if no plugin is found with the given name
188
188
  #
189
189
  # @api public
190
190
  def fetch(name, adapter_name = :default)