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
@@ -2,17 +2,35 @@ require 'rom/associations/abstract'
2
2
 
3
3
  module ROM
4
4
  module Associations
5
+ # Abstract one-to-many association
6
+ #
7
+ # @api public
5
8
  class OneToMany < 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 || target.foreign_key(source.name)
14
25
  end
15
26
 
27
+ # Associate child tuple 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
  pk, fk = join_key_map
@@ -21,11 +39,19 @@ module ROM
21
39
 
22
40
  protected
23
41
 
42
+ # Return primary key on the source side
43
+ #
44
+ # @return [Symbol]
45
+ #
24
46
  # @api protected
25
47
  def source_key
26
48
  source.schema.primary_key_name
27
49
  end
28
50
 
51
+ # Return foreign key name on the target side
52
+ #
53
+ # @return [Symbol]
54
+ #
29
55
  # @api protected
30
56
  def target_key
31
57
  foreign_key
@@ -2,6 +2,9 @@ require 'rom/associations/one_to_many'
2
2
 
3
3
  module ROM
4
4
  module Associations
5
+ # Abstract one-to-one association type
6
+ #
7
+ # @api public
5
8
  class OneToOne < OneToMany
6
9
  end
7
10
  end
@@ -2,6 +2,9 @@ require 'rom/associations/many_to_many'
2
2
 
3
3
  module ROM
4
4
  module Associations
5
+ # Abstract one-to-one-through association type
6
+ #
7
+ # @api public
5
8
  class OneToOneThrough < ManyToMany
6
9
  end
7
10
  end
data/lib/rom/attribute.rb CHANGED
@@ -20,7 +20,7 @@ module ROM
20
20
  extend Initializer
21
21
 
22
22
  # @!attribute [r] type
23
- # @return [Dry::Types::Definition, Dry::Types::Sum, Dry::Types::Constrained]
23
+ # @return [Dry::Types::Definition, Dry::Types::Sum, Dry::Types::Constrained] The attribute's type object
24
24
  param :type
25
25
 
26
26
  # @api private
@@ -336,7 +336,7 @@ module ROM
336
336
 
337
337
  # Check if the attribute type is equal to another
338
338
  #
339
- # @param [Dry::Type, Attribute]
339
+ # @param [Dry::Type, Attribute] other
340
340
  #
341
341
  # @return [TrueClass,FalseClass]
342
342
  #
@@ -1,4 +1,7 @@
1
1
  module ROM
2
+ # Relation extension which provides auto-currying of relation view methods
3
+ #
4
+ # @api private
2
5
  module AutoCurry
3
6
  def self.extended(klass)
4
7
  klass.define_singleton_method(:method_added) do |name|
@@ -8,6 +11,7 @@ module ROM
8
11
  end
9
12
  end
10
13
 
14
+ # @api private
11
15
  def auto_curry_guard
12
16
  @__auto_curry_busy__ = true
13
17
  yield
@@ -15,14 +19,21 @@ module ROM
15
19
  @__auto_curry_busy__ = false
16
20
  end
17
21
 
22
+ # @api private
18
23
  def auto_curry_busy?
19
24
  @__auto_curry_busy__ ||= false
20
25
  end
21
26
 
27
+ # @api private
22
28
  def auto_curried_methods
23
29
  @__auto_curried_methods__ ||= Set.new
24
30
  end
25
31
 
32
+ # Auto-curry a method
33
+ #
34
+ # @param [Symbol] name The name of a method
35
+ #
36
+ # @api private
26
37
  def auto_curry(name, &block)
27
38
  arity = instance_method(name).arity
28
39
 
data/lib/rom/cache.rb CHANGED
@@ -1,27 +1,45 @@
1
1
  require 'concurrent/map'
2
2
 
3
3
  module ROM
4
+ # Thread-safe cache used by various rom components
5
+ #
4
6
  # @api private
5
7
  class Cache
6
8
  attr_reader :objects
7
9
 
10
+ # @api private
8
11
  class Namespaced
12
+ # @api private
9
13
  attr_reader :cache
10
14
 
15
+ # @api private
11
16
  attr_reader :namespace
12
17
 
18
+ # @api private
13
19
  def initialize(cache, namespace)
14
20
  @cache = cache
15
21
  @namespace = namespace.to_sym
16
22
  end
17
23
 
24
+ # @api private
18
25
  def [](key)
19
26
  cache[[namespace, key].hash]
20
27
  end
21
28
 
29
+ # @api private
22
30
  def fetch_or_store(*args, &block)
23
31
  cache.fetch_or_store([namespace, args.hash].hash, &block)
24
32
  end
33
+
34
+ # @api private
35
+ def size
36
+ cache.size
37
+ end
38
+
39
+ # @api private
40
+ def inspect
41
+ %(#<#{self.class} size=#{size}>)
42
+ end
25
43
  end
26
44
 
27
45
  # @api private
@@ -39,8 +57,19 @@ module ROM
39
57
  objects.fetch_or_store(args.hash, &block)
40
58
  end
41
59
 
60
+ # @api private
61
+ def size
62
+ objects.size
63
+ end
64
+
65
+ # @api private
42
66
  def namespaced(namespace)
43
67
  @namespaced[namespace] ||= Namespaced.new(objects, namespace)
44
68
  end
69
+
70
+ # @api private
71
+ def inspect
72
+ %(#<#{self.class} size=#{size} namespaced=#{@namespaced.inspect}>)
73
+ end
45
74
  end
46
75
  end
@@ -23,15 +23,15 @@ module ROM
23
23
  end
24
24
 
25
25
  # @!attribute [r] gateways
26
- # @return [ROM::Registry]
26
+ # @return [ROM::Registry] Gateways used for command extensions
27
27
  param :gateways
28
28
 
29
29
  # @!attribute [r] relations
30
- # @return [ROM::RelationRegistry]
30
+ # @return [ROM::RelationRegistry] Relations used with a given compiler
31
31
  param :relations
32
32
 
33
- # @!attribute [r] relations
34
- # @return [ROM::Registry]
33
+ # @!attribute [r] commands
34
+ # @return [ROM::Registry] Command registries with custom commands
35
35
  param :commands
36
36
 
37
37
  # @!attribute [r] notifications
@@ -15,19 +15,23 @@ module ROM
15
15
  # @api private
16
16
  param :elements
17
17
 
18
- # Name of the relation from which commands are under
19
- #
20
- # @return [String]
21
- #
22
- # @api private
18
+ # @!attribute [r] relation_name
19
+ # @return [Relation::Name] The name of a relation
23
20
  option :relation_name
24
21
 
22
+ # @!attribute [r] mappers
23
+ # @return [MapperRegistry] Optional mapper registry
25
24
  option :mappers, optional: true
26
25
 
26
+ # @!attribute [r] mapper
27
+ # @return [Object#call] Default mapper for processing command results
27
28
  option :mapper, optional: true
28
29
 
30
+ # @!attribute [r] compiler
31
+ # @return [CommandCompiler] A command compiler instance
29
32
  option :compiler, optional: true
30
33
 
34
+ # @api private
31
35
  def self.element_not_found_error
32
36
  CommandNotFoundError
33
37
  end
@@ -75,12 +75,12 @@ module ROM
75
75
 
76
76
  # Create a command class with a specific type
77
77
  #
78
- # @param [Symbol] command name
79
- # @param [Class] parent class
78
+ # @param [Symbol] name Command name
79
+ # @param [Class] type Command class
80
80
  #
81
- # @yield [Class] create class
81
+ # @yield [Class]
82
82
  #
83
- # @return [Class, Object] return result of the block if it was provided
83
+ # @return [Class, Object]
84
84
  #
85
85
  # @api public
86
86
  def create_class(name, type, &block)
@@ -105,8 +105,8 @@ module ROM
105
105
  # end
106
106
  #
107
107
  # @param [Symbol] plugin
108
- # @param [Hash] options
109
- # @option options [Symbol] :adapter (:default) first adapter to check for plugin
108
+ # @param [Hash] _options
109
+ # @option _options [Symbol] :adapter (:default) first adapter to check for plugin
110
110
  #
111
111
  # @api public
112
112
  def use(plugin, _options = EMPTY_HASH)
@@ -115,7 +115,7 @@ module ROM
115
115
 
116
116
  # Extend a command class with relation view methods
117
117
  #
118
- # @param [Relation]
118
+ # @param [Relation] relation
119
119
  #
120
120
  # @return [Class]
121
121
  #
@@ -1,19 +1,37 @@
1
1
  module ROM
2
2
  module Commands
3
3
  class Graph
4
+ # Evaluator for lazy commands which extracts values for commands from nested hashes
5
+ #
6
+ # @api private
4
7
  class InputEvaluator
5
8
  include Dry::Equalizer(:tuple_path, :excluded_keys)
6
9
 
10
+ # @!attribute [r] tuple_path
11
+ # @return [Array<Symbol>] A list of keys pointing to a value inside a hash
7
12
  attr_reader :tuple_path
8
13
 
14
+ # @!attribute [r] excluded_keys
15
+ # @return [Array<Symbol>] A list of keys that should be excluded
9
16
  attr_reader :excluded_keys
10
17
 
18
+ # @!attribute [r] exclude_proc
19
+ # @return [Array<Symbol>] A function that should determine which keys should be excluded
11
20
  attr_reader :exclude_proc
12
21
 
22
+ # Build an input evaluator
23
+ #
24
+ # @param [Array<Symbol>] tuple_path The tuple path
25
+ # @param [Array] nodes
26
+ #
27
+ # @return [InputEvaluator]
28
+ #
29
+ # @api private
13
30
  def self.build(tuple_path, nodes)
14
31
  new(tuple_path, extract_excluded_keys(nodes))
15
32
  end
16
33
 
34
+ # @api private
17
35
  def self.extract_excluded_keys(nodes)
18
36
  return unless nodes
19
37
 
@@ -24,19 +42,31 @@ module ROM
24
42
  .reject { |item| item.is_a?(Array) }
25
43
  end
26
44
 
45
+ # Return default exclude_proc
46
+ #
47
+ # @api private
27
48
  def self.exclude_proc(excluded_keys)
28
49
  -> input { input.reject { |k, _| excluded_keys.include?(k) } }
29
50
  end
30
51
 
52
+ # Initialize a new input evaluator
53
+ #
54
+ # @return [InputEvaluator]
55
+ #
56
+ # @api private
31
57
  def initialize(tuple_path, excluded_keys)
32
58
  @tuple_path = tuple_path
33
59
  @excluded_keys = excluded_keys
34
60
  @exclude_proc = self.class.exclude_proc(excluded_keys)
35
61
  end
36
62
 
37
- def call(*args)
38
- input, index = args
39
-
63
+ # Evaluate input hash
64
+ #
65
+ # @param [Hash] input The input hash
66
+ # @param [Integer] index Optional index
67
+ #
68
+ # @return [Hash]
69
+ def call(input, index = nil)
40
70
  value =
41
71
  begin
42
72
  if index
@@ -57,8 +57,12 @@ module ROM
57
57
  Composite.new(self, other)
58
58
  end
59
59
 
60
+ # Combine with other lazy commands
61
+ #
60
62
  # @see Abstract#combine
61
63
  #
64
+ # @return [Graph]
65
+ #
62
66
  # @api public
63
67
  def combine(*others)
64
68
  Graph.new(self, others)
@@ -1,7 +1,17 @@
1
1
  module ROM
2
2
  module Commands
3
3
  class Lazy
4
+ # Lazy command wrapper for create commands
5
+ #
6
+ # @api public
4
7
  class Create < Lazy
8
+ # Execute a command
9
+ #
10
+ # @see Command::Create#call
11
+ #
12
+ # @return [Hash,Array<Hash>]
13
+ #
14
+ # @api public
5
15
  def call(*args)
6
16
  first = args.first
7
17
  last = args.last
@@ -1,7 +1,17 @@
1
1
  module ROM
2
2
  module Commands
3
3
  class Lazy
4
+ # Lazy command wrapper for delete commands
5
+ #
6
+ # @api public
4
7
  class Delete < Lazy
8
+ # Execute a lazy delete command
9
+ #
10
+ # @see Commands::Delete#call
11
+ #
12
+ # @return [Hash, Array<Hash>]
13
+ #
14
+ # @api public
5
15
  def call(*args)
6
16
  first = args.first
7
17
  last = args.last
@@ -1,7 +1,17 @@
1
1
  module ROM
2
2
  module Commands
3
3
  class Lazy
4
+ # Lazy command wrapper for update commands
5
+ #
6
+ # @api public
4
7
  class Update < Lazy
8
+ # Execute a lazy update command
9
+ #
10
+ # @see Commands::Update#call
11
+ #
12
+ # @return [Hash, Array<Hash>]
13
+ #
14
+ # @api public
5
15
  def call(*args)
6
16
  first = args.first
7
17
  last = args.last
@@ -22,7 +22,17 @@ module ROM
22
22
 
23
23
  NoDefaultAdapterError = Class.new(StandardError)
24
24
 
25
- attr_reader :environment, :setup, :notifications
25
+ # @!attribute [r] environment
26
+ # @return [Environment] Environment object with gateways
27
+ attr_reader :environment
28
+
29
+ # @!attribute [r] setup
30
+ # @return [Setup] Setup object which collects component classes and plugins
31
+ attr_reader :setup
32
+
33
+ # @!attribute [r] notifications
34
+ # @return [Notifications] Notification bus instance
35
+ attr_reader :notifications
26
36
 
27
37
  def_delegators :@setup, :register_relation, :register_command, :register_mapper, :register_plugin,
28
38
  :command_classes, :mapper_classes,
@@ -30,7 +40,13 @@ module ROM
30
40
 
31
41
  def_delegators :@environment, :gateways, :gateways_map, :configure, :config
32
42
 
33
- # @api public
43
+ # Initialize a new configuration
44
+ #
45
+ # @see Environment#initialize
46
+ #
47
+ # @return [Configuration]
48
+ #
49
+ # @api private
34
50
  def initialize(*args, &block)
35
51
  @environment = Environment.new(*args)
36
52
  @notifications = Notifications.event_bus(:configuration)
@@ -38,13 +54,15 @@ module ROM
38
54
 
39
55
  use :mappers # enable mappers by default
40
56
 
41
- block.call(self) unless block.nil?
57
+ block.call(self) if block
42
58
  end
43
59
 
44
60
  # Apply a plugin to the configuration
45
61
  #
46
- # @param [Mixed] The plugin identifier, usually a Symbol
47
- # @param [Hash] Plugin options
62
+ # @param [Mixed] plugin The plugin identifier, usually a Symbol
63
+ # @param [Hash] options Plugin options
64
+ #
65
+ # @return [Configuration]
48
66
  #
49
67
  # @api public
50
68
  def use(plugin, options = {})
@@ -68,15 +86,6 @@ module ROM
68
86
  gateways.fetch(name)
69
87
  end
70
88
 
71
- # Returns gateway if method is a name of a registered gateway
72
- #
73
- # @return [Gateway]
74
- #
75
- # @api private
76
- def method_missing(name, *)
77
- gateways.fetch(name) { super }
78
- end
79
-
80
89
  # Hook for respond_to? used internally
81
90
  #
82
91
  # @api private
@@ -110,5 +119,16 @@ module ROM
110
119
  def default_adapter
111
120
  @default_adapter ||= adapter_for_gateway(default_gateway) || ROM.adapters.keys.first
112
121
  end
122
+
123
+ private
124
+
125
+ # Returns gateway if method is a name of a registered gateway
126
+ #
127
+ # @return [Gateway]
128
+ #
129
+ # @api private
130
+ def method_missing(name, *)
131
+ gateways.fetch(name) { super }
132
+ end
113
133
  end
114
134
  end