rom 3.2.2 → 3.2.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +21 -1
- data/Gemfile +1 -1
- data/README.md +72 -4
- data/lib/rom/auto_curry.rb +2 -2
- data/lib/rom/relation.rb +4 -1
- data/lib/rom/relation/graph.rb +6 -1
- data/lib/rom/setup/auto_registration.rb +3 -2
- data/lib/rom/setup/auto_registration_strategies/base.rb +1 -1
- data/lib/rom/setup/auto_registration_strategies/custom_namespace.rb +41 -1
- data/lib/rom/version.rb +1 -1
- data/spec/fixtures/custom_namespace/commands/create_customer.rb +8 -0
- data/spec/fixtures/custom_namespace/mappers/customer_list.rb +8 -0
- data/spec/fixtures/custom_namespace/relations/customers.rb +8 -0
- data/spec/fixtures/wrong/commands/create_customer.rb +8 -0
- data/spec/fixtures/wrong/mappers/customer_list.rb +8 -0
- data/spec/fixtures/wrong/relations/customers.rb +8 -0
- data/spec/spec_helper.rb +2 -0
- data/spec/unit/rom/auto_curry_spec.rb +9 -1
- data/spec/unit/rom/relation/lazy/combine_spec.rb +4 -4
- data/spec/unit/rom/relation/lazy/graph_spec.rb +165 -0
- data/spec/unit/rom/setup/auto_registration_spec.rb +83 -21
- metadata +9 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0f727af1309d22c607fa43b3c26345749233dbef
|
4
|
+
data.tar.gz: 7a1d5142394e77da212457c8d656ca2d9d632759
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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: '
|
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
|
-
##
|
27
|
-
|
28
|
-
|
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
|
|
data/lib/rom/auto_curry.rb
CHANGED
@@ -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
|
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
|
#
|
data/lib/rom/relation/graph.rb
CHANGED
@@ -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
|
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("#{
|
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
|
@@ -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
|
-
|
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
data/spec/spec_helper.rb
CHANGED
@@ -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
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
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
|
-
|
134
|
-
|
135
|
-
|
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
|
-
|
140
|
-
|
141
|
-
|
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
|
-
|
146
|
-
|
147
|
-
|
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.
|
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-
|
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
|