rom 0.8.1 → 0.9.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +4 -0
  3. data/README.md +5 -1
  4. data/lib/rom.rb +35 -16
  5. data/lib/rom/command.rb +1 -9
  6. data/lib/rom/commands/graph/class_interface.rb +2 -2
  7. data/lib/rom/constants.rb +0 -6
  8. data/lib/rom/{env.rb → container.rb} +3 -3
  9. data/lib/rom/environment.rb +238 -0
  10. data/lib/rom/environment_plugin.rb +17 -0
  11. data/lib/rom/environment_plugins/auto_registration.rb +17 -0
  12. data/lib/rom/global.rb +0 -203
  13. data/lib/rom/mapper_registry.rb +2 -0
  14. data/lib/rom/pipeline.rb +2 -0
  15. data/lib/rom/plugin.rb +4 -18
  16. data/lib/rom/plugin_base.rb +31 -0
  17. data/lib/rom/plugin_registry.rb +54 -17
  18. data/lib/rom/relation.rb +54 -11
  19. data/lib/rom/relation/class_interface.rb +14 -21
  20. data/lib/rom/relation/curried.rb +36 -2
  21. data/lib/rom/relation/graph.rb +7 -0
  22. data/lib/rom/relation_registry.rb +4 -0
  23. data/lib/rom/setup.rb +9 -8
  24. data/lib/rom/setup/finalize.rb +5 -5
  25. data/lib/rom/version.rb +1 -1
  26. data/rom.gemspec +2 -0
  27. data/spec/integration/commands/create_spec.rb +1 -1
  28. data/spec/integration/commands/update_spec.rb +1 -1
  29. data/spec/integration/mappers/unwrap_spec.rb +1 -1
  30. data/spec/spec_helper.rb +2 -0
  31. data/spec/unit/rom/{env_spec.rb → container_spec.rb} +5 -5
  32. data/spec/unit/rom/plugin_spec.rb +0 -8
  33. data/spec/unit/rom/relation/composite_spec.rb +2 -2
  34. data/spec/unit/rom/relation/curried_spec.rb +53 -0
  35. data/spec/unit/rom/relation/graph_spec.rb +4 -0
  36. data/spec/unit/rom/relation/lazy/combine_spec.rb +6 -6
  37. data/spec/unit/rom/relation/lazy_spec.rb +4 -8
  38. data/spec/unit/rom/relation_spec.rb +0 -14
  39. data/spec/unit/rom/setup_spec.rb +1 -1
  40. metadata +52 -35
  41. data/lib/rom/header.rb +0 -193
  42. data/lib/rom/header/attribute.rb +0 -184
  43. data/lib/rom/mapper.rb +0 -103
  44. data/lib/rom/mapper/attribute_dsl.rb +0 -477
  45. data/lib/rom/mapper/dsl.rb +0 -119
  46. data/lib/rom/mapper/model_dsl.rb +0 -55
  47. data/lib/rom/model_builder.rb +0 -101
  48. data/lib/rom/processor.rb +0 -28
  49. data/lib/rom/processor/transproc.rb +0 -388
  50. data/lib/rom/relation/lazy.rb +0 -145
  51. data/lib/rom/support/array_dataset.rb +0 -41
  52. data/lib/rom/support/class_builder.rb +0 -44
  53. data/lib/rom/support/class_macros.rb +0 -56
  54. data/lib/rom/support/data_proxy.rb +0 -102
  55. data/lib/rom/support/deprecations.rb +0 -36
  56. data/lib/rom/support/enumerable_dataset.rb +0 -65
  57. data/lib/rom/support/inflector.rb +0 -73
  58. data/lib/rom/support/options.rb +0 -195
  59. data/lib/rom/support/registry.rb +0 -43
  60. data/spec/unit/rom/header_spec.rb +0 -102
  61. data/spec/unit/rom/mapper/dsl_spec.rb +0 -467
  62. data/spec/unit/rom/mapper_spec.rb +0 -84
  63. data/spec/unit/rom/model_builder_spec.rb +0 -46
  64. data/spec/unit/rom/processor/transproc_spec.rb +0 -448
  65. data/spec/unit/rom/support/array_dataset_spec.rb +0 -61
  66. data/spec/unit/rom/support/class_builder_spec.rb +0 -42
  67. data/spec/unit/rom/support/enumerable_dataset_spec.rb +0 -17
  68. data/spec/unit/rom/support/inflector_spec.rb +0 -89
  69. data/spec/unit/rom/support/options_spec.rb +0 -119
@@ -0,0 +1,17 @@
1
+ module ROM
2
+ module EnvironmentPlugins
3
+ # Automatically registers relations, mappers and commands as they are defined
4
+ #
5
+ # For now this plugin is always enabled
6
+ #
7
+ # @api public
8
+ module AutoRegistration
9
+ # @api private
10
+ def self.apply(environment)
11
+ ROM::Relation.on(:inherited) { |relation| environment.register_relation(relation) }
12
+ ROM::Command.on(:inherited) { |command| environment.register_command(command) }
13
+ ROM::Mapper.on(:inherited) { |mapper| environment.register_mapper(mapper) }
14
+ end
15
+ end
16
+ end
17
+ end
data/lib/rom/global.rb CHANGED
@@ -1,7 +1,4 @@
1
- require 'rom/setup'
2
- require 'rom/repository'
3
1
  require 'rom/plugin_registry'
4
-
5
2
  require 'rom/global/plugin_dsl'
6
3
 
7
4
  module ROM
@@ -16,7 +13,6 @@ module ROM
16
13
  super
17
14
 
18
15
  rom.instance_variable_set('@adapters', {})
19
- rom.instance_variable_set('@gateways', {})
20
16
  rom.instance_variable_set('@plugin_registry', PluginRegistry.new)
21
17
  end
22
18
 
@@ -27,13 +23,6 @@ module ROM
27
23
  # @api private
28
24
  attr_reader :adapters
29
25
 
30
- # An internal gateway => identifier map used by the setup
31
- #
32
- # @return [Hash]
33
- #
34
- # @api private
35
- attr_reader :gateways
36
-
37
26
  # An internal identifier => plugin map used by the setup
38
27
  #
39
28
  # @return [Hash]
@@ -41,137 +30,6 @@ module ROM
41
30
  # @api private
42
31
  attr_reader :plugin_registry
43
32
 
44
- # Setup object created during env setup phase
45
- #
46
- # This gets set to nil after setup is finalized
47
- #
48
- # @return [Setup]
49
- #
50
- # @api private
51
- attr_reader :boot
52
-
53
- # Return global default ROM environment configured by the setup
54
- #
55
- # @return [Env]
56
- #
57
- # @api public
58
- attr_reader :env
59
-
60
- # Starts the setup process for relations, mappers and commands.
61
- #
62
- # @overload setup(type, *args)
63
- # Sets up a single-gateway environment given a gateway type provided
64
- # under the ROM umbrella. For custom gateways, create an instance and
65
- # pass it directly.
66
- #
67
- # @param [Symbol] type
68
- # @param [Array] *args
69
- #
70
- # @overload setup(gateway)
71
- # @param [Gateway] gateway
72
- #
73
- # @overload setup(gateways)
74
- # Sets up multiple gateways.
75
- #
76
- # @param [Hash{Symbol=>Symbol,Array}] gateways
77
- #
78
- # @return [Setup] boot object
79
- #
80
- # @example
81
- # # Use the in-memory adapter shipped with ROM as the default gateway.
82
- # env = ROM.setup(:memory, 'memory://test')
83
- # # Use `rom-sql` with an in-memory sqlite database as default gateway.
84
- # ROM.setup(:sql, 'sqlite::memory')
85
- # # Registers a `default` and a `warehouse` gateway.
86
- # env = ROM.setup(
87
- # default: [:sql, 'sqlite::memory'],
88
- # warehouse: [:sql, 'postgres://localhost/warehouse']
89
- # )
90
- #
91
- # @example A full environment
92
- #
93
- # ROM.setup(:memory, 'memory://test')
94
- #
95
- # ROM.relation(:users) do
96
- # # ...
97
- # end
98
- #
99
- # ROM.mappers do
100
- # define(:users) do
101
- # # ...
102
- # end
103
- # end
104
- #
105
- # ROM.commands(:users) do
106
- # define(:create) do
107
- # # ...
108
- # end
109
- # end
110
- #
111
- # ROM.finalize # builds the env
112
- # ROM.env # returns the env registry
113
- #
114
- # @api public
115
- def setup(*args, &block)
116
- config = setup_config(*args)
117
- @boot = Setup.new(setup_gateways(config), adapters.keys.first)
118
-
119
- if block
120
- @boot.instance_exec(&block)
121
- @boot.finalize
122
- else
123
- @boot
124
- end
125
- end
126
-
127
- # Global relation setup DSL
128
- #
129
- # @example
130
- # ROM.setup(:memory)
131
- #
132
- # ROM.relation(:users) do
133
- # def by_name(name)
134
- # restrict(name: name)
135
- # end
136
- # end
137
- #
138
- # @api public
139
- def relation(*args, &block)
140
- boot.relation(*args, &block)
141
- end
142
-
143
- # Global commands setup DSL
144
- #
145
- # @example
146
- # ROM.setup(:memory)
147
- #
148
- # ROM.commands(:users) do
149
- # define(:create) do
150
- # # ..
151
- # end
152
- # end
153
- #
154
- # @api public
155
- def commands(*args, &block)
156
- boot.commands(*args, &block)
157
- end
158
-
159
- # Global mapper setup DSL
160
- #
161
- # @example
162
- # ROM.setup(:memory)
163
- #
164
- # ROM.mappers do
165
- # define(:uses) do
166
- # # ..
167
- # end
168
- # end
169
- #
170
- # @api public
171
- def mappers(*args, &block)
172
- boot.mappers(*args, &block)
173
- end
174
-
175
33
  # Global plugin setup DSL
176
34
  #
177
35
  # @example
@@ -184,24 +42,6 @@ module ROM
184
42
  PluginDSL.new(plugin_registry, *args, &block)
185
43
  end
186
44
 
187
- # Finalize the setup and store default global env under ROM.env
188
- #
189
- # @example
190
- # ROM.setup(:memory)
191
- # ROM.finalize # => ROM
192
- # ROM.boot # => nil
193
- # ROM.env # => the env
194
- #
195
- # @return [ROM]
196
- #
197
- # @api public
198
- def finalize
199
- @env = boot.finalize
200
- self
201
- ensure
202
- @boot = nil
203
- end
204
-
205
45
  # Register adapter namespace under a specified identifier
206
46
  #
207
47
  # @param [Symbol] identifier
@@ -214,48 +54,5 @@ module ROM
214
54
  adapters[identifier] = adapter
215
55
  self
216
56
  end
217
-
218
- # Relation subclass registration during setup phase
219
- #
220
- # @api private
221
- def register_relation(klass)
222
- boot.register_relation(klass) if boot
223
- end
224
-
225
- # Mapper subclass registration during setup phase
226
- #
227
- # @api private
228
- def register_mapper(klass)
229
- boot.register_mapper(klass) if boot
230
- end
231
-
232
- # Command subclass registration during setup phase
233
- #
234
- # @api private
235
- def register_command(klass)
236
- boot.register_command(klass) if boot
237
- end
238
-
239
- private
240
-
241
- # Helper method to handle single- or multi-repo setup options
242
- #
243
- # @api private
244
- def setup_config(*args)
245
- args.first.is_a?(Hash) ? args.first : { default: args }
246
- end
247
-
248
- # Build gateways using the setup interface
249
- #
250
- # @api private
251
- def setup_gateways(config)
252
- config.each_with_object({}) do |(name, spec), hash|
253
- identifier, *args = Array(spec)
254
- gateway = Gateway.setup(identifier, *(args.flatten))
255
- hash[name] = gateway
256
-
257
- gateways[gateway] = identifier unless identifier.is_a?(Gateway)
258
- end
259
- end
260
57
  end
261
58
  end
@@ -1,3 +1,5 @@
1
+ require 'rom/support/registry'
2
+
1
3
  module ROM
2
4
  # @private
3
5
  class MapperRegistry < Registry
data/lib/rom/pipeline.rb CHANGED
@@ -1,3 +1,5 @@
1
+ require 'equalizer'
2
+
1
3
  module ROM
2
4
  # Data pipeline common interface
3
5
  #
data/lib/rom/plugin.rb CHANGED
@@ -1,27 +1,13 @@
1
+ require 'rom/plugin_base'
2
+
1
3
  module ROM
2
4
  # Plugin is a simple object used to store plugin configurations
3
5
  #
4
6
  # @private
5
- class Plugin
6
- # @return [Module] a module representing the plugin
7
- #
8
- # @api private
9
- attr_reader :mod
10
-
11
- # @return [Hash] configuration options
12
- #
13
- # @api private
14
- attr_reader :options
15
-
16
- # @api private
17
- def initialize(mod, options)
18
- @mod = mod
19
- @options = options
20
- end
21
-
7
+ class Plugin < PluginBase
22
8
  # Apply this plugin to the provided class
23
9
  #
24
- # @param klass [Class]
10
+ # @param [Class] klass
25
11
  #
26
12
  # @api private
27
13
  def apply_to(klass)
@@ -0,0 +1,31 @@
1
+ module ROM
2
+ # Abstract plugin base
3
+ #
4
+ # @private
5
+ class PluginBase
6
+ # @return [Module] a module representing the plugin
7
+ #
8
+ # @api private
9
+ attr_reader :mod
10
+
11
+ # @return [Hash] configuration options
12
+ #
13
+ # @api private
14
+ attr_reader :options
15
+
16
+ # @api private
17
+ def initialize(mod, options)
18
+ @mod = mod
19
+ @options = options
20
+ end
21
+
22
+ # Apply this plugin to the provided class
23
+ #
24
+ # @param [Mixed] base
25
+ #
26
+ # @api private
27
+ def apply_to(base)
28
+ raise NotImplementedError, "#{self.class}#apply_to not implemented"
29
+ end
30
+ end
31
+ end
@@ -5,6 +5,12 @@ module ROM
5
5
  #
6
6
  # @api private
7
7
  class PluginRegistry
8
+ # Internal registry for environment plugins
9
+ #
10
+ # @return [EnvironmentPluginRegistry]
11
+ #
12
+ # @api private
13
+ attr_reader :environment
8
14
  # Internal registry for command plugins
9
15
  #
10
16
  # @return [InternalPluginRegistry]
@@ -28,6 +34,7 @@ module ROM
28
34
 
29
35
  # @api private
30
36
  def initialize
37
+ @environment = EnvironmentPluginRegistry.new
31
38
  @mappers = InternalPluginRegistry.new
32
39
  @commands = InternalPluginRegistry.new
33
40
  @relations = InternalPluginRegistry.new
@@ -46,7 +53,7 @@ module ROM
46
53
  type = options.fetch(:type)
47
54
  adapter = options.fetch(:adapter, :default)
48
55
 
49
- plugins_for(type, adapter)[name] = Plugin.new(mod, options)
56
+ plugins_for(type, adapter).register(name, mod, options)
50
57
  end
51
58
 
52
59
  private
@@ -56,27 +63,17 @@ module ROM
56
63
  # @api private
57
64
  def plugins_for(type, adapter)
58
65
  case type
59
- when :command then commands.adapter(adapter)
60
- when :mapper then mappers.adapter(adapter)
61
- when :relation then relations.adapter(adapter)
66
+ when :environment then environment
67
+ when :command then commands.adapter(adapter)
68
+ when :mapper then mappers.adapter(adapter)
69
+ when :relation then relations.adapter(adapter)
62
70
  end
63
71
  end
64
72
  end
65
-
66
- # A registry storing specific plugins
73
+ # Abstract registry defining common behaviour
67
74
  #
68
75
  # @api private
69
- class AdapterPluginRegistry < Registry
70
- # Assign a plugin to this adapter registry
71
- #
72
- # @param [Symbol] name The registered plugin name
73
- # @param [Plugin] plugin The plugin to register
74
- #
75
- # @api private
76
- def []=(name, plugin)
77
- elements[name] = plugin
78
- end
79
-
76
+ class PluginRegistryBase < Registry
80
77
  # Retrieve a registered plugin
81
78
  #
82
79
  # @param [Symbol] name The plugin to retrieve
@@ -88,6 +85,46 @@ module ROM
88
85
  elements[name]
89
86
  end
90
87
  end
88
+ # A registry storing environment specific plugins
89
+ #
90
+ # @api private
91
+ class EnvironmentPluginRegistry < PluginRegistryBase
92
+ # Assign a plugin to this environment registry
93
+ #
94
+ # @param [Symbol] name The registered plugin name
95
+ # @param [Module] mod The plugin to register
96
+ # @param [Hash] options optional configuration data
97
+ #
98
+ # @api private
99
+ def register(name, mod, options)
100
+ elements[name] = EnvironmentPlugin.new(mod, options)
101
+ end
102
+ # Return an environment plugin
103
+ #
104
+ # @param [Symbol] name The name of the environment plugin
105
+ #
106
+ # @raises [UnknownPluginError] if no plugin is found with the given name
107
+ #
108
+ # @api public
109
+ def fetch(name)
110
+ self[name] || raise(UnknownPluginError, name)
111
+ end
112
+ end
113
+ # A registry storing adapter specific plugins
114
+ #
115
+ # @api private
116
+ class AdapterPluginRegistry < PluginRegistryBase
117
+ # Assign a plugin to this adapter registry
118
+ #
119
+ # @param [Symbol] name The registered plugin name
120
+ # @param [Module] mod The plugin to register
121
+ # @param [Hash] options optional configuration data
122
+ #
123
+ # @api private
124
+ def register(name, mod, options)
125
+ elements[name] = Plugin.new(mod, options)
126
+ end
127
+ end
91
128
 
92
129
  # Store a set of registries grouped by adapter
93
130
  #
data/lib/rom/relation.rb CHANGED
@@ -1,7 +1,14 @@
1
+ require 'rom/support/deprecations'
1
2
  require 'rom/relation/class_interface'
2
3
 
3
- require 'rom/relation/lazy'
4
+ require 'rom/pipeline'
5
+ require 'rom/mapper_registry'
6
+
7
+ require 'rom/relation/loaded'
4
8
  require 'rom/relation/curried'
9
+ require 'rom/relation/composite'
10
+ require 'rom/relation/graph'
11
+ require 'rom/relation/materializable'
5
12
 
6
13
  module ROM
7
14
  # Base relation class
@@ -12,17 +19,23 @@ module ROM
12
19
  # however, is considered private and should not be used outside of the
13
20
  # relation instance.
14
21
  #
15
- # ROM builds sub-classes of this class for every relation defined in the env
16
- # for easy inspection and extensibility - every gateway can provide extensions
17
- # for those sub-classes but there is always a vanilla relation instance stored
18
- # in the schema registry.
22
+ # ROM builds sub-classes of this class for every relation defined in the
23
+ # environment for easy inspection and extensibility - every gateway can
24
+ # provide extensions for those sub-classes but there is always a vanilla
25
+ # relation instance stored in the schema registry.
19
26
  #
20
27
  # @api public
21
28
  class Relation
29
+ extend Deprecations
22
30
  extend ClassInterface
31
+ extend ROM::Support::GuardedInheritanceHook
23
32
 
24
33
  include Options
25
34
  include Equalizer.new(:dataset)
35
+ include Materializable
36
+ include Pipeline
37
+
38
+ option :mappers, reader: true, default: proc { MapperRegistry.new }
26
39
 
27
40
  # Dataset used by the relation
28
41
  #
@@ -49,6 +62,26 @@ module ROM
49
62
  dataset.each { |tuple| yield(tuple) }
50
63
  end
51
64
 
65
+ # Eager load other relation(s) for this relation
66
+ #
67
+ # @param [Array<Relation>] others The other relation(s) to eager load
68
+ #
69
+ # @return [Relation::Graph]
70
+ #
71
+ # @api public
72
+ def combine(*others)
73
+ Graph.build(self, others)
74
+ end
75
+
76
+ # Load relation
77
+ #
78
+ # @return [Relation::Loaded]
79
+ #
80
+ # @api public
81
+ def call
82
+ Loaded.new(self)
83
+ end
84
+
52
85
  # Materialize a relation into an array
53
86
  #
54
87
  # @return [Array<Hash>]
@@ -58,15 +91,25 @@ module ROM
58
91
  to_enum.to_a
59
92
  end
60
93
 
61
- # Turn relation into a lazy-loadable and composable relation
94
+ # Return if this relation is curried
62
95
  #
63
- # @see Lazy
64
- #
65
- # @return [Lazy]
96
+ # @return [false]
66
97
  #
98
+ # @api private
99
+ def curried?
100
+ false
101
+ end
102
+
103
+ # @api private
104
+ def with(options)
105
+ __new__(dataset, options)
106
+ end
107
+ deprecate :to_lazy, :with, "to_lazy is no longer needed"
108
+
67
109
  # @api public
68
- def to_lazy(*args)
69
- Lazy.new(self, *args)
110
+ def relation
111
+ Deprecations.announce("#relation", 'all relations are now lazy')
112
+ self
70
113
  end
71
114
 
72
115
  private