rom 0.9.1 → 1.0.0.beta1

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 (143) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop_todo.yml +30 -12
  3. data/.travis.yml +1 -1
  4. data/CHANGELOG.md +24 -0
  5. data/Gemfile +7 -3
  6. data/README.md +24 -11
  7. data/lib/rom.rb +9 -26
  8. data/lib/rom/command.rb +113 -75
  9. data/lib/rom/commands/class_interface.rb +115 -0
  10. data/lib/rom/commands/graph.rb +17 -23
  11. data/lib/rom/commands/graph/builder.rb +176 -0
  12. data/lib/rom/commands/graph/class_interface.rb +8 -2
  13. data/lib/rom/commands/graph/input_evaluator.rb +13 -9
  14. data/lib/rom/commands/lazy.rb +23 -17
  15. data/lib/rom/commands/lazy/create.rb +23 -0
  16. data/lib/rom/commands/lazy/delete.rb +27 -0
  17. data/lib/rom/commands/lazy/update.rb +34 -0
  18. data/lib/rom/commands/result.rb +14 -0
  19. data/lib/rom/commands/update.rb +0 -4
  20. data/lib/rom/configuration.rb +86 -0
  21. data/lib/rom/{setup_dsl/setup.rb → configuration_dsl.rb} +9 -7
  22. data/lib/rom/configuration_dsl/command.rb +43 -0
  23. data/lib/rom/{setup_dsl → configuration_dsl}/command_dsl.rb +5 -4
  24. data/lib/rom/configuration_dsl/mapper.rb +37 -0
  25. data/lib/rom/{setup_dsl → configuration_dsl}/mapper_dsl.rb +11 -5
  26. data/lib/rom/configuration_dsl/relation.rb +26 -0
  27. data/lib/rom/configuration_plugin.rb +17 -0
  28. data/lib/rom/constants.rb +5 -12
  29. data/lib/rom/container.rb +11 -8
  30. data/lib/rom/create_container.rb +61 -0
  31. data/lib/rom/environment.rb +27 -241
  32. data/lib/rom/gateway.rb +18 -2
  33. data/lib/rom/global.rb +24 -0
  34. data/lib/rom/global/plugin_dsl.rb +2 -0
  35. data/lib/rom/lint/spec.rb +0 -12
  36. data/lib/rom/lint/test.rb +0 -31
  37. data/lib/rom/memory/commands.rb +2 -2
  38. data/lib/rom/memory/gateway.rb +2 -0
  39. data/lib/rom/pipeline.rb +1 -1
  40. data/lib/rom/plugin_base.rb +1 -1
  41. data/lib/rom/plugin_registry.rb +12 -10
  42. data/lib/rom/plugins/configuration/configuration_dsl.rb +16 -0
  43. data/lib/rom/plugins/relation/key_inference.rb +31 -0
  44. data/lib/rom/plugins/relation/view.rb +90 -0
  45. data/lib/rom/plugins/relation/view/dsl.rb +32 -0
  46. data/lib/rom/relation.rb +1 -11
  47. data/lib/rom/relation/class_interface.rb +37 -50
  48. data/lib/rom/setup.rb +13 -104
  49. data/lib/rom/setup/auto_registration.rb +55 -0
  50. data/lib/rom/setup/finalize.rb +113 -127
  51. data/lib/rom/setup/finalize/commands.rb +67 -0
  52. data/lib/rom/setup/finalize/mappers.rb +36 -0
  53. data/lib/rom/setup/finalize/relations.rb +53 -0
  54. data/lib/rom/support/configurable.rb +21 -7
  55. data/lib/rom/version.rb +1 -1
  56. data/rakelib/mutant.rake +4 -1
  57. data/rom.gemspec +3 -4
  58. data/spec/fixtures/app/commands/create_user.rb +2 -0
  59. data/spec/fixtures/app/mappers/user_list.rb +2 -0
  60. data/spec/fixtures/app/relations/users.rb +2 -0
  61. data/spec/fixtures/lib/persistence/commands/create_user.rb +6 -0
  62. data/spec/fixtures/lib/persistence/mappers/user_list.rb +6 -0
  63. data/spec/fixtures/lib/persistence/relations/users.rb +6 -0
  64. data/spec/{unit/rom → integration}/command_registry_spec.rb +8 -9
  65. data/spec/integration/commands/create_spec.rb +17 -13
  66. data/spec/integration/commands/delete_spec.rb +12 -11
  67. data/spec/integration/commands/error_handling_spec.rb +5 -4
  68. data/spec/integration/commands/graph_builder_spec.rb +213 -0
  69. data/spec/integration/commands/graph_spec.rb +112 -49
  70. data/spec/integration/commands/update_spec.rb +14 -11
  71. data/spec/integration/commands_spec.rb +60 -0
  72. data/spec/integration/mappers/combine_spec.rb +7 -6
  73. data/spec/integration/mappers/deep_embedded_spec.rb +5 -6
  74. data/spec/integration/mappers/definition_dsl_spec.rb +19 -18
  75. data/spec/integration/mappers/embedded_spec.rb +11 -12
  76. data/spec/integration/mappers/exclude_spec.rb +5 -6
  77. data/spec/integration/mappers/fold_spec.rb +8 -7
  78. data/spec/integration/mappers/group_spec.rb +16 -15
  79. data/spec/integration/mappers/overwrite_attributes_value_spec.rb +5 -5
  80. data/spec/integration/mappers/prefix_separator_spec.rb +5 -7
  81. data/spec/integration/mappers/prefix_spec.rb +5 -7
  82. data/spec/integration/mappers/prefixing_attributes_spec.rb +7 -7
  83. data/spec/integration/mappers/registering_custom_mappers_spec.rb +4 -5
  84. data/spec/integration/mappers/renaming_attributes_spec.rb +18 -18
  85. data/spec/integration/mappers/step_spec.rb +11 -12
  86. data/spec/integration/mappers/symbolizing_attributes_spec.rb +11 -8
  87. data/spec/integration/mappers/unfold_spec.rb +9 -10
  88. data/spec/integration/mappers/ungroup_spec.rb +10 -11
  89. data/spec/integration/mappers/unwrap_spec.rb +10 -15
  90. data/spec/integration/mappers/wrap_spec.rb +16 -15
  91. data/spec/{unit/rom → integration}/memory/commands/create_spec.rb +7 -5
  92. data/spec/{unit/rom → integration}/memory/commands/delete_spec.rb +7 -5
  93. data/spec/{unit/rom → integration}/memory/commands/update_spec.rb +7 -5
  94. data/spec/integration/multi_env_spec.rb +16 -124
  95. data/spec/integration/multi_repo_spec.rb +9 -9
  96. data/spec/integration/relations/default_dataset_spec.rb +15 -0
  97. data/spec/integration/relations/inheritance_spec.rb +5 -7
  98. data/spec/integration/relations/reading_spec.rb +32 -65
  99. data/spec/integration/relations/registry_dsl_spec.rb +5 -4
  100. data/spec/integration/repositories/extending_relations_spec.rb +6 -7
  101. data/spec/integration/repositories/setting_logger_spec.rb +5 -7
  102. data/spec/integration/setup_spec.rb +49 -61
  103. data/spec/shared/command_graph.rb +50 -0
  104. data/spec/shared/container.rb +9 -0
  105. data/spec/shared/gateway_only.rb +6 -0
  106. data/spec/shared/no_container.rb +16 -0
  107. data/spec/shared/one_behavior.rb +4 -4
  108. data/spec/shared/users_and_tasks.rb +5 -17
  109. data/spec/spec_helper.rb +5 -3
  110. data/spec/test/memory_repository_lint_test.rb +1 -1
  111. data/spec/unit/rom/auto_registration_spec.rb +54 -0
  112. data/spec/unit/rom/commands/graph_spec.rb +18 -44
  113. data/spec/unit/rom/commands/lazy_spec.rb +246 -35
  114. data/spec/unit/rom/commands/result_spec.rb +56 -0
  115. data/spec/unit/rom/commands_spec.rb +9 -73
  116. data/spec/unit/rom/configurable_spec.rb +49 -0
  117. data/spec/unit/rom/configuration_spec.rb +61 -0
  118. data/spec/unit/rom/container_spec.rb +39 -33
  119. data/spec/unit/rom/create_container_spec.rb +151 -0
  120. data/spec/unit/rom/environment_spec.rb +123 -0
  121. data/spec/unit/rom/gateway_spec.rb +58 -2
  122. data/spec/unit/rom/global_spec.rb +10 -7
  123. data/spec/unit/rom/plugin_spec.rb +44 -25
  124. data/spec/unit/rom/plugins/relation/key_inference_spec.rb +27 -0
  125. data/spec/unit/rom/plugins/relation/view_spec.rb +47 -0
  126. data/spec/unit/rom/relation/composite_spec.rb +20 -20
  127. data/spec/unit/rom/relation/curried_spec.rb +10 -11
  128. data/spec/unit/rom/relation/graph_spec.rb +27 -27
  129. data/spec/unit/rom/relation/lazy/combine_spec.rb +26 -20
  130. data/spec/unit/rom/relation/lazy_spec.rb +38 -38
  131. data/spec/unit/rom/relation/loaded_spec.rb +2 -3
  132. data/spec/unit/rom/relation_spec.rb +39 -2
  133. metadata +58 -66
  134. data/lib/rom/commands/abstract.rb +0 -184
  135. data/lib/rom/environment_plugin.rb +0 -17
  136. data/lib/rom/environment_plugins/auto_registration.rb +0 -38
  137. data/lib/rom/repository.rb +0 -16
  138. data/lib/rom/setup_dsl/command.rb +0 -36
  139. data/lib/rom/setup_dsl/mapper.rb +0 -32
  140. data/lib/rom/setup_dsl/relation.rb +0 -30
  141. data/spec/integration/inline_setup_spec.rb +0 -65
  142. data/spec/unit/rom/repository_spec.rb +0 -12
  143. data/spec/unit/rom/setup_spec.rb +0 -253
data/lib/rom/gateway.rb CHANGED
@@ -3,6 +3,10 @@ module ROM
3
3
  #
4
4
  # @api public
5
5
  class Gateway
6
+ extend ClassMacros
7
+
8
+ defines :adapter
9
+
6
10
  # Return connection object
7
11
  #
8
12
  # @return [Object] type varies depending on the gateway
@@ -74,7 +78,7 @@ module ROM
74
78
  #
75
79
  # @api private
76
80
  def self.class_from_symbol(type)
77
- adapter = ROM.adapters.fetch(type) do
81
+ adapter = ROM.adapters.fetch(type) {
78
82
  begin
79
83
  require "rom/#{type}"
80
84
  rescue LoadError
@@ -82,7 +86,7 @@ module ROM
82
86
  end
83
87
 
84
88
  ROM.adapters.fetch(type)
85
- end
89
+ }
86
90
 
87
91
  if adapter.const_defined?(:Gateway)
88
92
  adapter.const_get(:Gateway)
@@ -91,6 +95,18 @@ module ROM
91
95
  end
92
96
  end
93
97
 
98
+ # Returns the adapter, defined for the class
99
+ #
100
+ # @return [Symbol]
101
+ #
102
+ # @api public
103
+ def adapter
104
+ self.class.adapter || raise(
105
+ MissingAdapterIdentifierError,
106
+ "gateway class +#{self}+ is missing the adapter identifier"
107
+ )
108
+ end
109
+
94
110
  # A generic interface for setting up a logger
95
111
  #
96
112
  # @api public
data/lib/rom/global.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require 'rom/plugin_registry'
2
2
  require 'rom/global/plugin_dsl'
3
+ require 'rom/support/deprecations'
3
4
 
4
5
  module ROM
5
6
  # Globally accessible public interface exposed via ROM module
@@ -12,6 +13,7 @@ module ROM
12
13
  def self.extended(rom)
13
14
  super
14
15
 
16
+ rom.instance_variable_set('@env', nil)
15
17
  rom.instance_variable_set('@adapters', {})
16
18
  rom.instance_variable_set('@plugin_registry', PluginRegistry.new)
17
19
  end
@@ -54,5 +56,27 @@ module ROM
54
56
  adapters[identifier] = adapter
55
57
  self
56
58
  end
59
+
60
+ def env=(container)
61
+ @env = container
62
+ end
63
+
64
+ def env
65
+ if @env.nil?
66
+ ROM::Deprecations.announce(:env, %q{
67
+ ROM.env is no longer automatically populated with your container.
68
+ If possible, refactor your code to remove the dependency on global ROM state. If it is not
69
+ possible—or as a temporary solution—you can assign your container to `ROM.env` upon
70
+ creation:
71
+
72
+ ROM.env = ROM.container(:memory) do |rom|
73
+ ...
74
+ end
75
+ })
76
+ nil
77
+ else
78
+ @env
79
+ end
80
+ end
57
81
  end
58
82
  end
@@ -1,3 +1,5 @@
1
+ require 'rom/support/constants'
2
+
1
3
  module ROM
2
4
  module Global
3
5
  # plugin registration DSL
data/lib/rom/lint/spec.rb CHANGED
@@ -1,18 +1,6 @@
1
1
  require 'rom/lint/gateway'
2
2
  require 'rom/lint/enumerable_dataset'
3
3
 
4
- RSpec.shared_examples "a rom repository" do
5
- before(:all) do
6
- ROM::Deprecations.announce "[Adapter]::Repository is", <<-MSG
7
- Please use [Adapter]::Gateway instead.
8
- MSG
9
- end
10
-
11
- let(:gateway) { repository }
12
-
13
- include_examples "a rom gateway"
14
- end
15
-
16
4
  RSpec.shared_examples "a rom gateway" do
17
5
  ROM::Lint::Gateway.each_lint do |name, linter|
18
6
  it name do
data/lib/rom/lint/test.rb CHANGED
@@ -61,37 +61,6 @@ module ROM
61
61
  end
62
62
  end
63
63
 
64
- # This is a transitional lint-test loader for repository class
65
- # to ensure that the basic interfaces are in place
66
- #
67
- # class MyRepositoryTest < Minitest::Test
68
- # include ROM::Lint::TestRepository
69
- #
70
- # def setup
71
- # @repository = MyRepository
72
- # @uri = "super_db://something"
73
- # end
74
- # end
75
- #
76
- # @see [ROM::Lint::TestGateway]
77
- #
78
- # @api public
79
- module TestRepository
80
- extend TestGateway
81
-
82
- # Returns the reposiotry class
83
- #
84
- # @api public
85
- attr_reader :repository
86
-
87
- def setup
88
- ROM::Deprecations.announce "[Adapter]::Repository is", <<-MSG
89
- Please use [Adapter]::Gateway instead.
90
- MSG
91
- @gateway = repository
92
- end
93
- end
94
-
95
64
  # This is a simple lint-test for a gateway dataset class to ensure the
96
65
  # basic behavior is correct
97
66
  #
@@ -14,12 +14,12 @@ module ROM
14
14
 
15
15
  # @see ROM::Commands::Create#execute
16
16
  def execute(tuples)
17
- Array([tuples]).flatten.map do |tuple|
17
+ Array([tuples]).flatten.map { |tuple|
18
18
  attributes = input[tuple]
19
19
  validator.call(attributes)
20
20
  relation.insert(attributes.to_h)
21
21
  attributes
22
- end.to_a
22
+ }.to_a
23
23
  end
24
24
  end
25
25
 
@@ -13,6 +13,8 @@ module ROM
13
13
  #
14
14
  # @api public
15
15
  class Gateway < ROM::Gateway
16
+ adapter :memory
17
+
16
18
  # @return [Object] default logger
17
19
  #
18
20
  # @api public
data/lib/rom/pipeline.rb CHANGED
@@ -68,7 +68,7 @@ module ROM
68
68
  #
69
69
  # @api private
70
70
  class Composite
71
- include Equalizer.new(:left, :right)
71
+ include Dry::Equalizer(:left, :right)
72
72
  include Proxy
73
73
 
74
74
  # @api private
@@ -24,7 +24,7 @@ module ROM
24
24
  # @param [Mixed] base
25
25
  #
26
26
  # @api private
27
- def apply_to(base)
27
+ def apply_to(_base)
28
28
  raise NotImplementedError, "#{self.class}#apply_to not implemented"
29
29
  end
30
30
  end
@@ -5,12 +5,13 @@ module ROM
5
5
  #
6
6
  # @api private
7
7
  class PluginRegistry
8
- # Internal registry for environment plugins
8
+ # Internal registry for configuration plugins
9
9
  #
10
- # @return [EnvironmentPluginRegistry]
10
+ # @return [ConfigurationPluginRegistry]
11
11
  #
12
12
  # @api private
13
- attr_reader :environment
13
+ attr_reader :configuration
14
+
14
15
  # Internal registry for command plugins
15
16
  #
16
17
  # @return [InternalPluginRegistry]
@@ -34,7 +35,7 @@ module ROM
34
35
 
35
36
  # @api private
36
37
  def initialize
37
- @environment = EnvironmentPluginRegistry.new
38
+ @configuration = ConfigurationPluginRegistry.new
38
39
  @mappers = InternalPluginRegistry.new
39
40
  @commands = InternalPluginRegistry.new
40
41
  @relations = InternalPluginRegistry.new
@@ -63,10 +64,10 @@ module ROM
63
64
  # @api private
64
65
  def plugins_for(type, adapter)
65
66
  case type
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)
67
+ when :configuration then configuration
68
+ when :command then commands.adapter(adapter)
69
+ when :mapper then mappers.adapter(adapter)
70
+ when :relation then relations.adapter(adapter)
70
71
  end
71
72
  end
72
73
  end
@@ -88,7 +89,7 @@ module ROM
88
89
  # A registry storing environment specific plugins
89
90
  #
90
91
  # @api private
91
- class EnvironmentPluginRegistry < PluginRegistryBase
92
+ class ConfigurationPluginRegistry < PluginRegistryBase
92
93
  # Assign a plugin to this environment registry
93
94
  #
94
95
  # @param [Symbol] name The registered plugin name
@@ -97,8 +98,9 @@ module ROM
97
98
  #
98
99
  # @api private
99
100
  def register(name, mod, options)
100
- elements[name] = EnvironmentPlugin.new(mod, options)
101
+ elements[name] = ConfigurationPlugin.new(mod, options)
101
102
  end
103
+
102
104
  # Return an environment plugin
103
105
  #
104
106
  # @param [Symbol] name The name of the environment plugin
@@ -0,0 +1,16 @@
1
+ require 'rom/configuration_dsl'
2
+
3
+ module ROM
4
+ module ConfigurationPlugins
5
+ # Provides macros for defining relations, mappers and commands
6
+ #
7
+ # @api public
8
+ module ConfigurationDSL
9
+
10
+ # @api private
11
+ def self.apply(configuration, options = {})
12
+ configuration.extend(ROM::ConfigurationDSL)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,31 @@
1
+ module ROM
2
+ module Plugins
3
+ module Relation
4
+ module KeyInference
5
+ # Infer foreign_key name for this relation
6
+ #
7
+ # TODO: this should be configurable and handled by an injected policy
8
+ #
9
+ # @return [Symbol]
10
+ #
11
+ # @api private
12
+ def foreign_key
13
+ :"#{Inflector.singularize(name)}_id"
14
+ end
15
+
16
+ # Return base name which defaults to name attribute
17
+ #
18
+ # @return [Symbol]
19
+ #
20
+ # @api private
21
+ def base_name
22
+ name
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+
29
+ ROM.plugins do
30
+ register :key_inference, ROM::Plugins::Relation::KeyInference, type: :relation
31
+ end
@@ -0,0 +1,90 @@
1
+ require 'rom/plugins/relation/view/dsl'
2
+
3
+ module ROM
4
+ module Plugins
5
+ module Relation
6
+ module View
7
+ def self.included(klass)
8
+ super
9
+
10
+ klass.class_eval do
11
+ extend ClassInterface
12
+
13
+ option :view, reader: true
14
+
15
+ def self.attributes
16
+ @__attributes__ ||= {}
17
+ end
18
+ end
19
+ end
20
+
21
+ # Return column names that will be selected for this relation
22
+ #
23
+ # By default we use dataset columns but first we look at configured
24
+ # attributes by `view` DSL
25
+ #
26
+ # @return [Array<Symbol>]
27
+ #
28
+ # @api private
29
+ def attributes(view_name = view)
30
+ header = self.class.attributes
31
+ .fetch(view_name, self.class.attributes.fetch(:base))
32
+
33
+ if header.is_a?(Proc)
34
+ instance_exec(&header)
35
+ else
36
+ header
37
+ end
38
+ end
39
+
40
+ module ClassInterface
41
+ # Define a relation view with a specific header
42
+ #
43
+ # With headers defined all the mappers will be inferred automatically
44
+ #
45
+ # @example
46
+ # class Users < ROM::Relation[:sql]
47
+ # view(:by_name, [:id, :name]) do |name|
48
+ # where(name: name)
49
+ # end
50
+ #
51
+ # view(:listing, [:id, :name, :email]) do
52
+ # select(:id, :name, :email).order(:name)
53
+ # end
54
+ # end
55
+ #
56
+ # @api public
57
+ def view(*args, &block)
58
+ if args.size == 1 && block.arity > 0
59
+ raise ArgumentError, "header must be set as second argument"
60
+ end
61
+
62
+ name, names, relation_block =
63
+ if args.size == 1
64
+ DSL.new(*args, &block).call
65
+ else
66
+ [*args, block]
67
+ end
68
+
69
+ attributes[name] = names
70
+
71
+ if relation_block.arity > 0
72
+ auto_curry_guard do
73
+ define_method(name, &relation_block)
74
+ auto_curry(name) { with(view: name) }
75
+ end
76
+ else
77
+ define_method(name) do
78
+ instance_exec(&relation_block).with(view: name)
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
87
+
88
+ ROM.plugins do
89
+ register :view, ROM::Plugins::Relation::View, type: :relation
90
+ end
@@ -0,0 +1,32 @@
1
+ module ROM
2
+ module Plugins
3
+ module Relation
4
+ module View
5
+ class DSL
6
+ attr_reader :name
7
+
8
+ attr_reader :attributes
9
+
10
+ attr_reader :relation_block
11
+
12
+ def initialize(name, &block)
13
+ @name = name
14
+ instance_eval(&block)
15
+ end
16
+
17
+ def header(*args, &block)
18
+ @attributes = args.size > 0 ? args.first : block
19
+ end
20
+
21
+ def relation(&block)
22
+ @relation_block = lambda(&block)
23
+ end
24
+
25
+ def call
26
+ [name, attributes, relation_block]
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
data/lib/rom/relation.rb CHANGED
@@ -1,4 +1,3 @@
1
- require 'rom/support/deprecations'
2
1
  require 'rom/relation/class_interface'
3
2
 
4
3
  require 'rom/pipeline'
@@ -26,12 +25,10 @@ module ROM
26
25
  #
27
26
  # @api public
28
27
  class Relation
29
- extend Deprecations
30
28
  extend ClassInterface
31
- extend ROM::Support::GuardedInheritanceHook
32
29
 
33
30
  include Options
34
- include Equalizer.new(:dataset)
31
+ include Dry::Equalizer(:dataset)
35
32
  include Materializable
36
33
  include Pipeline
37
34
 
@@ -104,13 +101,6 @@ module ROM
104
101
  def with(options)
105
102
  __new__(dataset, options)
106
103
  end
107
- deprecate :to_lazy, :with, "to_lazy is no longer needed"
108
-
109
- # @api public
110
- def relation
111
- Deprecations.announce("#relation", 'all relations are now lazy')
112
- self
113
- end
114
104
 
115
105
  private
116
106