rom 3.2.2 → 3.2.3

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: dcffdcd66a5b0b8127eb767564652778c8061ca6
4
- data.tar.gz: 27f25c3fae64b26b1ab8d6643a5a7f90cb4fb633
3
+ metadata.gz: 0f727af1309d22c607fa43b3c26345749233dbef
4
+ data.tar.gz: 7a1d5142394e77da212457c8d656ca2d9d632759
5
5
  SHA512:
6
- metadata.gz: 83984e098b54e2e544b231be28aaf51157cae035c3f53f34d7509c42eb3e994796c47599feebf6a28cafcf284c64c1c6c61eeef046db7cc0216516f5d71ecbf6
7
- data.tar.gz: 0aba220bf1b4667ff29d801dca1afd457e0fca1456d60353625ca3d72aa8903186d415e2de8c412ccbb69c5993f153930d4b85acde15f096e89b0ccc85d11185
6
+ metadata.gz: 2b915a97368fd38abcaab1160d28bbc4aa5b218415fc58605fc8517d6149ca21f7ae749b383a5733e00d937b362dde5a0e61e3acfe65d98e0c847a6632982682
7
+ data.tar.gz: ca3d98f9a4446d108bc029aa6ee8da32a0185b52a6a2dd4ed007abf702fb7cf1a8d742b300db5d796ba2e141b3f90bc0608182198f7d64c3e4cfb90265d5c4a4
data/CHANGELOG.md CHANGED
@@ -1,8 +1,28 @@
1
+ # v3.2.3 2017-05-31
2
+
3
+ ## Added
4
+
5
+ * auto-registration was improved with better handling of custom namespaces (Krule)
6
+
7
+ ## Changed
8
+
9
+ * `Relation#combine` was deprecated in favor of `Relation#graph` (solnic)
10
+
11
+ [Compare v3.2.2...v3.2.3](https://github.com/rom-rb/rom/compare/v3.2.2...v3.2.3)
12
+
13
+ # v3.2.2 2017-05-05
14
+
15
+ ## Changed
16
+
17
+ * [internal] Compatibility with `dry-core` v0.3.0 (flash-gordon)
18
+
19
+ [Compare v3.2.1...v3.2.2](https://github.com/rom-rb/rom/compare/v3.2.1...v3.2.2)
20
+
1
21
  # v3.2.1 2017-05-02
2
22
 
3
23
  ## Changed
4
24
 
5
- * `ROM::Schema::Attribute` uses `Initializer` now (flash-gordon)
25
+ * [internal] `ROM::Schema::Attribute` uses `Initializer` now (flash-gordon)
6
26
 
7
27
  [Compare v3.2.0...v3.2.1](https://github.com/rom-rb/rom/compare/v3.2.0...v3.2.1)
8
28
 
data/Gemfile CHANGED
@@ -24,7 +24,7 @@ group :test do
24
24
  end
25
25
 
26
26
  group :sql do
27
- gem 'rom-sql', git: 'https://github.com/rom-rb/rom-sql.git', branch: 'master'
27
+ gem 'rom-sql', git: 'https://github.com/rom-rb/rom-sql.git', branch: 'release-1.0'
28
28
  gem 'sequel'
29
29
  gem 'jdbc-sqlite3', platforms: :jruby
30
30
  gem 'jdbc-postgres', platforms: :jruby
data/README.md CHANGED
@@ -13,6 +13,8 @@
13
13
  [![Code Climate](https://codeclimate.com/github/rom-rb/rom/badges/gpa.svg)][codeclimate]
14
14
  [![Test Coverage](https://codeclimate.com/github/rom-rb/rom/badges/coverage.svg)][codeclimate]
15
15
  [![Inline docs](http://inch-ci.org/github/rom-rb/rom.svg?branch=master&style=flat)][inchpages]
16
+ [![OpenCollective](https://opencollective.com/rom/backers/badge.svg)](#backers)
17
+ [![OpenCollective](https://opencollective.com/rom/sponsors/badge.svg)](#sponsors)
16
18
 
17
19
  Ruby Object Mapper (ROM) is a data mapping and persistence toolkit for Ruby
18
20
  with the goal to provide powerful object mapping capabilities without limiting
@@ -22,10 +24,76 @@ Learn more:
22
24
 
23
25
  * [Introduction](http://rom-rb.org/learn/introduction)
24
26
  * [Quick Start](http://rom-rb.org/learn/repositories/quick-start)
25
-
26
- ## Support Campaign
27
-
28
- You can support ROM's development via our [campaign on Bountysource](https://salt.bountysource.com/teams/rom-rb). Cheers!
27
+
28
+ ## Backers
29
+
30
+ Support us with a monthly donation and help us continue our activities. [[Become a backer](https://opencollective.com/rom#backer)]
31
+
32
+ <a href="https://opencollective.com/rom/backer/0/website" target="_blank"><img src="https://opencollective.com/rom/backer/0/avatar.svg"></a>
33
+ <a href="https://opencollective.com/rom/backer/1/website" target="_blank"><img src="https://opencollective.com/rom/backer/1/avatar.svg"></a>
34
+ <a href="https://opencollective.com/rom/backer/2/website" target="_blank"><img src="https://opencollective.com/rom/backer/2/avatar.svg"></a>
35
+ <a href="https://opencollective.com/rom/backer/3/website" target="_blank"><img src="https://opencollective.com/rom/backer/3/avatar.svg"></a>
36
+ <a href="https://opencollective.com/rom/backer/4/website" target="_blank"><img src="https://opencollective.com/rom/backer/4/avatar.svg"></a>
37
+ <a href="https://opencollective.com/rom/backer/5/website" target="_blank"><img src="https://opencollective.com/rom/backer/5/avatar.svg"></a>
38
+ <a href="https://opencollective.com/rom/backer/6/website" target="_blank"><img src="https://opencollective.com/rom/backer/6/avatar.svg"></a>
39
+ <a href="https://opencollective.com/rom/backer/7/website" target="_blank"><img src="https://opencollective.com/rom/backer/7/avatar.svg"></a>
40
+ <a href="https://opencollective.com/rom/backer/8/website" target="_blank"><img src="https://opencollective.com/rom/backer/8/avatar.svg"></a>
41
+ <a href="https://opencollective.com/rom/backer/9/website" target="_blank"><img src="https://opencollective.com/rom/backer/9/avatar.svg"></a>
42
+ <a href="https://opencollective.com/rom/backer/10/website" target="_blank"><img src="https://opencollective.com/rom/backer/10/avatar.svg"></a>
43
+ <a href="https://opencollective.com/rom/backer/11/website" target="_blank"><img src="https://opencollective.com/rom/backer/11/avatar.svg"></a>
44
+ <a href="https://opencollective.com/rom/backer/12/website" target="_blank"><img src="https://opencollective.com/rom/backer/12/avatar.svg"></a>
45
+ <a href="https://opencollective.com/rom/backer/13/website" target="_blank"><img src="https://opencollective.com/rom/backer/13/avatar.svg"></a>
46
+ <a href="https://opencollective.com/rom/backer/14/website" target="_blank"><img src="https://opencollective.com/rom/backer/14/avatar.svg"></a>
47
+ <a href="https://opencollective.com/rom/backer/15/website" target="_blank"><img src="https://opencollective.com/rom/backer/15/avatar.svg"></a>
48
+ <a href="https://opencollective.com/rom/backer/16/website" target="_blank"><img src="https://opencollective.com/rom/backer/16/avatar.svg"></a>
49
+ <a href="https://opencollective.com/rom/backer/17/website" target="_blank"><img src="https://opencollective.com/rom/backer/17/avatar.svg"></a>
50
+ <a href="https://opencollective.com/rom/backer/18/website" target="_blank"><img src="https://opencollective.com/rom/backer/18/avatar.svg"></a>
51
+ <a href="https://opencollective.com/rom/backer/19/website" target="_blank"><img src="https://opencollective.com/rom/backer/19/avatar.svg"></a>
52
+ <a href="https://opencollective.com/rom/backer/20/website" target="_blank"><img src="https://opencollective.com/rom/backer/20/avatar.svg"></a>
53
+ <a href="https://opencollective.com/rom/backer/21/website" target="_blank"><img src="https://opencollective.com/rom/backer/21/avatar.svg"></a>
54
+ <a href="https://opencollective.com/rom/backer/22/website" target="_blank"><img src="https://opencollective.com/rom/backer/22/avatar.svg"></a>
55
+ <a href="https://opencollective.com/rom/backer/23/website" target="_blank"><img src="https://opencollective.com/rom/backer/23/avatar.svg"></a>
56
+ <a href="https://opencollective.com/rom/backer/24/website" target="_blank"><img src="https://opencollective.com/rom/backer/24/avatar.svg"></a>
57
+ <a href="https://opencollective.com/rom/backer/25/website" target="_blank"><img src="https://opencollective.com/rom/backer/25/avatar.svg"></a>
58
+ <a href="https://opencollective.com/rom/backer/26/website" target="_blank"><img src="https://opencollective.com/rom/backer/26/avatar.svg"></a>
59
+ <a href="https://opencollective.com/rom/backer/27/website" target="_blank"><img src="https://opencollective.com/rom/backer/27/avatar.svg"></a>
60
+ <a href="https://opencollective.com/rom/backer/28/website" target="_blank"><img src="https://opencollective.com/rom/backer/28/avatar.svg"></a>
61
+ <a href="https://opencollective.com/rom/backer/29/website" target="_blank"><img src="https://opencollective.com/rom/backer/29/avatar.svg"></a>
62
+
63
+ ## Sponsors
64
+
65
+ Become a sponsor and get your logo on our README on Github with a link to your site. [[Become a sponsor](https://opencollective.com/rom#sponsor)]
66
+
67
+ <a href="https://opencollective.com/rom/sponsor/0/website" target="_blank"><img src="https://opencollective.com/rom/sponsor/0/avatar.svg"></a>
68
+ <a href="https://opencollective.com/rom/sponsor/1/website" target="_blank"><img src="https://opencollective.com/rom/sponsor/1/avatar.svg"></a>
69
+ <a href="https://opencollective.com/rom/sponsor/2/website" target="_blank"><img src="https://opencollective.com/rom/sponsor/2/avatar.svg"></a>
70
+ <a href="https://opencollective.com/rom/sponsor/3/website" target="_blank"><img src="https://opencollective.com/rom/sponsor/3/avatar.svg"></a>
71
+ <a href="https://opencollective.com/rom/sponsor/4/website" target="_blank"><img src="https://opencollective.com/rom/sponsor/4/avatar.svg"></a>
72
+ <a href="https://opencollective.com/rom/sponsor/5/website" target="_blank"><img src="https://opencollective.com/rom/sponsor/5/avatar.svg"></a>
73
+ <a href="https://opencollective.com/rom/sponsor/6/website" target="_blank"><img src="https://opencollective.com/rom/sponsor/6/avatar.svg"></a>
74
+ <a href="https://opencollective.com/rom/sponsor/7/website" target="_blank"><img src="https://opencollective.com/rom/sponsor/7/avatar.svg"></a>
75
+ <a href="https://opencollective.com/rom/sponsor/8/website" target="_blank"><img src="https://opencollective.com/rom/sponsor/8/avatar.svg"></a>
76
+ <a href="https://opencollective.com/rom/sponsor/9/website" target="_blank"><img src="https://opencollective.com/rom/sponsor/9/avatar.svg"></a>
77
+ <a href="https://opencollective.com/rom/sponsor/10/website" target="_blank"><img src="https://opencollective.com/rom/sponsor/10/avatar.svg"></a>
78
+ <a href="https://opencollective.com/rom/sponsor/11/website" target="_blank"><img src="https://opencollective.com/rom/sponsor/11/avatar.svg"></a>
79
+ <a href="https://opencollective.com/rom/sponsor/12/website" target="_blank"><img src="https://opencollective.com/rom/sponsor/12/avatar.svg"></a>
80
+ <a href="https://opencollective.com/rom/sponsor/13/website" target="_blank"><img src="https://opencollective.com/rom/sponsor/13/avatar.svg"></a>
81
+ <a href="https://opencollective.com/rom/sponsor/14/website" target="_blank"><img src="https://opencollective.com/rom/sponsor/14/avatar.svg"></a>
82
+ <a href="https://opencollective.com/rom/sponsor/15/website" target="_blank"><img src="https://opencollective.com/rom/sponsor/15/avatar.svg"></a>
83
+ <a href="https://opencollective.com/rom/sponsor/16/website" target="_blank"><img src="https://opencollective.com/rom/sponsor/16/avatar.svg"></a>
84
+ <a href="https://opencollective.com/rom/sponsor/17/website" target="_blank"><img src="https://opencollective.com/rom/sponsor/17/avatar.svg"></a>
85
+ <a href="https://opencollective.com/rom/sponsor/18/website" target="_blank"><img src="https://opencollective.com/rom/sponsor/18/avatar.svg"></a>
86
+ <a href="https://opencollective.com/rom/sponsor/19/website" target="_blank"><img src="https://opencollective.com/rom/sponsor/19/avatar.svg"></a>
87
+ <a href="https://opencollective.com/rom/sponsor/20/website" target="_blank"><img src="https://opencollective.com/rom/sponsor/20/avatar.svg"></a>
88
+ <a href="https://opencollective.com/rom/sponsor/21/website" target="_blank"><img src="https://opencollective.com/rom/sponsor/21/avatar.svg"></a>
89
+ <a href="https://opencollective.com/rom/sponsor/22/website" target="_blank"><img src="https://opencollective.com/rom/sponsor/22/avatar.svg"></a>
90
+ <a href="https://opencollective.com/rom/sponsor/23/website" target="_blank"><img src="https://opencollective.com/rom/sponsor/23/avatar.svg"></a>
91
+ <a href="https://opencollective.com/rom/sponsor/24/website" target="_blank"><img src="https://opencollective.com/rom/sponsor/24/avatar.svg"></a>
92
+ <a href="https://opencollective.com/rom/sponsor/25/website" target="_blank"><img src="https://opencollective.com/rom/sponsor/25/avatar.svg"></a>
93
+ <a href="https://opencollective.com/rom/sponsor/26/website" target="_blank"><img src="https://opencollective.com/rom/sponsor/26/avatar.svg"></a>
94
+ <a href="https://opencollective.com/rom/sponsor/27/website" target="_blank"><img src="https://opencollective.com/rom/sponsor/27/avatar.svg"></a>
95
+ <a href="https://opencollective.com/rom/sponsor/28/website" target="_blank"><img src="https://opencollective.com/rom/sponsor/28/avatar.svg"></a>
96
+ <a href="https://opencollective.com/rom/sponsor/29/website" target="_blank"><img src="https://opencollective.com/rom/sponsor/29/avatar.svg"></a>
29
97
 
30
98
  ## Ecosystem
31
99
 
@@ -31,10 +31,10 @@ module ROM
31
31
  mod = Module.new
32
32
 
33
33
  mod.module_eval do
34
- define_method(name) do |*args|
34
+ define_method(name) do |*args, &mblock|
35
35
  response =
36
36
  if arity < 0 || arity == args.size
37
- super(*args)
37
+ super(*args, &mblock)
38
38
  else
39
39
  self.class.curried.new(self, name: name, curry_args: args, arity: arity)
40
40
  end
data/lib/rom/relation.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'dry/core/class_attributes'
2
+ require 'dry/core/deprecations'
2
3
 
3
4
  require 'rom/initializer'
4
5
  require 'rom/relation/class_interface'
@@ -41,6 +42,7 @@ module ROM
41
42
 
42
43
  extend Initializer
43
44
  extend ClassInterface
45
+ extend Dry::Core::Deprecations[:rom]
44
46
 
45
47
  extend Dry::Core::ClassAttributes
46
48
  defines :schema_class, :schema_inferrer, :schema_dsl
@@ -120,9 +122,10 @@ module ROM
120
122
  # @return [Relation::Graph]
121
123
  #
122
124
  # @api public
123
- def combine(*others)
125
+ def graph(*others)
124
126
  Graph.build(self, others)
125
127
  end
128
+ deprecate :combine, :graph
126
129
 
127
130
  # Loads relation
128
131
  #
@@ -1,3 +1,5 @@
1
+ require 'dry/core/deprecations'
2
+
1
3
  require 'rom/relation/loaded'
2
4
  require 'rom/relation/composite'
3
5
  require 'rom/relation/materializable'
@@ -24,6 +26,8 @@ module ROM
24
26
  #
25
27
  # @api public
26
28
  class Graph
29
+ extend Dry::Core::Deprecations[:rom]
30
+
27
31
  include Materializable
28
32
  include Pipeline
29
33
  include Pipeline::Proxy
@@ -82,9 +86,10 @@ module ROM
82
86
  # @return [Graph]
83
87
  #
84
88
  # @api public
85
- def combine(*others)
89
+ def graph(*others)
86
90
  self.class.new(root, nodes + others)
87
91
  end
92
+ deprecate :combine, :graph
88
93
 
89
94
  # Materialize this relation graph
90
95
  #
@@ -29,7 +29,7 @@ module ROM
29
29
  option :globs, default: -> {
30
30
  Hash[
31
31
  component_dirs.map { |component, path|
32
- [component, directory.join("#{ path }/**/*.rb")]
32
+ [component, directory.join("#{path}/**/*.rb")]
33
33
  }
34
34
  ]
35
35
  }
@@ -55,7 +55,7 @@ module ROM
55
55
  case namespace
56
56
  when String
57
57
  AutoRegistrationStrategies::CustomNamespace.new(
58
- namespace: namespace, file: file
58
+ namespace: namespace, file: file, directory: directory
59
59
  ).call
60
60
  when TrueClass
61
61
  AutoRegistrationStrategies::WithNamespace.new(
@@ -66,6 +66,7 @@ module ROM
66
66
  file: file, directory: directory, entity: component_dirs.fetch(entity)
67
67
  ).call
68
68
  end
69
+
69
70
  Dry::Core::Inflector.constantize(klass_name)
70
71
  end
71
72
  end
@@ -10,7 +10,7 @@ module ROM
10
10
 
11
11
  option :file, type: Types::Strict::String
12
12
 
13
- EXTENSION_REGEX = /\.rb\z/.freeze
13
+ EXTENSION_REGEX = /\.rb\z/
14
14
  end
15
15
  end
16
16
  end
@@ -7,17 +7,57 @@ require 'rom/setup/auto_registration_strategies/base'
7
7
  module ROM
8
8
  module AutoRegistrationStrategies
9
9
  class CustomNamespace < Base
10
+ option :directory, type: PathnameType
10
11
  option :namespace, type: Types::Strict::String
11
12
 
12
13
  def call
13
- "#{namespace}::#{Dry::Core::Inflector.camelize(filename)}"
14
+ potential = []
15
+ attempted = []
16
+
17
+ path_arr.reverse.each do |dir|
18
+ const_fragment = potential.unshift(
19
+ Dry::Core::Inflector.camelize(dir)
20
+ ).join("::")
21
+
22
+ constant = "#{namespace}::#{const_fragment}"
23
+
24
+ return constant if ns_const.const_defined?(const_fragment)
25
+
26
+ attempted << constant
27
+ end
28
+
29
+ # If we have reached this point, its means constant is not defined and
30
+ # NameError will be thrown if we attempt to camelize something like:
31
+ # `"#{namespace}::#{Dry::Core::Inflector.camelize(filename)}"`
32
+ # so we can assume naming convention was not respected in required
33
+ # file.
34
+
35
+ raise NameError, name_error_message(attempted)
14
36
  end
15
37
 
16
38
  private
17
39
 
40
+ def name_error_message(attempted)
41
+ "required file does not define expected constant name; either " \
42
+ "register your constant explicitly of try following the path" \
43
+ "naming convention like:\n\n\t- #{attempted.join("\n\t- ")}\n"
44
+ end
45
+
18
46
  def filename
19
47
  Pathname(file).basename('.rb')
20
48
  end
49
+
50
+ def ns_const
51
+ @namespace_constant ||= Dry::Core::Inflector.constantize(namespace)
52
+ end
53
+
54
+ def path_arr
55
+ file_path << filename
56
+ end
57
+
58
+ def file_path
59
+ File.dirname(file).split("/") - directory.to_s.split("/")
60
+ end
21
61
  end
22
62
  end
23
63
  end
data/lib/rom/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module ROM
2
- VERSION = '3.2.2'.freeze
2
+ VERSION = '3.2.3'.freeze
3
3
  end
@@ -0,0 +1,8 @@
1
+ module My
2
+ module Namespace
3
+ module Commands
4
+ class CreateCustomer
5
+ end
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ module My
2
+ module Namespace
3
+ module Mappers
4
+ class CustomerList
5
+ end
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ module My
2
+ module Namespace
3
+ module Relations
4
+ class Customers
5
+ end
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ module My
2
+ module NewNamespace
3
+ module Foo
4
+ class CreateCustomer
5
+ end
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ module My
2
+ module NewNamespace
3
+ module Foo
4
+ class CustomerList
5
+ end
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ module My
2
+ module NewNamespace
3
+ module Foo
4
+ class Customers
5
+ end
6
+ end
7
+ end
8
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,3 +1,5 @@
1
+ require 'pathname'
2
+
1
3
  if RUBY_ENGINE == 'ruby' && ENV['COVERAGE'] == 'true'
2
4
  require 'yaml'
3
5
  rubies = YAML.load(File.read(File.join(__dir__, '..', '.travis.yml')))['rvm']
@@ -30,6 +30,10 @@ RSpec.describe ROM::AutoCurry do
30
30
  args
31
31
  end
32
32
 
33
+ def yielding_block(arg)
34
+ yield(arg)
35
+ end
36
+
33
37
  protected
34
38
 
35
39
  def leave_me_alone(foo)
@@ -39,7 +43,7 @@ RSpec.describe ROM::AutoCurry do
39
43
  end
40
44
 
41
45
  it 'registers auto-curried methods' do
42
- expect(object.class.auto_curried_methods).to eql(%i[arity_1 arity_2 arity_many])
46
+ expect(object.class.auto_curried_methods).to eql(%i[arity_1 arity_2 arity_many yielding_block])
43
47
  end
44
48
 
45
49
  it 'auto-curries method with arity == 0' do
@@ -60,4 +64,8 @@ RSpec.describe ROM::AutoCurry do
60
64
  expect(object.arity_many).to eql([])
61
65
  expect(object.arity_many(1, 2)).to eql([1, 2])
62
66
  end
67
+
68
+ it 'yields block' do
69
+ expect(object.yielding_block(1) { |arg| [arg, 2] }).to eql([1, 2])
70
+ end
63
71
  end
@@ -106,8 +106,8 @@ RSpec.describe ROM::Relation, '#combine' do
106
106
  { name: 'Jane', title: 'be cool', priority: 2 }
107
107
  ],
108
108
  tags: [
109
- { task: 'be cool', name: 'red' },
110
- { task: 'be cool', name: 'green' }
109
+ { task: 'be cool', name: 'red', user: 'Jane' },
110
+ { task: 'be cool', name: 'green', user: 'Jane' }
111
111
  ]
112
112
  }
113
113
  ]
@@ -129,8 +129,8 @@ RSpec.describe ROM::Relation, '#combine' do
129
129
  { name: 'Jane', title: 'be cool', priority: 2 }
130
130
  ],
131
131
  tags: [
132
- { task: 'be cool', name: 'red' },
133
- { task: 'be cool', name: 'green' }
132
+ { task: 'be cool', name: 'red', user: 'Jane' },
133
+ { task: 'be cool', name: 'green', user: 'Jane' }
134
134
  ]
135
135
  }
136
136
  ]
@@ -0,0 +1,165 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe ROM::Relation, '#graph' do
4
+ include_context 'gateway only'
5
+ include_context 'users and tasks'
6
+
7
+ let(:tags_dataset) { gateway.dataset(:tags) }
8
+
9
+ let(:users_relation) do
10
+ Class.new(ROM::Memory::Relation) do
11
+ def by_name(name)
12
+ restrict(name: name)
13
+ end
14
+ end.new(users_dataset)
15
+ end
16
+
17
+ let(:tasks_relation) do
18
+ Class.new(ROM::Memory::Relation) do
19
+ def for_users(users)
20
+ names = users.map { |user| user[:name] }
21
+ restrict { |task| names.include?(task[:name]) }
22
+ end
23
+ end.new(tasks_dataset)
24
+ end
25
+
26
+ let(:tags_relation) do
27
+ Class.new(ROM::Memory::Relation) do
28
+ attr_accessor :tasks
29
+ forward :map
30
+
31
+ def for_tasks(tasks)
32
+ titles = tasks.map { |task| task[:title] }
33
+ restrict { |tag| titles.include?(tag[:task]) }
34
+ end
35
+
36
+ def for_users(users)
37
+ user_tasks = tasks.for_users(users)
38
+
39
+ for_tasks(user_tasks).map { |tag|
40
+ tag.merge(user: user_tasks.detect { |task|
41
+ task[:title] == tag[:task]
42
+ } [:name])
43
+ }
44
+ end
45
+ end.new(tags_dataset).tap { |r| r.tasks = tasks_relation }
46
+ end
47
+
48
+ before do
49
+ tags_dataset.insert(task: 'be cool', name: 'red')
50
+ tags_dataset.insert(task: 'be cool', name: 'green')
51
+ end
52
+
53
+ let(:map_users) {
54
+ proc { |users, tasks|
55
+ users.map { |user|
56
+ user.merge(tasks: tasks.select { |task| task[:name] == user[:name] })
57
+ }
58
+ }
59
+ }
60
+
61
+ let(:map_tasks) {
62
+ proc { |(tasks, children)|
63
+ tags = children.first
64
+
65
+ tasks.map { |task|
66
+ task.merge(tags: tags.select { |tag| tag[:task] == task[:title] })
67
+ }
68
+ }
69
+ }
70
+
71
+ let(:map_user_with_tasks_and_tags) {
72
+ proc { |users, (tasks, tags)|
73
+ users.map { |user|
74
+ user_tasks = tasks.select { |task| task[:name] == user[:name] }
75
+
76
+ user_tags = tasks.flat_map { |task|
77
+ tags.select { |tag| tag[:task] == task[:title] }
78
+ }
79
+
80
+ user.merge(
81
+ tasks: user_tasks,
82
+ tags: user_tags
83
+ )
84
+ }
85
+ }
86
+ }
87
+
88
+ let(:map_user_with_tasks) {
89
+ proc { |users, children|
90
+ map_users[users, map_tasks[children.first]]
91
+ }
92
+ }
93
+
94
+ it 'raises error when composite relation is passed as a node' do
95
+ expect {
96
+ users_relation.graph(tasks_relation >> proc {})
97
+ }.to raise_error(ROM::UnsupportedRelationError)
98
+ end
99
+
100
+ it 'supports more than one eagerly-loaded relation' do
101
+ expected = [
102
+ {
103
+ name: 'Jane',
104
+ email: 'jane@doe.org',
105
+ tasks: [
106
+ { name: 'Jane', title: 'be cool', priority: 2 }
107
+ ],
108
+ tags: [
109
+ { task: 'be cool', name: 'red', user: 'Jane' },
110
+ { task: 'be cool', name: 'green', user: 'Jane' }
111
+ ]
112
+ }
113
+ ]
114
+
115
+ user_with_tasks_and_tags = users_relation.by_name('Jane')
116
+ .graph(tasks_relation.for_users, tags_relation.for_users)
117
+
118
+ result = user_with_tasks_and_tags >> map_user_with_tasks_and_tags
119
+
120
+ expect(result.to_a).to eql(expected)
121
+ end
122
+
123
+ it 'supports more than one eagerly-loaded relation via chaining' do
124
+ expected = [
125
+ {
126
+ name: 'Jane',
127
+ email: 'jane@doe.org',
128
+ tasks: [
129
+ { name: 'Jane', title: 'be cool', priority: 2 }
130
+ ],
131
+ tags: [
132
+ { task: 'be cool', name: 'red', user: 'Jane' },
133
+ { task: 'be cool', name: 'green', user: 'Jane' }
134
+ ]
135
+ }
136
+ ]
137
+
138
+ user_with_tasks_and_tags = users_relation.by_name('Jane')
139
+ .graph(tasks_relation.for_users).graph(tags_relation.for_users)
140
+
141
+ result = user_with_tasks_and_tags >> map_user_with_tasks_and_tags
142
+
143
+ expect(result).to match_array(expected)
144
+ end
145
+
146
+ it 'supports nested eager-loading' do
147
+ expected = [
148
+ {
149
+ name: 'Jane', email: 'jane@doe.org', tasks: [
150
+ { name: 'Jane', title: 'be cool', priority: 2, tags: [
151
+ { task: 'be cool', name: 'red' },
152
+ { task: 'be cool', name: 'green' }
153
+ ] }
154
+ ]
155
+ }
156
+ ]
157
+
158
+ user_with_tasks = users_relation.by_name('Jane')
159
+ .graph(tasks_relation.for_users.graph(tags_relation.for_tasks))
160
+
161
+ result = user_with_tasks >> map_user_with_tasks
162
+
163
+ expect(result).to match_array(expected)
164
+ end
165
+ end
@@ -117,34 +117,96 @@ RSpec.describe ROM::Setup, '#auto_registration' do
117
117
  end
118
118
  end
119
119
 
120
- context 'with custom namespace' do
121
- before do
122
- setup.auto_registration(
123
- SPEC_ROOT.join('fixtures/custom'),
124
- component_dirs: {
125
- relations: :relations,
126
- mappers: :mappers,
127
- commands: :commands
128
- },
129
- namespace: 'My::Namespace'
130
- )
131
- end
120
+ describe 'custom namespace' do
121
+ context 'when namespace has subnamespace' do
122
+ before do
123
+ setup.auto_registration(
124
+ SPEC_ROOT.join('fixtures/custom_namespace'),
125
+ component_dirs: {
126
+ relations: :relations,
127
+ mappers: :mappers,
128
+ commands: :commands
129
+ },
130
+ namespace: 'My::Namespace'
131
+ )
132
+ end
132
133
 
133
- describe '#relations' do
134
- it 'loads files and returns constants' do
135
- expect(setup.relation_classes).to eql([My::Namespace::Users])
134
+ describe '#relations' do
135
+ it 'loads files and returns constants' do
136
+ expect(setup.relation_classes).to eql([My::Namespace::Relations::Customers])
137
+ end
138
+ end
139
+
140
+ describe '#commands' do
141
+ it 'loads files and returns constants' do
142
+ expect(setup.command_classes).to eql([My::Namespace::Commands::CreateCustomer])
143
+ end
144
+ end
145
+
146
+ describe '#mappers' do
147
+ it 'loads files and returns constants' do
148
+ expect(setup.mapper_classes).to eql([My::Namespace::Mappers::CustomerList])
149
+ end
136
150
  end
137
151
  end
138
152
 
139
- describe '#commands' do
140
- it 'loads files and returns constants' do
141
- expect(setup.command_classes).to eql([My::Namespace::CreateUser])
153
+ context 'when namespace has wrong subnamespace' do
154
+ subject do
155
+ -> do
156
+ setup.auto_registration(
157
+ SPEC_ROOT.join('fixtures/wrong'),
158
+ component_dirs: {
159
+ relations: :relations,
160
+ mappers: :mappers,
161
+ commands: :commands
162
+ },
163
+ namespace: 'My::NewNamespace'
164
+ )
165
+ end
166
+ end
167
+
168
+ describe '#relations' do
169
+ it { is_expected.to raise_exception NameError }
170
+ end
171
+
172
+ describe '#commands' do
173
+ it { is_expected.to raise_exception NameError }
174
+ end
175
+
176
+ describe '#mappers' do
177
+ it { is_expected.to raise_exception NameError }
142
178
  end
143
179
  end
144
180
 
145
- describe '#mappers' do
146
- it 'loads files and returns constants' do
147
- expect(setup.mapper_classes).to eql([My::Namespace::UserList])
181
+ context 'when namespace does not implement subnamespace' do
182
+ before do
183
+ setup.auto_registration(
184
+ SPEC_ROOT.join('fixtures/custom'),
185
+ component_dirs: {
186
+ relations: :relations,
187
+ mappers: :mappers,
188
+ commands: :commands
189
+ },
190
+ namespace: 'My::Namespace'
191
+ )
192
+ end
193
+
194
+ describe '#relations' do
195
+ it 'loads files and returns constants' do
196
+ expect(setup.relation_classes).to eql([My::Namespace::Users])
197
+ end
198
+ end
199
+
200
+ describe '#commands' do
201
+ it 'loads files and returns constants' do
202
+ expect(setup.command_classes).to eql([My::Namespace::CreateUser])
203
+ end
204
+ end
205
+
206
+ describe '#mappers' do
207
+ it 'loads files and returns constants' do
208
+ expect(setup.mapper_classes).to eql([My::Namespace::UserList])
209
+ end
148
210
  end
149
211
  end
150
212
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rom
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.2.2
4
+ version: 3.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Piotr Solnica
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-05-05 00:00:00.000000000 Z
11
+ date: 2017-05-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -258,12 +258,18 @@ files:
258
258
  - spec/fixtures/custom/commands/create_user.rb
259
259
  - spec/fixtures/custom/mappers/user_list.rb
260
260
  - spec/fixtures/custom/relations/users.rb
261
+ - spec/fixtures/custom_namespace/commands/create_customer.rb
262
+ - spec/fixtures/custom_namespace/mappers/customer_list.rb
263
+ - spec/fixtures/custom_namespace/relations/customers.rb
261
264
  - spec/fixtures/lib/persistence/commands/create_user.rb
262
265
  - spec/fixtures/lib/persistence/mappers/user_list.rb
263
266
  - spec/fixtures/lib/persistence/my_commands/create_user.rb
264
267
  - spec/fixtures/lib/persistence/my_mappers/user_list.rb
265
268
  - spec/fixtures/lib/persistence/my_relations/users.rb
266
269
  - spec/fixtures/lib/persistence/relations/users.rb
270
+ - spec/fixtures/wrong/commands/create_customer.rb
271
+ - spec/fixtures/wrong/mappers/customer_list.rb
272
+ - spec/fixtures/wrong/relations/customers.rb
267
273
  - spec/integration/command_registry_spec.rb
268
274
  - spec/integration/commands/create_spec.rb
269
275
  - spec/integration/commands/delete_spec.rb
@@ -353,6 +359,7 @@ files:
353
359
  - spec/unit/rom/relation/curried_spec.rb
354
360
  - spec/unit/rom/relation/graph_spec.rb
355
361
  - spec/unit/rom/relation/lazy/combine_spec.rb
362
+ - spec/unit/rom/relation/lazy/graph_spec.rb
356
363
  - spec/unit/rom/relation/lazy_spec.rb
357
364
  - spec/unit/rom/relation/loaded_spec.rb
358
365
  - spec/unit/rom/relation/name_spec.rb