rom 2.0.2 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
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