rom 2.0.2 → 3.0.0

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 (156) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +4 -7
  3. data/.yardopts +2 -0
  4. data/CHANGELOG.md +35 -1
  5. data/Gemfile +17 -2
  6. data/Rakefile +7 -2
  7. data/lib/rom/array_dataset.rb +44 -0
  8. data/lib/rom/association_set.rb +11 -5
  9. data/lib/rom/auto_curry.rb +55 -0
  10. data/lib/rom/command.rb +331 -47
  11. data/lib/rom/command_registry.rb +7 -18
  12. data/lib/rom/commands/class_interface.rb +120 -6
  13. data/lib/rom/commands/composite.rb +0 -1
  14. data/lib/rom/commands/graph.rb +7 -15
  15. data/lib/rom/commands/lazy/update.rb +1 -1
  16. data/lib/rom/configuration.rb +2 -0
  17. data/lib/rom/configuration_dsl/command.rb +6 -8
  18. data/lib/rom/configuration_dsl/mapper.rb +2 -3
  19. data/lib/rom/configuration_dsl/mapper_dsl.rb +0 -1
  20. data/lib/rom/configuration_dsl/relation.rb +4 -4
  21. data/lib/rom/configuration_dsl.rb +0 -4
  22. data/lib/rom/constants.rb +7 -1
  23. data/lib/rom/container.rb +11 -17
  24. data/lib/rom/create_container.rb +0 -2
  25. data/lib/rom/data_proxy.rb +94 -0
  26. data/lib/rom/enumerable_dataset.rb +68 -0
  27. data/lib/rom/gateway.rb +74 -32
  28. data/lib/rom/global/plugin_dsl.rb +0 -2
  29. data/lib/rom/global.rb +0 -2
  30. data/lib/rom/initializer.rb +26 -0
  31. data/lib/rom/lint/gateway.rb +17 -0
  32. data/lib/rom/mapper_registry.rb +1 -1
  33. data/lib/rom/memory/commands.rb +0 -2
  34. data/lib/rom/memory/dataset.rb +1 -2
  35. data/lib/rom/memory/relation.rb +14 -1
  36. data/lib/rom/memory/schema.rb +13 -0
  37. data/lib/rom/plugin_registry.rb +1 -1
  38. data/lib/rom/plugins/command/schema.rb +2 -2
  39. data/lib/rom/plugins/configuration/configuration_dsl.rb +6 -2
  40. data/lib/rom/plugins/relation/key_inference.rb +4 -2
  41. data/lib/rom/plugins/relation/registry_reader.rb +5 -1
  42. data/lib/rom/registry.rb +50 -0
  43. data/lib/rom/relation/class_interface.rb +142 -30
  44. data/lib/rom/relation/curried.rb +15 -15
  45. data/lib/rom/relation/view_dsl.rb +31 -0
  46. data/lib/rom/relation.rb +101 -41
  47. data/lib/rom/schema/attribute.rb +367 -0
  48. data/lib/rom/schema/dsl.rb +14 -10
  49. data/lib/rom/schema.rb +337 -19
  50. data/lib/rom/setup/auto_registration.rb +20 -17
  51. data/lib/rom/setup/auto_registration_strategies/base.rb +8 -3
  52. data/lib/rom/setup/auto_registration_strategies/custom_namespace.rb +4 -3
  53. data/lib/rom/setup/auto_registration_strategies/no_namespace.rb +5 -4
  54. data/lib/rom/setup/auto_registration_strategies/with_namespace.rb +3 -3
  55. data/lib/rom/setup/finalize/finalize_commands.rb +1 -1
  56. data/lib/rom/setup/finalize/finalize_mappers.rb +1 -1
  57. data/lib/rom/setup/finalize/finalize_relations.rb +4 -2
  58. data/lib/rom/setup/finalize.rb +1 -1
  59. data/lib/rom/transaction.rb +24 -0
  60. data/lib/rom/types.rb +9 -1
  61. data/lib/rom/version.rb +1 -1
  62. data/lib/rom.rb +4 -8
  63. data/rom.gemspec +5 -4
  64. data/spec/integration/command_registry_spec.rb +1 -14
  65. data/spec/integration/commands/create_spec.rb +5 -25
  66. data/spec/integration/commands/delete_spec.rb +1 -1
  67. data/spec/integration/commands/error_handling_spec.rb +1 -1
  68. data/spec/integration/commands/graph_spec.rb +20 -14
  69. data/spec/integration/commands/update_spec.rb +4 -27
  70. data/spec/integration/commands_spec.rb +1 -1
  71. data/spec/integration/{repositories → gateways}/extending_relations_spec.rb +1 -1
  72. data/spec/integration/{repositories → gateways}/setting_logger_spec.rb +2 -2
  73. data/spec/integration/mappers/combine_spec.rb +1 -1
  74. data/spec/integration/mappers/deep_embedded_spec.rb +1 -1
  75. data/spec/integration/mappers/definition_dsl_spec.rb +1 -1
  76. data/spec/integration/mappers/embedded_spec.rb +1 -1
  77. data/spec/integration/mappers/exclude_spec.rb +1 -1
  78. data/spec/integration/mappers/fold_spec.rb +1 -1
  79. data/spec/integration/mappers/group_spec.rb +1 -1
  80. data/spec/integration/mappers/overwrite_attributes_value_spec.rb +1 -1
  81. data/spec/integration/mappers/prefix_separator_spec.rb +1 -1
  82. data/spec/integration/mappers/prefix_spec.rb +1 -1
  83. data/spec/integration/mappers/prefixing_attributes_spec.rb +1 -1
  84. data/spec/integration/mappers/registering_custom_mappers_spec.rb +1 -1
  85. data/spec/integration/mappers/renaming_attributes_spec.rb +1 -1
  86. data/spec/integration/mappers/reusing_mappers_spec.rb +1 -1
  87. data/spec/integration/mappers/step_spec.rb +1 -1
  88. data/spec/integration/mappers/symbolizing_attributes_spec.rb +1 -1
  89. data/spec/integration/mappers/unfold_spec.rb +1 -1
  90. data/spec/integration/mappers/ungroup_spec.rb +2 -2
  91. data/spec/integration/mappers/unwrap_spec.rb +2 -2
  92. data/spec/integration/mappers/wrap_spec.rb +1 -1
  93. data/spec/integration/memory/commands/create_spec.rb +1 -1
  94. data/spec/integration/memory/commands/delete_spec.rb +1 -1
  95. data/spec/integration/memory/commands/update_spec.rb +1 -1
  96. data/spec/integration/multi_env_spec.rb +1 -1
  97. data/spec/integration/multi_repo_spec.rb +1 -1
  98. data/spec/integration/relations/default_dataset_spec.rb +1 -1
  99. data/spec/integration/relations/reading_spec.rb +1 -1
  100. data/spec/integration/relations/registry_dsl_spec.rb +1 -1
  101. data/spec/integration/setup_spec.rb +10 -4
  102. data/spec/shared/command_graph.rb +8 -4
  103. data/spec/shared/enumerable_dataset.rb +1 -1
  104. data/spec/spec_helper.rb +7 -9
  105. data/spec/support/schema.rb +14 -0
  106. data/spec/unit/rom/array_dataset_spec.rb +59 -0
  107. data/spec/unit/rom/association_set_spec.rb +4 -0
  108. data/spec/unit/rom/auto_curry_spec.rb +63 -0
  109. data/spec/unit/rom/commands/graph_spec.rb +12 -11
  110. data/spec/unit/rom/commands/lazy_spec.rb +8 -5
  111. data/spec/unit/rom/commands/pre_and_post_processors_spec.rb +336 -0
  112. data/spec/unit/rom/commands/result_spec.rb +1 -1
  113. data/spec/unit/rom/commands_spec.rb +26 -3
  114. data/spec/unit/rom/configuration_spec.rb +1 -1
  115. data/spec/unit/rom/container_spec.rb +15 -5
  116. data/spec/unit/rom/create_container_spec.rb +1 -1
  117. data/spec/unit/rom/enumerable_dataset_spec.rb +15 -0
  118. data/spec/unit/rom/gateway_spec.rb +1 -1
  119. data/spec/unit/rom/mapper_registry_spec.rb +1 -1
  120. data/spec/unit/rom/memory/commands_spec.rb +1 -1
  121. data/spec/unit/rom/memory/dataset_spec.rb +1 -1
  122. data/spec/unit/rom/memory/{repository_spec.rb → gateway_spec.rb} +1 -1
  123. data/spec/unit/rom/memory/inheritance_spec.rb +32 -0
  124. data/spec/unit/rom/memory/relation_spec.rb +15 -3
  125. data/spec/unit/rom/memory/storage_spec.rb +1 -1
  126. data/spec/unit/rom/plugin_spec.rb +1 -1
  127. data/spec/unit/rom/plugins/command/schema_spec.rb +5 -5
  128. data/spec/unit/rom/plugins/relation/key_inference_spec.rb +1 -1
  129. data/spec/unit/rom/registry_spec.rb +86 -0
  130. data/spec/unit/rom/relation/attribute_reader_spec.rb +17 -0
  131. data/spec/unit/rom/relation/call_spec.rb +51 -0
  132. data/spec/unit/rom/relation/composite_spec.rb +1 -1
  133. data/spec/unit/rom/relation/graph_spec.rb +1 -1
  134. data/spec/unit/rom/relation/lazy/combine_spec.rb +1 -1
  135. data/spec/unit/rom/relation/lazy_spec.rb +1 -1
  136. data/spec/unit/rom/relation/loaded_spec.rb +1 -1
  137. data/spec/unit/rom/relation/schema_spec.rb +50 -6
  138. data/spec/unit/rom/relation/view_spec.rb +122 -0
  139. data/spec/unit/rom/relation_spec.rb +20 -5
  140. data/spec/unit/rom/schema/accessing_attributes_spec.rb +52 -0
  141. data/spec/unit/rom/schema/append_spec.rb +17 -0
  142. data/spec/unit/rom/schema/exclude_spec.rb +15 -0
  143. data/spec/unit/rom/schema/finalize_spec.rb +59 -0
  144. data/spec/unit/rom/schema/key_predicate_spec.rb +15 -0
  145. data/spec/unit/rom/schema/merge_spec.rb +17 -0
  146. data/spec/unit/rom/schema/prefix_spec.rb +16 -0
  147. data/spec/unit/rom/schema/project_spec.rb +15 -0
  148. data/spec/unit/rom/schema/rename_spec.rb +22 -0
  149. data/spec/unit/rom/schema/type_spec.rb +49 -0
  150. data/spec/unit/rom/schema/uniq_spec.rb +21 -0
  151. data/spec/unit/rom/schema/wrap_spec.rb +17 -0
  152. data/spec/unit/rom/schema_spec.rb +2 -2
  153. metadata +79 -17
  154. data/lib/rom/plugins/relation/view/dsl.rb +0 -32
  155. data/lib/rom/plugins/relation/view.rb +0 -95
  156. data/spec/unit/rom/plugins/relation/view_spec.rb +0 -51
@@ -1,5 +1,5 @@
1
+ require 'rom/initializer'
1
2
  require 'rom/pipeline'
2
- require 'rom/support/options'
3
3
  require 'rom/commands/graph/class_interface'
4
4
 
5
5
  module ROM
@@ -8,35 +8,27 @@ module ROM
8
8
  #
9
9
  # @api private
10
10
  class Graph
11
+ extend Initializer
11
12
  include Dry::Equalizer(:root, :nodes)
12
13
 
13
14
  extend ClassInterface
14
15
 
15
- include Options
16
16
  include Pipeline
17
17
  include Pipeline::Proxy
18
18
 
19
19
  # @attr_reader [Command] root The root command
20
- attr_reader :root
20
+ param :root
21
21
 
22
22
  # @attr_reader [Array<Command>] nodes The child commands
23
- attr_reader :nodes
24
-
25
- # @attr_reader [Symbol] root's relation name
26
- attr_reader :name
23
+ param :nodes
27
24
 
28
25
  alias_method :left, :root
29
26
  alias_method :right, :nodes
30
27
 
31
- option :mappers, reader: true, default: proc { MapperRegistry.new }
28
+ # @attr_reader [Symbol] root's relation name
29
+ option :name, reader: true, default: -> g { g.root.name }
32
30
 
33
- # @api private
34
- def initialize(root, nodes, options = EMPTY_HASH)
35
- super
36
- @root = root
37
- @nodes = nodes
38
- @name = root.name
39
- end
31
+ option :mappers, reader: true, default: proc { MapperRegistry.new }
40
32
 
41
33
  # Calls root and all nodes with the result from root
42
34
  #
@@ -20,7 +20,7 @@ module ROM
20
20
 
21
21
  if input.is_a?(Array)
22
22
  input.map.with_index do |item, index|
23
- command_proc[command, last, item].call(item, *args[1..size-1])
23
+ command_proc[command, last, item].call(item, *args[1..size-1])
24
24
  end
25
25
  else
26
26
  command_proc[command, *(size > 1 ? [last, input] : [input])]
@@ -1,3 +1,5 @@
1
+ require 'forwardable'
2
+
1
3
  require 'rom/environment'
2
4
  require 'rom/setup'
3
5
  require 'rom/configuration_dsl'
@@ -1,7 +1,5 @@
1
- require 'rom/support/constants'
2
-
3
- require 'rom/support/inflector'
4
- require 'rom/support/class_builder'
1
+ require 'dry/core/inflector'
2
+ require 'dry/core/class_builder'
5
3
 
6
4
  module ROM
7
5
  module ConfigurationDSL
@@ -16,12 +14,12 @@ module ROM
16
14
  # @api private
17
15
  def self.build_class(name, relation, options = EMPTY_HASH, &block)
18
16
  type = options.fetch(:type) { name }
19
- command_type = Inflector.classify(type)
17
+ command_type = Dry::Core::Inflector.classify(type)
20
18
  adapter = options.fetch(:adapter)
21
19
  parent = ROM::Command.adapter_namespace(adapter).const_get(command_type)
22
20
  class_name = generate_class_name(adapter, command_type, relation)
23
21
 
24
- ClassBuilder.new(name: class_name, parent: parent).call do |klass|
22
+ Dry::Core::ClassBuilder.new(name: class_name, parent: parent).call do |klass|
25
23
  klass.register_as(name)
26
24
  klass.relation(relation)
27
25
  klass.class_eval(&block) if block
@@ -33,9 +31,9 @@ module ROM
33
31
  # @api private
34
32
  def self.generate_class_name(adapter, command_type, relation)
35
33
  pieces = ['ROM']
36
- pieces << Inflector.classify(adapter)
34
+ pieces << Dry::Core::Inflector.classify(adapter)
37
35
  pieces << 'Commands'
38
- pieces << "#{command_type}[#{Inflector.classify(relation)}s]"
36
+ pieces << "#{command_type}[#{Dry::Core::Inflector.classify(relation)}s]"
39
37
  pieces.join('::')
40
38
  end
41
39
  end
@@ -1,5 +1,4 @@
1
- require 'rom/support/constants'
2
- require 'rom/support/class_builder'
1
+ require 'dry/core/class_builder'
3
2
 
4
3
  module ROM
5
4
  module ConfigurationDSL
@@ -25,7 +24,7 @@ module ROM
25
24
  ROM::Mapper
26
25
  end
27
26
 
28
- ClassBuilder.new(name: class_name, parent: parent_class).call do |klass|
27
+ Dry::Core::ClassBuilder.new(name: class_name, parent: parent_class).call do |klass|
29
28
  klass.relation(name)
30
29
  klass.inherit_header(inherit_header)
31
30
 
@@ -1,4 +1,3 @@
1
- require 'rom/support/constants'
2
1
  require 'rom/configuration_dsl/mapper'
3
2
 
4
3
  module ROM
@@ -1,5 +1,5 @@
1
- require 'rom/support/constants'
2
- require 'rom/support/class_builder'
1
+ require 'dry/core/class_builder'
2
+ require 'dry/core/inflector'
3
3
 
4
4
  module ROM
5
5
  module ConfigurationDSL
@@ -13,10 +13,10 @@ module ROM
13
13
  #
14
14
  # @api private
15
15
  def self.build_class(name, options = EMPTY_HASH)
16
- class_name = "ROM::Relation[#{Inflector.camelize(name)}]"
16
+ class_name = "ROM::Relation[#{Dry::Core::Inflector.camelize(name)}]"
17
17
  adapter = options.fetch(:adapter)
18
18
 
19
- ClassBuilder.new(name: class_name, parent: ROM::Relation[adapter]).call do |klass|
19
+ Dry::Core::ClassBuilder.new(name: class_name, parent: ROM::Relation[adapter]).call do |klass|
20
20
  klass.gateway(options.fetch(:gateway, :default))
21
21
  klass.dataset(name)
22
22
  end
@@ -1,5 +1,3 @@
1
- require 'rom/support/constants'
2
-
3
1
  require 'rom/configuration_dsl/relation'
4
2
  require 'rom/configuration_dsl/mapper_dsl'
5
3
  require 'rom/configuration_dsl/command_dsl'
@@ -55,13 +53,11 @@ module ROM
55
53
  # setup.commands(:users) do
56
54
  # define(:create) do
57
55
  # input NewUserParams
58
- # validator NewUserValidator
59
56
  # result :one
60
57
  # end
61
58
  #
62
59
  # define(:update) do
63
60
  # input UserParams
64
- # validator UserValidator
65
61
  # result :many
66
62
  # end
67
63
  #
data/lib/rom/constants.rb CHANGED
@@ -22,8 +22,14 @@ module ROM
22
22
  UnsupportedRelationError = Class.new(StandardError)
23
23
  MissingAdapterIdentifierError = Class.new(StandardError)
24
24
 
25
+ MissingSchemaClassError = Class.new(StandardError) do
26
+ def initialize(klass)
27
+ super("#{klass.inspect} relation is missing schema_class")
28
+ end
29
+ end
30
+
25
31
  DuplicateConfigurationError = Class.new(StandardError)
26
- DuplicateContainerError = Class.new(StandardError)
32
+ DuplicateContainerError = Class.new(StandardError)
27
33
 
28
34
  InvalidOptionValueError = Class.new(StandardError)
29
35
  InvalidOptionKeyError = Class.new(StandardError)
data/lib/rom/container.rb CHANGED
@@ -1,7 +1,6 @@
1
1
  require 'rom/relation/loaded'
2
2
  require 'rom/commands/graph'
3
3
  require 'rom/commands/graph/builder'
4
- require 'rom/support/publisher'
5
4
 
6
5
  module ROM
7
6
  # ROM container is an isolated environment with no global state where all
@@ -12,14 +11,14 @@ module ROM
12
11
  #
13
12
  # There are 3 types of container setup:
14
13
  #
15
- # * in-line setup - a simple block-based configuration which allows configuring
14
+ # * Setup DSL - a simple block-based configuration which allows configuring
16
15
  # all components and gives you back a container instance. This type is suitable
17
16
  # for small scripts, or in some cases rake tasks
18
- # * multi-step setup - this type requires creating a configuration object,
17
+ # * Explicit setup - this type requires creating a configuration object,
19
18
  # registering component classes (ie relation classes) and passing the config
20
19
  # to container builder function. This type is suitable when your environment
21
20
  # is not typical and you need full control over component registration
22
- # * multi-step setup with auto-registration - same as multi-step but allows
21
+ # * Explicit setup with auto-registration - same as explicit setup but allows
23
22
  # you to configure auto-registration mechanism which will register component
24
23
  # classes for you, based on dir/file naming conventions. This is the most
25
24
  # common type of setup that's used by framework integrations
@@ -98,27 +97,22 @@ module ROM
98
97
  #
99
98
  # @api public
100
99
  class Container
101
- include ROM::Support::Publisher
102
100
  include Dry::Equalizer(:gateways, :relations, :mappers, :commands)
103
101
 
104
- # @return [Hash] configured gateways
105
- #
106
- # @api public
102
+ # @!attribute [r] gateways
103
+ # @return [Hash] A hash with configured gateways
107
104
  attr_reader :gateways
108
105
 
109
- # @return [RelationRegistry] relation registry
110
- #
111
- # @api public
106
+ # @!attribute [r] relations
107
+ # @return [RelationRegistry] The relation registry
112
108
  attr_reader :relations
113
109
 
114
- # @return [Registry] command registry
115
- #
116
- # @api public
110
+ # @!attribute [r] gateways
111
+ # @return [CommandRegistry] The command registry
117
112
  attr_reader :commands
118
113
 
119
- # @return [Registry] mapper registry
120
- #
121
- # @api public
114
+ # @!attribute [r] mappers
115
+ # @return [Hash] A hash with configured custom mappers
122
116
  attr_reader :mappers
123
117
 
124
118
  # @api private
@@ -5,8 +5,6 @@ require 'rom/setup/finalize'
5
5
 
6
6
  module ROM
7
7
  class CreateContainer
8
- include ROM::Support::Publisher
9
-
10
8
  attr_reader :container
11
9
 
12
10
  def initialize(environment, setup)
@@ -0,0 +1,94 @@
1
+ module ROM
2
+ # Helper module for dataset classes
3
+ #
4
+ # It provides a constructor accepting data, header and an optional row_proc.
5
+ # This module is used internally by EnumerableDataset and ArrayDataset.
6
+ #
7
+ # @private
8
+ module DataProxy
9
+ NON_FORWARDABLE = [
10
+ :each, :to_a, :to_ary, :kind_of?, :instance_of?, :is_a?
11
+ ].freeze
12
+
13
+ # Wrapped data array
14
+ #
15
+ # @return [Object] Data object for the iterator
16
+ #
17
+ # @api private
18
+ attr_reader :data
19
+
20
+ # @return [Proc] tuple processing proc
21
+ #
22
+ # @api private
23
+ attr_reader :row_proc
24
+
25
+ # Extends the class with `forward` DSL and Equalizer using `data` attribute
26
+ #
27
+ # @see ClassMethods#forward
28
+ #
29
+ # @api private
30
+ def self.included(klass)
31
+ klass.class_eval do
32
+ extend ClassMethods
33
+
34
+ include Dry::Equalizer(:data)
35
+
36
+ option :row_proc, reader: true, default: proc { |obj| obj.class.row_proc }
37
+ end
38
+ end
39
+
40
+ # Iterate over data using row_proc
41
+ #
42
+ # @return [Enumerator] if block is not given
43
+ #
44
+ # @api private
45
+ def each
46
+ return to_enum unless block_given?
47
+ data.each { |tuple| yield(row_proc[tuple]) }
48
+ end
49
+
50
+ module ClassMethods
51
+ # Default no-op tuple proc
52
+ #
53
+ # @return [Proc]
54
+ #
55
+ # @api private
56
+ def row_proc
57
+ -> tuple { tuple }
58
+ end
59
+
60
+ # Forward provided methods to the underlaying data object
61
+ #
62
+ # @example
63
+ #
64
+ # class MyDataset
65
+ # include DataProxy
66
+ #
67
+ # forward(:find_all, :map)
68
+ # end
69
+ #
70
+ # @return [undefined]
71
+ #
72
+ # @api public
73
+ def forward(*methods)
74
+ # FIXME: we should probably raise if one of the non-forwardable methods
75
+ # was provided
76
+ (methods - NON_FORWARDABLE).each do |method_name|
77
+ class_eval <<-RUBY, __FILE__, __LINE__ + 1
78
+ def #{method_name}(*args, &block)
79
+ response = data.public_send(#{method_name.inspect}, *args, &block)
80
+
81
+ if response.equal?(data)
82
+ self
83
+ elsif response.is_a?(data.class)
84
+ self.class.new(response)
85
+ else
86
+ response
87
+ end
88
+ end
89
+ RUBY
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,68 @@
1
+ require 'rom/initializer'
2
+ require 'rom/data_proxy'
3
+
4
+ module ROM
5
+ # A helper module that adds data-proxy behavior to an enumerable object
6
+ #
7
+ # This module is intended to be used by gateways
8
+ #
9
+ # Class that includes this module can define `row_proc` class method which
10
+ # must return a proc-like object which will be used to process each element
11
+ # in the enumerable
12
+ #
13
+ # @example
14
+ # class MyDataset
15
+ # include ROM::EnumerableDataset
16
+ #
17
+ # def self.row_proc
18
+ # -> tuple { tuple.each_with_object({}) { |(k,v), h| h[k.to_sym] = v } }
19
+ # end
20
+ # end
21
+ #
22
+ # ds = MyDataset.new([{ 'name' => 'Jane' }, [:name])
23
+ # ds.to_a # => { :name => 'Jane' }
24
+ #
25
+ # @api public
26
+ module EnumerableDataset
27
+ extend DataProxy::ClassMethods
28
+ include Enumerable
29
+
30
+ # Coerce a dataset to an array
31
+ #
32
+ # @return [Array]
33
+ #
34
+ # @api public
35
+ alias_method :to_ary, :to_a
36
+
37
+ # Included hook which extends a class with DataProxy behavior
38
+ #
39
+ # This module can also be included into other modules so we apply the
40
+ # extension only for classes
41
+ #
42
+ # @api private
43
+ def self.included(klass)
44
+ return unless klass.is_a?(Class)
45
+
46
+ klass.class_eval do
47
+ extend Initializer
48
+ include DataProxy
49
+
50
+ param :data
51
+ end
52
+ end
53
+
54
+ forward :take
55
+
56
+ [
57
+ :chunk, :collect, :collect_concat, :drop_while, :find_all, :flat_map,
58
+ :grep, :map, :reject, :select, :sort, :sort_by, :take_while
59
+ ].each do |method|
60
+ class_eval <<-RUBY, __FILE__, __LINE__ + 1
61
+ def #{method}(*args, &block)
62
+ return to_enum unless block
63
+ self.class.new(super(*args, &block), options)
64
+ end
65
+ RUBY
66
+ end
67
+ end
68
+ end
data/lib/rom/gateway.rb CHANGED
@@ -1,49 +1,65 @@
1
+ require 'dry/core/class_attributes'
2
+
3
+ require 'rom/transaction'
4
+
1
5
  module ROM
2
6
  # Abstract gateway class
3
7
  #
8
+ # Every adapter needs to inherit from this class and implement
9
+ # required interface
10
+ #
11
+ # @abstract
12
+ #
4
13
  # @api public
5
14
  class Gateway
6
- extend ClassMacros
15
+ extend Dry::Core::ClassAttributes
7
16
 
8
17
  defines :adapter
9
18
 
10
- # Return connection object
11
- #
12
- # @return [Object] type varies depending on the gateway
13
- #
14
- # @api public
19
+ # @!attribute [r] connection
20
+ # @return [Object] The gateway's connection object (type varies across adapters)
15
21
  attr_reader :connection
16
22
 
17
- # Setup a gateway
23
+ # Set up a gateway
18
24
  #
19
25
  # @overload setup(type, *args)
20
26
  # Sets up a single-gateway given a gateway type.
21
27
  # For custom gateways, create an instance and pass it directly.
22
28
  #
23
- # @param [Symbol] type
24
- # @param [Array] *args
29
+ # @example
30
+ # module SuperDB
31
+ # class Gateway < ROM::Gateway
32
+ # def initialize(options)
33
+ # end
34
+ # end
35
+ # end
25
36
  #
26
- # @overload setup(gateway)
27
- # @param [Gateway] gateway
37
+ # ROM.register_adapter(:super_db, SuperDB)
28
38
  #
29
- # @return [Gateway] a specific gateway subclass
39
+ # Gateway.setup(:super_db, some: 'options')
40
+ # # SuperDB::Gateway.new(some: 'options') is called
41
+ #
42
+ # @param [Symbol] type Registered gateway identifier
43
+ # @param [Array] args Additional gateway options
30
44
  #
31
- # @example
32
- # module SuperDB
33
- # class Gateway < ROM::Gateway
34
- # def initialize(options)
45
+ # @overload setup(gateway)
46
+ # Set up a gateway instance
47
+ #
48
+ # @example
49
+ # module SuperDB
50
+ # class Gateway < ROM::Gateway
51
+ # def initialize(options)
52
+ # end
35
53
  # end
36
54
  # end
37
- # end
38
55
  #
39
- # ROM.register_adapter(:super_db, SuperDB)
56
+ # ROM.register_adapter(:super_db, SuperDB)
40
57
  #
41
- # Gateway.setup(:super_db, some: 'options')
42
- # # SuperDB::Gateway.new(some: 'options') is called
58
+ # Gateway.setup(SuperDB::Gateway.new(some: 'options'))
59
+ #
60
+ # @param [Gateway] gateway
43
61
  #
44
- # # or alternatively
45
- # super_db = Gateway.setup(SuperDB::Gateway.new(some: 'options'))
46
- # Gateway.setup(super_db)
62
+ # @return [Gateway] a specific gateway subclass
47
63
  #
48
64
  # @api public
49
65
  def self.setup(gateway_or_scheme, *args)
@@ -72,7 +88,7 @@ module ROM
72
88
 
73
89
  # Get gateway subclass for a specific adapter
74
90
  #
75
- # @param [Symbol] type adapter identifier
91
+ # @param [Symbol] type Adapter identifier
76
92
  #
77
93
  # @return [Class]
78
94
  #
@@ -88,11 +104,7 @@ module ROM
88
104
  ROM.adapters.fetch(type)
89
105
  }
90
106
 
91
- if adapter.const_defined?(:Gateway)
92
- adapter.const_get(:Gateway)
93
- else
94
- adapter.const_get(:Repository)
95
- end
107
+ adapter.const_get(:Gateway)
96
108
  end
97
109
 
98
110
  # Returns the adapter, defined for the class
@@ -109,6 +121,10 @@ module ROM
109
121
 
110
122
  # A generic interface for setting up a logger
111
123
  #
124
+ # This is not a required interface, it's a no-op by default
125
+ #
126
+ # @abstract
127
+ #
112
128
  # @api public
113
129
  def use_logger(*)
114
130
  # noop
@@ -116,6 +132,11 @@ module ROM
116
132
 
117
133
  # A generic interface for returning default logger
118
134
  #
135
+ # Adapters should implement this method as handling loggers is different
136
+ # across adapters. This is a no-op by default and returns nil.
137
+ #
138
+ # @return [NilClass]
139
+ #
119
140
  # @api public
120
141
  def logger
121
142
  # noop
@@ -123,8 +144,10 @@ module ROM
123
144
 
124
145
  # Extension hook for adding gateway-specific behavior to a command class
125
146
  #
126
- # @param [Class] klass command class
127
- # @param [Object] _dataset dataset that will be used with this command class
147
+ # This simply returns back the class by default
148
+ #
149
+ # @param [Class] klass The command class
150
+ # @param [Object] _dataset The dataset that will be used with this command class
128
151
  #
129
152
  # @return [Class]
130
153
  #
@@ -137,7 +160,7 @@ module ROM
137
160
  #
138
161
  # Every gateway that supports schema inference should implement this method
139
162
  #
140
- # @return [Array] array with datasets and their names
163
+ # @return [Array] An array with dataset names
141
164
  #
142
165
  # @api private
143
166
  def schema
@@ -150,5 +173,24 @@ module ROM
150
173
  def disconnect
151
174
  # noop
152
175
  end
176
+
177
+ # Runs a block inside a transaction. The underlying transaction engine
178
+ # is adapter-specific
179
+ #
180
+ # @param [Hash] Transaction options
181
+ # @return The result of yielding the block or +nil+ if
182
+ # the transaction was rolled back
183
+ #
184
+ # @api public
185
+ def transaction(opts = EMPTY_HASH, &block)
186
+ transaction_runner(opts).run(opts, &block)
187
+ end
188
+
189
+ private
190
+
191
+ # @api private
192
+ def transaction_runner(_)
193
+ Transaction::NoOp
194
+ end
153
195
  end
154
196
  end
@@ -1,5 +1,3 @@
1
- require 'rom/support/constants'
2
-
3
1
  module ROM
4
2
  module Global
5
3
  # plugin registration DSL
data/lib/rom/global.rb CHANGED
@@ -1,7 +1,5 @@
1
- # -*- coding: utf-8 -*-
2
1
  require 'rom/plugin_registry'
3
2
  require 'rom/global/plugin_dsl'
4
- require 'rom/support/deprecations'
5
3
 
6
4
  module ROM
7
5
  # Globally accessible public interface exposed via ROM module
@@ -0,0 +1,26 @@
1
+ require 'dry-initializer'
2
+
3
+ module ROM
4
+
5
+ # @api private
6
+ module Initializer
7
+
8
+ # @api private
9
+ def self.extended(base)
10
+ base.extend(Dry::Initializer::Mixin)
11
+ base.include(InstanceMethods)
12
+ end
13
+
14
+ # @api private
15
+ module InstanceMethods
16
+ # Instance options
17
+ #
18
+ # @return [Hash]
19
+ #
20
+ # @api public
21
+ def options
22
+ @__options__
23
+ end
24
+ end
25
+ end
26
+ end
@@ -69,6 +69,23 @@ module ROM
69
69
  complain "#{gateway_instance} must respond to dataset?"
70
70
  end
71
71
 
72
+ # Lint: Ensure +gateway_instance+ supports +transaction+ interface
73
+ #
74
+ # @api public
75
+ def lint_transaction_support
76
+ result = gateway_instance.transaction { 1 }
77
+
78
+ if result != 1
79
+ complain "#{gateway_instance} must return the result of a transaction block"
80
+ end
81
+
82
+ gateway_instance.transaction do |t|
83
+ t.rollback!
84
+
85
+ complain "#{gateway_instance} must interrupt a transaction on rollback"
86
+ end
87
+ end
88
+
72
89
  private
73
90
 
74
91
  # Setup gateway instance
@@ -1,4 +1,4 @@
1
- require 'rom/support/registry'
1
+ require 'rom/registry'
2
2
 
3
3
  module ROM
4
4
  # @private
@@ -17,7 +17,6 @@ module ROM
17
17
  def execute(tuples)
18
18
  Array([tuples]).flatten.map { |tuple|
19
19
  attributes = input[tuple]
20
- validator.call(attributes)
21
20
  relation.insert(attributes.to_h)
22
21
  attributes
23
22
  }.to_a
@@ -34,7 +33,6 @@ module ROM
34
33
  # @see ROM::Commands::Update#execute
35
34
  def execute(params)
36
35
  attributes = input[params]
37
- validator.call(attributes)
38
36
  relation.map { |tuple| tuple.update(attributes.to_h) }
39
37
  end
40
38
  end