rom 2.0.2 → 3.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 (149) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +4 -4
  3. data/CHANGELOG.md +34 -1
  4. data/Gemfile +16 -2
  5. data/Rakefile +7 -2
  6. data/lib/rom/array_dataset.rb +44 -0
  7. data/lib/rom/association_set.rb +11 -5
  8. data/lib/rom/auto_curry.rb +55 -0
  9. data/lib/rom/command.rb +70 -41
  10. data/lib/rom/command_registry.rb +7 -18
  11. data/lib/rom/commands/class_interface.rb +7 -6
  12. data/lib/rom/commands/composite.rb +0 -1
  13. data/lib/rom/commands/graph.rb +7 -15
  14. data/lib/rom/commands/lazy/update.rb +1 -1
  15. data/lib/rom/configuration_dsl/command.rb +6 -8
  16. data/lib/rom/configuration_dsl/mapper.rb +2 -3
  17. data/lib/rom/configuration_dsl/mapper_dsl.rb +0 -1
  18. data/lib/rom/configuration_dsl/relation.rb +4 -4
  19. data/lib/rom/configuration_dsl.rb +0 -4
  20. data/lib/rom/constants.rb +1 -1
  21. data/lib/rom/container.rb +0 -2
  22. data/lib/rom/create_container.rb +0 -2
  23. data/lib/rom/data_proxy.rb +94 -0
  24. data/lib/rom/enumerable_dataset.rb +68 -0
  25. data/lib/rom/gateway.rb +23 -6
  26. data/lib/rom/global/plugin_dsl.rb +0 -2
  27. data/lib/rom/global.rb +0 -2
  28. data/lib/rom/initializer.rb +26 -0
  29. data/lib/rom/lint/gateway.rb +17 -0
  30. data/lib/rom/mapper_registry.rb +1 -1
  31. data/lib/rom/memory/commands.rb +0 -2
  32. data/lib/rom/memory/dataset.rb +1 -2
  33. data/lib/rom/memory/relation.rb +14 -1
  34. data/lib/rom/memory/schema.rb +13 -0
  35. data/lib/rom/plugin_registry.rb +1 -1
  36. data/lib/rom/plugins/configuration/configuration_dsl.rb +6 -2
  37. data/lib/rom/plugins/relation/key_inference.rb +4 -2
  38. data/lib/rom/plugins/relation/registry_reader.rb +5 -1
  39. data/lib/rom/registry.rb +50 -0
  40. data/lib/rom/relation/class_interface.rb +94 -26
  41. data/lib/rom/relation/curried.rb +15 -15
  42. data/lib/rom/relation/view_dsl.rb +31 -0
  43. data/lib/rom/relation.rb +49 -34
  44. data/lib/rom/schema/dsl.rb +7 -9
  45. data/lib/rom/schema/type.rb +115 -0
  46. data/lib/rom/schema.rb +218 -18
  47. data/lib/rom/setup/auto_registration.rb +20 -17
  48. data/lib/rom/setup/auto_registration_strategies/base.rb +8 -3
  49. data/lib/rom/setup/auto_registration_strategies/custom_namespace.rb +4 -3
  50. data/lib/rom/setup/auto_registration_strategies/no_namespace.rb +5 -4
  51. data/lib/rom/setup/auto_registration_strategies/with_namespace.rb +3 -3
  52. data/lib/rom/setup/finalize/finalize_commands.rb +1 -1
  53. data/lib/rom/setup/finalize/finalize_mappers.rb +1 -1
  54. data/lib/rom/setup/finalize/finalize_relations.rb +3 -1
  55. data/lib/rom/setup/finalize.rb +1 -1
  56. data/lib/rom/transaction.rb +24 -0
  57. data/lib/rom/types.rb +9 -1
  58. data/lib/rom/version.rb +1 -1
  59. data/lib/rom.rb +4 -8
  60. data/rom.gemspec +4 -3
  61. data/spec/integration/command_registry_spec.rb +1 -14
  62. data/spec/integration/commands/create_spec.rb +5 -25
  63. data/spec/integration/commands/delete_spec.rb +1 -1
  64. data/spec/integration/commands/error_handling_spec.rb +1 -1
  65. data/spec/integration/commands/graph_spec.rb +20 -14
  66. data/spec/integration/commands/update_spec.rb +4 -27
  67. data/spec/integration/commands_spec.rb +1 -1
  68. data/spec/integration/{repositories → gateways}/extending_relations_spec.rb +1 -1
  69. data/spec/integration/{repositories → gateways}/setting_logger_spec.rb +2 -2
  70. data/spec/integration/mappers/combine_spec.rb +1 -1
  71. data/spec/integration/mappers/deep_embedded_spec.rb +1 -1
  72. data/spec/integration/mappers/definition_dsl_spec.rb +1 -1
  73. data/spec/integration/mappers/embedded_spec.rb +1 -1
  74. data/spec/integration/mappers/exclude_spec.rb +1 -1
  75. data/spec/integration/mappers/fold_spec.rb +1 -1
  76. data/spec/integration/mappers/group_spec.rb +1 -1
  77. data/spec/integration/mappers/overwrite_attributes_value_spec.rb +1 -1
  78. data/spec/integration/mappers/prefix_separator_spec.rb +1 -1
  79. data/spec/integration/mappers/prefix_spec.rb +1 -1
  80. data/spec/integration/mappers/prefixing_attributes_spec.rb +1 -1
  81. data/spec/integration/mappers/registering_custom_mappers_spec.rb +1 -1
  82. data/spec/integration/mappers/renaming_attributes_spec.rb +1 -1
  83. data/spec/integration/mappers/reusing_mappers_spec.rb +1 -1
  84. data/spec/integration/mappers/step_spec.rb +1 -1
  85. data/spec/integration/mappers/symbolizing_attributes_spec.rb +1 -1
  86. data/spec/integration/mappers/unfold_spec.rb +1 -1
  87. data/spec/integration/mappers/ungroup_spec.rb +1 -1
  88. data/spec/integration/mappers/unwrap_spec.rb +2 -2
  89. data/spec/integration/mappers/wrap_spec.rb +1 -1
  90. data/spec/integration/memory/commands/create_spec.rb +1 -1
  91. data/spec/integration/memory/commands/delete_spec.rb +1 -1
  92. data/spec/integration/memory/commands/update_spec.rb +1 -1
  93. data/spec/integration/multi_env_spec.rb +1 -1
  94. data/spec/integration/multi_repo_spec.rb +1 -1
  95. data/spec/integration/relations/default_dataset_spec.rb +1 -1
  96. data/spec/integration/relations/reading_spec.rb +1 -1
  97. data/spec/integration/relations/registry_dsl_spec.rb +1 -1
  98. data/spec/integration/setup_spec.rb +10 -4
  99. data/spec/shared/command_graph.rb +8 -4
  100. data/spec/shared/enumerable_dataset.rb +1 -1
  101. data/spec/spec_helper.rb +7 -9
  102. data/spec/support/schema.rb +14 -0
  103. data/spec/unit/rom/array_dataset_spec.rb +59 -0
  104. data/spec/unit/rom/association_set_spec.rb +4 -0
  105. data/spec/unit/rom/auto_curry_spec.rb +63 -0
  106. data/spec/unit/rom/commands/graph_spec.rb +12 -11
  107. data/spec/unit/rom/commands/lazy_spec.rb +8 -5
  108. data/spec/unit/rom/commands/pre_and_post_processors_spec.rb +269 -0
  109. data/spec/unit/rom/commands/result_spec.rb +1 -1
  110. data/spec/unit/rom/commands_spec.rb +9 -3
  111. data/spec/unit/rom/configuration_spec.rb +1 -1
  112. data/spec/unit/rom/container_spec.rb +11 -5
  113. data/spec/unit/rom/create_container_spec.rb +1 -1
  114. data/spec/unit/rom/enumerable_dataset_spec.rb +15 -0
  115. data/spec/unit/rom/gateway_spec.rb +1 -1
  116. data/spec/unit/rom/mapper_registry_spec.rb +1 -1
  117. data/spec/unit/rom/memory/commands_spec.rb +1 -1
  118. data/spec/unit/rom/memory/dataset_spec.rb +1 -1
  119. data/spec/unit/rom/memory/{repository_spec.rb → gateway_spec.rb} +1 -1
  120. data/spec/unit/rom/memory/inheritance_spec.rb +32 -0
  121. data/spec/unit/rom/memory/relation_spec.rb +15 -3
  122. data/spec/unit/rom/memory/storage_spec.rb +1 -1
  123. data/spec/unit/rom/plugin_spec.rb +1 -1
  124. data/spec/unit/rom/plugins/relation/key_inference_spec.rb +1 -1
  125. data/spec/unit/rom/registry_spec.rb +86 -0
  126. data/spec/unit/rom/relation/attribute_reader_spec.rb +17 -0
  127. data/spec/unit/rom/relation/composite_spec.rb +1 -1
  128. data/spec/unit/rom/relation/graph_spec.rb +1 -1
  129. data/spec/unit/rom/relation/lazy/combine_spec.rb +1 -1
  130. data/spec/unit/rom/relation/lazy_spec.rb +1 -1
  131. data/spec/unit/rom/relation/loaded_spec.rb +1 -1
  132. data/spec/unit/rom/relation/schema_spec.rb +10 -6
  133. data/spec/unit/rom/relation/view_spec.rb +112 -0
  134. data/spec/unit/rom/relation_spec.rb +16 -2
  135. data/spec/unit/rom/schema/accessing_attributes_spec.rb +52 -0
  136. data/spec/unit/rom/schema/exclude_spec.rb +15 -0
  137. data/spec/unit/rom/schema/finalize_spec.rb +59 -0
  138. data/spec/unit/rom/schema/key_predicate_spec.rb +15 -0
  139. data/spec/unit/rom/schema/merge_spec.rb +17 -0
  140. data/spec/unit/rom/schema/prefix_spec.rb +16 -0
  141. data/spec/unit/rom/schema/project_spec.rb +15 -0
  142. data/spec/unit/rom/schema/rename_spec.rb +22 -0
  143. data/spec/unit/rom/schema/type_spec.rb +49 -0
  144. data/spec/unit/rom/schema/wrap_spec.rb +17 -0
  145. data/spec/unit/rom/schema_spec.rb +2 -2
  146. metadata +69 -17
  147. data/lib/rom/plugins/relation/view/dsl.rb +0 -32
  148. data/lib/rom/plugins/relation/view.rb +0 -95
  149. data/spec/unit/rom/plugins/relation/view_spec.rb +0 -51
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e6dd420bd1787efc67261de110b316f6b5c92ae8
4
- data.tar.gz: e9f8fb3dbc40528ac46f6427d7b7238c162980bd
3
+ metadata.gz: 58d0cbbb31e4ac734e6b569dcd7c0a1bd679bd89
4
+ data.tar.gz: d6f72e2b130a21ba81cc66400be6da7ea179aa6c
5
5
  SHA512:
6
- metadata.gz: 6a48171fa2e771fec4e68e14b99e4f78cfd31f6d5162ff5f14546f41d6970b44c8522304cfa9546cff203967696853002e3524f714023d7ac0fd5ea086d7ea9f
7
- data.tar.gz: 34e9a0f63fabaf30897d767db9b8d26e1ac92cd0661cff7bdb5b1f27979fe56feb9f6b0c12ae7305f514c623322e270009ecd3ce35e51867bfdac5a199393408
6
+ metadata.gz: 3ae3f83681a32b2f51629a49ab3ecde5c66d2ce2ce59e6dfdb36475343a73ff4515bda9e5aa5b7ab59fb7fd81777296ee7b98b221af621f1f37bd4ae42159442
7
+ data.tar.gz: b688b6b8430a4f9bbe4dd43dbe066813aa354adc5d0e519107be7c3c8e226abb8498c06c2bbbd4042d6498a2ea0c63e63a73396ad1fddf342740a1c438c14045
data/.travis.yml CHANGED
@@ -5,11 +5,11 @@ cache: bundler
5
5
  bundler_args: --without sql benchmarks console tools
6
6
  script: "bundle exec rake ci"
7
7
  after_success:
8
- - '[ "$TRAVIS_RUBY_VERSION" = "2.3.1" ] && [ "$TRAVIS_BRANCH" = "master" ] && bundle exec codeclimate-test-reporter'
8
+ - '[ -d coverage ] && bundle exec codeclimate-test-reporter'
9
9
  rvm:
10
- - 2.1
11
- - 2.2
12
- - 2.3.1
10
+ - 2.2.6
11
+ - 2.3.3
12
+ - 2.4.0
13
13
  - rbx-3
14
14
  - jruby-9.1.5.0
15
15
  env:
data/CHANGELOG.md CHANGED
@@ -1,3 +1,36 @@
1
+ ## v3.0.0 to-be-released
2
+
3
+ ## Added
4
+
5
+ * Support for schemas in view definitions via `schema do ... end` block (evaluated in the context of the canonical schema) (solnic)
6
+ * Schemas have their own types with adapter-specific APIs (solnic)
7
+ * Schema attributes include meta properties `source` and `target` (for FKs) (solnic)
8
+ * Inferred schemas can have explicit attribute definitions for cases where inference didn't work (solnic)
9
+ * New schema APIs: `#project`, `#rename`, `#exclude`, `#prefix`, `#wrap` and `#merge` (solnic)
10
+ * New schema attribute APIs: `#name`, `#aliased`, `#aliased?`, `#prefixed`, `#prefixed?`, `#wrapped`, `#wrapped?`, `#source`, `#target`, `#primary_key?`, `#foreign_key?` (solnic)
11
+ * Schemas are coercible to arrays that include all attribute types (solnic)
12
+ * Automatic relation view projection via `Schema#call` (abstract method for adapters) (solnic)
13
+ * `Relation#new(dataset, new_opts)` interface (solnic)
14
+ * `Relation#[]` interface for convenient access to schema attributes (solnic)
15
+ * `Command` has now support for `before` and `after` hooks (solnic)
16
+ * New `Command#before` method for creating a command with before hook(s) at run-time (solnic)
17
+ * New `Command#after` method for creating a command with after hook(s) at run-time (solnic)
18
+ * New `Gateway#transaction` method runs code inside a transaction (flash-gordon)
19
+
20
+ ## Changed
21
+
22
+ * [BREAKING] All relations have schemas now, empty by default (solnic)
23
+ * [BREAKING] `view` DSL is now part of the core relation API (solnic)
24
+ * [BREAKING] `view` DSL is based on schemas now, `header` was replaced with `schema` (solnic)
25
+ * [BREAKING] Deprecated `Command.validator` was removed (solnic)
26
+ * [internal] Renamed `relation` => `target` meta property in FK types (solnic)
27
+ * [internal] Use deprecations API from dry-core (flash-gordon)
28
+ * [internal] Use common constants from dry-core (EMPTY_HASH, EMPTY_ARRAY etc.) (flash-gordon)
29
+ * [internal] Internal ROM modules (array_dataset, enumerable_dataset, auto_curry, and data_proxy) were moved from rom-support to ROM itself (flash-gordon)
30
+ * [internal] rom-support dependency was removed (flash-gordon)
31
+
32
+ [Compare v2.0.2...v3.0.0](https://github.com/rom-rb/rom/compare/v2.0.2...v3.0.0)
33
+
1
34
  ## v2.0.2 2016-11-11
2
35
 
3
36
  ## Added
@@ -9,7 +42,7 @@
9
42
  * Custom command input function is no longer overridden by schema hash (solnic)
10
43
  * `Relation::Name#to_s` returns a string properly when there is no alias (solnic)
11
44
 
12
- [Compare v2.0.1...v2.0.2](https://github.com/rom-rb/rom/compare/v2.0.0...v2.0.2)
45
+ [Compare v2.0.1...v2.0.2](https://github.com/rom-rb/rom/compare/v2.0.1...v2.0.2)
13
46
 
14
47
  ## v2.0.1 2016-09-30
15
48
 
data/Gemfile CHANGED
@@ -2,6 +2,8 @@ source 'https://rubygems.org'
2
2
 
3
3
  gemspec
4
4
 
5
+ gem 'rom-mapper', git: 'https://github.com/rom-rb/rom-mapper.git', branch: 'master'
6
+
5
7
  group :console do
6
8
  gem 'pry'
7
9
  gem 'pg', platforms: [:mri]
@@ -24,18 +26,30 @@ group :test do
24
26
  end
25
27
 
26
28
  group :sql do
27
- gem 'rom-sql', github: 'rom-rb/rom-sql', branch: 'master'
29
+ gem 'rom-sql', git: 'https://github.com/rom-rb/rom-sql.git', branch: 'master'
28
30
  gem 'sequel'
29
31
  gem 'jdbc-sqlite3', platforms: :jruby
32
+ gem 'jdbc-postgres', platforms: :jruby
30
33
  gem 'sqlite3', platforms: [:mri, :rbx]
34
+
35
+ git_source(:github) { |repo_name| "https://github.com/#{repo_name}.git" }
36
+
37
+ platform :jruby do
38
+ github 'jruby/activerecord-jdbc-adapter', branch: 'rails-5' do
39
+ gem 'activerecord-jdbc-adapter'
40
+ gem 'activerecord-jdbcpostgresql-adapter'
41
+ end
42
+ end
31
43
  end
32
44
 
33
45
  group :benchmarks do
34
46
  gem 'activerecord', '~> 5.0'
35
47
  gem 'benchmark-ips', '~> 2.2.0'
36
- gem 'rom-repository', github: 'rom-rb/rom-repository', branch: 'master'
48
+ gem 'rom-repository', git: 'https://github.com/rom-rb/rom-repository.git', branch: 'master'
37
49
  end
38
50
 
39
51
  group :tools do
40
52
  gem 'byebug', platform: :mri
53
+ gem 'mutant'
54
+ gem 'mutant-rspec'
41
55
  end
data/Rakefile CHANGED
@@ -11,8 +11,13 @@ task :"spec:isolation" do
11
11
  end
12
12
  end
13
13
 
14
- desc "Run CI tasks"
15
- task ci: [:spec, :lint, :"spec:isolation"]
14
+ if RUBY_ENGINE == 'jruby'
15
+ desc "Run CI tasks"
16
+ task ci: [:spec, :lint]
17
+ else
18
+ desc "Run CI tasks"
19
+ task ci: [:spec, :lint, :"spec:isolation"]
20
+ end
16
21
 
17
22
  Rake::TestTask.new(:lint) do |test|
18
23
  test.description = "Run adapter lint tests against memory adapter"
@@ -0,0 +1,44 @@
1
+ require 'rom/initializer'
2
+ require 'rom/enumerable_dataset'
3
+
4
+ module ROM
5
+ # A helper module that adds data-proxy behavior to an array-like object
6
+ #
7
+ # @see EnumerableDataset
8
+ #
9
+ # @api public
10
+ module ArrayDataset
11
+ extend DataProxy::ClassMethods
12
+ include EnumerableDataset
13
+
14
+ # Extends the class with data-proxy behavior
15
+ #
16
+ # @api private
17
+ def self.included(klass)
18
+ klass.class_eval do
19
+ extend Initializer
20
+ include DataProxy
21
+
22
+ param :data
23
+ end
24
+ end
25
+
26
+ forward(
27
+ :*, :+, :-, :compact, :compact!, :flatten, :flatten!, :length, :pop,
28
+ :reverse, :reverse!, :sample, :size, :shift, :shuffle, :shuffle!,
29
+ :slice, :slice!, :sort!, :uniq, :uniq!, :unshift, :values_at
30
+ )
31
+
32
+ [
33
+ :map!, :combination, :cycle, :delete_if, :keep_if, :permutation, :reject!,
34
+ :select!, :sort_by!
35
+ ].each do |method|
36
+ class_eval <<-RUBY, __FILE__, __LINE__ + 1
37
+ def #{method}(*args, &block)
38
+ return to_enum unless block
39
+ self.class.new(data.send(:#{method}, *args, &block), options)
40
+ end
41
+ RUBY
42
+ end
43
+ end
44
+ end
@@ -1,12 +1,14 @@
1
- require 'rom/support/registry'
2
- require 'rom/support/inflector'
1
+ require 'dry/core/inflector'
2
+ require 'rom/registry'
3
3
 
4
4
  module ROM
5
5
  class AssociationSet < ROM::Registry
6
6
  # @api private
7
7
  def try(name, &block)
8
- if key?(name)
9
- yield(self[name])
8
+ key = name.to_sym
9
+
10
+ if key?(key) || key?(singularize(key))
11
+ yield(self[key])
10
12
  else
11
13
  false
12
14
  end
@@ -19,8 +21,12 @@ module ROM
19
21
  if key?(key)
20
22
  super
21
23
  else
22
- super(Inflector.singularize(key))
24
+ super(singularize(key))
23
25
  end
24
26
  end
27
+
28
+ def singularize(key)
29
+ Dry::Core::Inflector.singularize(key).to_sym
30
+ end
25
31
  end
26
32
  end
@@ -0,0 +1,55 @@
1
+ module ROM
2
+ module AutoCurry
3
+ def self.extended(klass)
4
+ klass.define_singleton_method(:method_added) do |name|
5
+ return if auto_curry_busy?
6
+ auto_curry_guard { auto_curry(name) }
7
+ super(name)
8
+ end
9
+ end
10
+
11
+ def auto_curry_guard
12
+ @__auto_curry_busy__ = true
13
+ yield
14
+ ensure
15
+ @__auto_curry_busy__ = false
16
+ end
17
+
18
+ def auto_curry_busy?
19
+ @__auto_curry_busy__ ||= false
20
+ end
21
+
22
+ def auto_curried_methods
23
+ @__auto_curried_methods__ ||= []
24
+ end
25
+
26
+ def auto_curry(name, &block)
27
+ arity = instance_method(name).arity
28
+
29
+ return unless public_instance_methods.include?(name) && arity != 0
30
+
31
+ mod = Module.new
32
+
33
+ mod.module_eval do
34
+ define_method(name) do |*args|
35
+ response =
36
+ if arity < 0 || arity == args.size
37
+ super(*args)
38
+ else
39
+ self.class.curried.new(self, name: name, curry_args: args, arity: arity)
40
+ end
41
+
42
+ if block
43
+ response.instance_exec(&block)
44
+ else
45
+ response
46
+ end
47
+ end
48
+ end
49
+
50
+ auto_curried_methods << name
51
+
52
+ prepend(mod)
53
+ end
54
+ end
55
+ end
data/lib/rom/command.rb CHANGED
@@ -1,5 +1,8 @@
1
- require 'rom/support/deprecations'
2
- require 'rom/support/options'
1
+ require 'dry/core/deprecations'
2
+ require 'dry/core/class_attributes'
3
+
4
+ require 'rom/types'
5
+ require 'rom/initializer'
3
6
  require 'rom/pipeline'
4
7
 
5
8
  require 'rom/commands/class_interface'
@@ -20,57 +23,33 @@ module ROM
20
23
  #
21
24
  # @private
22
25
  class Command
23
- DEFAULT_VALIDATOR = proc {}
24
-
26
+ extend Initializer
25
27
  include Dry::Equalizer(:relation, :options)
26
28
  include Commands
27
29
  include Pipeline::Operator
28
30
 
29
- extend ClassMacros
31
+ extend Dry::Core::ClassAttributes
30
32
  extend ClassInterface
31
33
 
32
- include Options
34
+ defines :adapter, :relation, :result, :input, :register_as, :restrictable, :before, :after
33
35
 
34
- defines :adapter, :relation, :result, :input, :validator, :register_as, :restrictable
36
+ # @attr_reader [Relation] relation The command's relation
37
+ param :relation
35
38
 
36
- option :type, allow: [:create, :update, :delete]
37
- option :source, reader: true
38
- option :result, reader: true, allow: [:one, :many]
39
- option :validator, reader: true
39
+ CommandType = Types::Strict::Symbol.enum(:create, :update, :delete)
40
+ Result = Types::Strict::Symbol.enum(:one, :many)
41
+
42
+ option :type, type: CommandType, optional: true
43
+ option :source, reader: true, optional: true, default: -> c { c.relation }
44
+ option :result, reader: true, type: Result
40
45
  option :input, reader: true
41
- option :curry_args, type: Array, reader: true, default: EMPTY_ARRAY
46
+ option :curry_args, reader: true, default: -> _ { EMPTY_ARRAY }
47
+ option :before, Types::Coercible::Array, reader: true, as: :before_hooks, default: proc { EMPTY_ARRAY }
48
+ option :after, Types::Coercible::Array, reader: true, as: :after_hooks, default: proc { EMPTY_ARRAY }
42
49
 
43
50
  input Hash
44
- validator DEFAULT_VALIDATOR
45
51
  result :many
46
52
 
47
- # @deprecated
48
- #
49
- # @api public
50
- def self.validator(vp = nil)
51
- if defined?(@validator) && vp.nil?
52
- @validator
53
- else
54
- unless vp.equal?(DEFAULT_VALIDATOR)
55
- Deprecations.announce(
56
- "#{name}.validator",
57
- 'Please handle validation before calling commands'
58
- )
59
- end
60
- super
61
- end
62
- end
63
-
64
- # @attr_reader [Relation] relation The command's relation
65
- attr_reader :relation
66
-
67
- # @api private
68
- def initialize(relation, options = EMPTY_HASH)
69
- super
70
- @relation = relation
71
- @source = options[:source] || relation
72
- end
73
-
74
53
  # Return name of this command's relation
75
54
  #
76
55
  # @return [ROM::Relation::Name]
@@ -107,7 +86,25 @@ module ROM
107
86
  #
108
87
  # @api public
109
88
  def call(*args, &block)
110
- tuples = execute(*(curry_args + args), &block)
89
+ tuples =
90
+ if hooks?
91
+ prepared =
92
+ if curried?
93
+ apply_hooks(before_hooks, *(curry_args + args))
94
+ else
95
+ apply_hooks(before_hooks, *args)
96
+ end
97
+
98
+ result = prepared ? execute(prepared, &block) : execute(&block)
99
+
100
+ if curried?
101
+ apply_hooks(after_hooks, result, *args)
102
+ else
103
+ apply_hooks(after_hooks, result, *args[1..args.size-1])
104
+ end
105
+ else
106
+ execute(*(curry_args + args), &block)
107
+ end
111
108
 
112
109
  if one?
113
110
  tuples.first
@@ -133,6 +130,16 @@ module ROM
133
130
  end
134
131
  alias_method :with, :curry
135
132
 
133
+ # @api public
134
+ def curried?
135
+ curry_args.size > 0
136
+ end
137
+
138
+ # @api private
139
+ def hooks?
140
+ before_hooks.size > 0 || after_hooks.size > 0
141
+ end
142
+
136
143
  # @api public
137
144
  def combine(*others)
138
145
  Graph.new(self, others)
@@ -163,11 +170,33 @@ module ROM
163
170
  self.class.build(new_relation, options.merge(source: relation))
164
171
  end
165
172
 
173
+ # @api public
174
+ def before(*hooks)
175
+ self.class.new(relation, options.merge(before: hooks))
176
+ end
177
+
178
+ # @api public
179
+ def after(*hooks)
180
+ self.class.new(relation, options.merge(after: hooks))
181
+ end
182
+
166
183
  private
167
184
 
168
185
  # @api private
169
186
  def composite_class
170
187
  Command::Composite
171
188
  end
189
+
190
+ # @api private
191
+ def apply_hooks(hooks, tuples, *args)
192
+ hooks.reduce(tuples) do |a, e|
193
+ if e.is_a?(Hash)
194
+ hook_meth, hook_args = e.to_a.flatten(1)
195
+ __send__(hook_meth, a, *args, **hook_args)
196
+ else
197
+ __send__(e, a, *args)
198
+ end
199
+ end
200
+ end
172
201
  end
173
202
  end
@@ -1,3 +1,4 @@
1
+ require 'rom/types'
1
2
  require 'rom/commands/result'
2
3
 
3
4
  module ROM
@@ -5,40 +6,28 @@ module ROM
5
6
  #
6
7
  # @api public
7
8
  class CommandRegistry
9
+ extend Initializer
8
10
  include Commands
9
- include Options
10
11
 
11
12
  CommandNotFoundError = Class.new(KeyError)
13
+ RegistryType = Types.Definition(Registry) | Types.Constructor(Registry) { |r| Registry.new(r, self.class.name) }
12
14
 
13
15
  # Name of the relation from which commands are under
14
16
  #
15
17
  # @return [String]
16
18
  #
17
19
  # @api private
18
- attr_reader :relation_name
20
+ param :relation_name
19
21
 
20
22
  # Internal command registry
21
23
  #
22
24
  # @return [Registry]
23
25
  #
24
26
  # @api private
25
- attr_reader :registry
27
+ param :registry, type: RegistryType
26
28
 
27
- option :mappers, reader: true
28
- option :mapper, reader: true
29
-
30
- # @api private
31
- def initialize(relation_name, elements, options = EMPTY_HASH)
32
- super
33
-
34
- @relation_name = relation_name
35
- @registry =
36
- if elements.is_a?(Registry)
37
- elements
38
- else
39
- Registry.new(elements, self.class.name)
40
- end
41
- end
29
+ option :mappers, reader: true, optional: true
30
+ option :mapper, reader: true, optional: true
42
31
 
43
32
  # Try to execute a command in a block
44
33
  #
@@ -1,4 +1,5 @@
1
- require 'rom/support/class_builder'
1
+ require 'dry/core/class_builder'
2
+ require 'dry/core/inflector'
2
3
 
3
4
  module ROM
4
5
  # Base command class with factory class-level interface and setup-related logic
@@ -20,7 +21,7 @@ module ROM
20
21
  #
21
22
  # @api public
22
23
  def [](adapter)
23
- adapter_namespace(adapter).const_get(Inflector.demodulize(name))
24
+ adapter_namespace(adapter).const_get(Dry::Core::Inflector.demodulize(name))
24
25
  end
25
26
 
26
27
  # Return namespaces that contains command subclasses of a specific adapter
@@ -65,8 +66,8 @@ module ROM
65
66
  #
66
67
  # @api public
67
68
  def create_class(name, type, &block)
68
- klass = ClassBuilder
69
- .new(name: "#{Inflector.classify(type)}[:#{name}]", parent: type)
69
+ klass = Dry::Core::ClassBuilder
70
+ .new(name: "#{Dry::Core::Inflector.classify(type)}[:#{name}]", parent: type)
70
71
  .call
71
72
 
72
73
  if block
@@ -113,7 +114,7 @@ module ROM
113
114
  #
114
115
  # @api private
115
116
  def default_name
116
- Inflector.underscore(Inflector.demodulize(name)).to_sym
117
+ Dry::Core::Inflector.underscore(Dry::Core::Inflector.demodulize(name)).to_sym
117
118
  end
118
119
 
119
120
  # Return default options based on class macros
@@ -122,7 +123,7 @@ module ROM
122
123
  #
123
124
  # @api private
124
125
  def options
125
- { input: input, validator: validator, result: result }
126
+ { input: input, result: result, before: before, after: after }
126
127
  end
127
128
 
128
129
  # @api private
@@ -1,5 +1,4 @@
1
1
  require 'rom/pipeline'
2
- require 'rom/support/constants'
3
2
 
4
3
  module ROM
5
4
  module Commands
@@ -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,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