rom 0.9.1 → 1.0.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop_todo.yml +30 -12
- data/.travis.yml +1 -1
- data/CHANGELOG.md +24 -0
- data/Gemfile +7 -3
- data/README.md +24 -11
- data/lib/rom.rb +9 -26
- data/lib/rom/command.rb +113 -75
- data/lib/rom/commands/class_interface.rb +115 -0
- data/lib/rom/commands/graph.rb +17 -23
- data/lib/rom/commands/graph/builder.rb +176 -0
- data/lib/rom/commands/graph/class_interface.rb +8 -2
- data/lib/rom/commands/graph/input_evaluator.rb +13 -9
- data/lib/rom/commands/lazy.rb +23 -17
- data/lib/rom/commands/lazy/create.rb +23 -0
- data/lib/rom/commands/lazy/delete.rb +27 -0
- data/lib/rom/commands/lazy/update.rb +34 -0
- data/lib/rom/commands/result.rb +14 -0
- data/lib/rom/commands/update.rb +0 -4
- data/lib/rom/configuration.rb +86 -0
- data/lib/rom/{setup_dsl/setup.rb → configuration_dsl.rb} +9 -7
- data/lib/rom/configuration_dsl/command.rb +43 -0
- data/lib/rom/{setup_dsl → configuration_dsl}/command_dsl.rb +5 -4
- data/lib/rom/configuration_dsl/mapper.rb +37 -0
- data/lib/rom/{setup_dsl → configuration_dsl}/mapper_dsl.rb +11 -5
- data/lib/rom/configuration_dsl/relation.rb +26 -0
- data/lib/rom/configuration_plugin.rb +17 -0
- data/lib/rom/constants.rb +5 -12
- data/lib/rom/container.rb +11 -8
- data/lib/rom/create_container.rb +61 -0
- data/lib/rom/environment.rb +27 -241
- data/lib/rom/gateway.rb +18 -2
- data/lib/rom/global.rb +24 -0
- data/lib/rom/global/plugin_dsl.rb +2 -0
- data/lib/rom/lint/spec.rb +0 -12
- data/lib/rom/lint/test.rb +0 -31
- data/lib/rom/memory/commands.rb +2 -2
- data/lib/rom/memory/gateway.rb +2 -0
- data/lib/rom/pipeline.rb +1 -1
- data/lib/rom/plugin_base.rb +1 -1
- data/lib/rom/plugin_registry.rb +12 -10
- data/lib/rom/plugins/configuration/configuration_dsl.rb +16 -0
- data/lib/rom/plugins/relation/key_inference.rb +31 -0
- data/lib/rom/plugins/relation/view.rb +90 -0
- data/lib/rom/plugins/relation/view/dsl.rb +32 -0
- data/lib/rom/relation.rb +1 -11
- data/lib/rom/relation/class_interface.rb +37 -50
- data/lib/rom/setup.rb +13 -104
- data/lib/rom/setup/auto_registration.rb +55 -0
- data/lib/rom/setup/finalize.rb +113 -127
- data/lib/rom/setup/finalize/commands.rb +67 -0
- data/lib/rom/setup/finalize/mappers.rb +36 -0
- data/lib/rom/setup/finalize/relations.rb +53 -0
- data/lib/rom/support/configurable.rb +21 -7
- data/lib/rom/version.rb +1 -1
- data/rakelib/mutant.rake +4 -1
- data/rom.gemspec +3 -4
- data/spec/fixtures/app/commands/create_user.rb +2 -0
- data/spec/fixtures/app/mappers/user_list.rb +2 -0
- data/spec/fixtures/app/relations/users.rb +2 -0
- data/spec/fixtures/lib/persistence/commands/create_user.rb +6 -0
- data/spec/fixtures/lib/persistence/mappers/user_list.rb +6 -0
- data/spec/fixtures/lib/persistence/relations/users.rb +6 -0
- data/spec/{unit/rom → integration}/command_registry_spec.rb +8 -9
- data/spec/integration/commands/create_spec.rb +17 -13
- data/spec/integration/commands/delete_spec.rb +12 -11
- data/spec/integration/commands/error_handling_spec.rb +5 -4
- data/spec/integration/commands/graph_builder_spec.rb +213 -0
- data/spec/integration/commands/graph_spec.rb +112 -49
- data/spec/integration/commands/update_spec.rb +14 -11
- data/spec/integration/commands_spec.rb +60 -0
- data/spec/integration/mappers/combine_spec.rb +7 -6
- data/spec/integration/mappers/deep_embedded_spec.rb +5 -6
- data/spec/integration/mappers/definition_dsl_spec.rb +19 -18
- data/spec/integration/mappers/embedded_spec.rb +11 -12
- data/spec/integration/mappers/exclude_spec.rb +5 -6
- data/spec/integration/mappers/fold_spec.rb +8 -7
- data/spec/integration/mappers/group_spec.rb +16 -15
- data/spec/integration/mappers/overwrite_attributes_value_spec.rb +5 -5
- data/spec/integration/mappers/prefix_separator_spec.rb +5 -7
- data/spec/integration/mappers/prefix_spec.rb +5 -7
- data/spec/integration/mappers/prefixing_attributes_spec.rb +7 -7
- data/spec/integration/mappers/registering_custom_mappers_spec.rb +4 -5
- data/spec/integration/mappers/renaming_attributes_spec.rb +18 -18
- data/spec/integration/mappers/step_spec.rb +11 -12
- data/spec/integration/mappers/symbolizing_attributes_spec.rb +11 -8
- data/spec/integration/mappers/unfold_spec.rb +9 -10
- data/spec/integration/mappers/ungroup_spec.rb +10 -11
- data/spec/integration/mappers/unwrap_spec.rb +10 -15
- data/spec/integration/mappers/wrap_spec.rb +16 -15
- data/spec/{unit/rom → integration}/memory/commands/create_spec.rb +7 -5
- data/spec/{unit/rom → integration}/memory/commands/delete_spec.rb +7 -5
- data/spec/{unit/rom → integration}/memory/commands/update_spec.rb +7 -5
- data/spec/integration/multi_env_spec.rb +16 -124
- data/spec/integration/multi_repo_spec.rb +9 -9
- data/spec/integration/relations/default_dataset_spec.rb +15 -0
- data/spec/integration/relations/inheritance_spec.rb +5 -7
- data/spec/integration/relations/reading_spec.rb +32 -65
- data/spec/integration/relations/registry_dsl_spec.rb +5 -4
- data/spec/integration/repositories/extending_relations_spec.rb +6 -7
- data/spec/integration/repositories/setting_logger_spec.rb +5 -7
- data/spec/integration/setup_spec.rb +49 -61
- data/spec/shared/command_graph.rb +50 -0
- data/spec/shared/container.rb +9 -0
- data/spec/shared/gateway_only.rb +6 -0
- data/spec/shared/no_container.rb +16 -0
- data/spec/shared/one_behavior.rb +4 -4
- data/spec/shared/users_and_tasks.rb +5 -17
- data/spec/spec_helper.rb +5 -3
- data/spec/test/memory_repository_lint_test.rb +1 -1
- data/spec/unit/rom/auto_registration_spec.rb +54 -0
- data/spec/unit/rom/commands/graph_spec.rb +18 -44
- data/spec/unit/rom/commands/lazy_spec.rb +246 -35
- data/spec/unit/rom/commands/result_spec.rb +56 -0
- data/spec/unit/rom/commands_spec.rb +9 -73
- data/spec/unit/rom/configurable_spec.rb +49 -0
- data/spec/unit/rom/configuration_spec.rb +61 -0
- data/spec/unit/rom/container_spec.rb +39 -33
- data/spec/unit/rom/create_container_spec.rb +151 -0
- data/spec/unit/rom/environment_spec.rb +123 -0
- data/spec/unit/rom/gateway_spec.rb +58 -2
- data/spec/unit/rom/global_spec.rb +10 -7
- data/spec/unit/rom/plugin_spec.rb +44 -25
- data/spec/unit/rom/plugins/relation/key_inference_spec.rb +27 -0
- data/spec/unit/rom/plugins/relation/view_spec.rb +47 -0
- data/spec/unit/rom/relation/composite_spec.rb +20 -20
- data/spec/unit/rom/relation/curried_spec.rb +10 -11
- data/spec/unit/rom/relation/graph_spec.rb +27 -27
- data/spec/unit/rom/relation/lazy/combine_spec.rb +26 -20
- data/spec/unit/rom/relation/lazy_spec.rb +38 -38
- data/spec/unit/rom/relation/loaded_spec.rb +2 -3
- data/spec/unit/rom/relation_spec.rb +39 -2
- metadata +58 -66
- data/lib/rom/commands/abstract.rb +0 -184
- data/lib/rom/environment_plugin.rb +0 -17
- data/lib/rom/environment_plugins/auto_registration.rb +0 -38
- data/lib/rom/repository.rb +0 -16
- data/lib/rom/setup_dsl/command.rb +0 -36
- data/lib/rom/setup_dsl/mapper.rb +0 -32
- data/lib/rom/setup_dsl/relation.rb +0 -30
- data/spec/integration/inline_setup_spec.rb +0 -65
- data/spec/unit/rom/repository_spec.rb +0 -12
- data/spec/unit/rom/setup_spec.rb +0 -253
@@ -1,16 +1,11 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe ROM::Relation::Composite do
|
4
|
+
include_context 'gateway only'
|
4
5
|
include_context 'users and tasks'
|
5
6
|
|
6
|
-
let(:
|
7
|
-
|
8
|
-
|
9
|
-
let(:name_list) { proc { |r| r.map { |t| t[:name] } } }
|
10
|
-
let(:upcaser) { proc { |r| r.map(&:upcase) } }
|
11
|
-
|
12
|
-
before do
|
13
|
-
setup.relation(:users) do
|
7
|
+
let(:users_relation) do
|
8
|
+
Class.new(ROM::Memory::Relation) do
|
14
9
|
def by_name(name)
|
15
10
|
restrict(name: name)
|
16
11
|
end
|
@@ -18,30 +13,35 @@ describe ROM::Relation::Composite do
|
|
18
13
|
def sorted(other)
|
19
14
|
other.source.order(:name)
|
20
15
|
end
|
21
|
-
end
|
16
|
+
end.new(users_dataset)
|
17
|
+
end
|
22
18
|
|
23
|
-
|
19
|
+
let(:tasks_relation) do
|
20
|
+
Class.new(ROM::Memory::Relation) do
|
24
21
|
def for_users(users)
|
25
22
|
restrict(name: users.map { |u| u[:name] })
|
26
23
|
end
|
27
|
-
end
|
24
|
+
end.new(tasks_dataset)
|
28
25
|
end
|
29
26
|
|
27
|
+
let(:name_list) { proc { |r| r.map { |t| t[:name] } } }
|
28
|
+
let(:upcaser) { proc { |r| r.map(&:upcase) } }
|
29
|
+
|
30
30
|
describe '#call' do
|
31
31
|
it 'sends a relation through mappers' do
|
32
|
-
relation =
|
32
|
+
relation = users_relation >> name_list >> upcaser
|
33
33
|
loaded = relation.call
|
34
34
|
|
35
|
-
expect(loaded.source).to eql(
|
35
|
+
expect(loaded.source).to eql(users_relation)
|
36
36
|
|
37
37
|
expect(loaded).to match_array(%w(JANE JOE))
|
38
38
|
end
|
39
39
|
|
40
40
|
it 'sends a relation through another relation' do
|
41
|
-
relation =
|
41
|
+
relation = users_relation >> users_relation.sorted
|
42
42
|
loaded = relation.call
|
43
43
|
|
44
|
-
expect(loaded.source).to eql(
|
44
|
+
expect(loaded.source).to eql(users_relation.sorted(users_relation.call))
|
45
45
|
|
46
46
|
expect(loaded).to match_array([
|
47
47
|
{ name: 'Jane', email: 'jane@doe.org' },
|
@@ -50,12 +50,12 @@ describe ROM::Relation::Composite do
|
|
50
50
|
end
|
51
51
|
|
52
52
|
it 'sends a relation through another composite relation' do
|
53
|
-
task_mapper = ->
|
54
|
-
relation =
|
53
|
+
task_mapper = -> tasks_relation { tasks_relation }
|
54
|
+
relation = users_relation.by_name('Jane') >> (tasks_relation.for_users >> task_mapper)
|
55
55
|
|
56
56
|
loaded = relation.call
|
57
57
|
|
58
|
-
expect(loaded.source).to eql(
|
58
|
+
expect(loaded.source).to eql(tasks_relation.for_users(users_relation.by_name('Jane')))
|
59
59
|
|
60
60
|
expect(loaded).to match_array([
|
61
61
|
{ name: 'Jane', title: 'be cool', priority: 2 }
|
@@ -64,7 +64,7 @@ describe ROM::Relation::Composite do
|
|
64
64
|
end
|
65
65
|
|
66
66
|
describe '#each' do
|
67
|
-
let(:relation) {
|
67
|
+
let(:relation) { users_relation >> name_list >> upcaser }
|
68
68
|
|
69
69
|
it 'calls and iterates' do
|
70
70
|
result = []
|
@@ -80,7 +80,7 @@ describe ROM::Relation::Composite do
|
|
80
80
|
end
|
81
81
|
|
82
82
|
describe '#first' do
|
83
|
-
let(:relation) {
|
83
|
+
let(:relation) { users_relation >> name_list >> upcaser }
|
84
84
|
|
85
85
|
it 'calls and returns the first object' do
|
86
86
|
expect(relation.first).to eql('JOE')
|
@@ -1,12 +1,11 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
RSpec.describe ROM::Relation::Curried do
|
4
|
+
include_context 'gateway only'
|
4
5
|
include_context 'users and tasks'
|
5
6
|
|
6
|
-
let(:
|
7
|
-
|
8
|
-
before do
|
9
|
-
setup.relation(:users) do
|
7
|
+
let(:users_relation) do
|
8
|
+
Class.new(ROM::Memory::Relation) do
|
10
9
|
def by_name(name)
|
11
10
|
restrict(name: name)
|
12
11
|
end
|
@@ -14,11 +13,11 @@ RSpec.describe ROM::Relation::Curried do
|
|
14
13
|
def find(criteria)
|
15
14
|
restrict(criteria)
|
16
15
|
end
|
17
|
-
end
|
16
|
+
end.new(users_dataset)
|
18
17
|
end
|
19
18
|
|
20
19
|
describe '#call' do
|
21
|
-
let(:relation) {
|
20
|
+
let(:relation) { users_relation.by_name.call('Jane') }
|
22
21
|
|
23
22
|
it 'materializes a relation' do
|
24
23
|
expect(relation).to match_array([
|
@@ -27,27 +26,27 @@ RSpec.describe ROM::Relation::Curried do
|
|
27
26
|
end
|
28
27
|
|
29
28
|
it 'returns a loaded relation' do
|
30
|
-
expect(relation.source).to eql(
|
29
|
+
expect(relation.source).to eql(users_relation.by_name('Jane'))
|
31
30
|
end
|
32
31
|
end
|
33
32
|
|
34
33
|
describe '#respond_to?' do
|
35
34
|
it 'returns true if wrapped relation responds to a method' do
|
36
|
-
expect(
|
35
|
+
expect(users_relation.by_name).to respond_to(:dataset)
|
37
36
|
end
|
38
37
|
|
39
38
|
it 'returns false if wrapped relation does not respond to a method' do
|
40
|
-
expect(
|
39
|
+
expect(users_relation.by_name).not_to respond_to(:not_here)
|
41
40
|
end
|
42
41
|
end
|
43
42
|
|
44
43
|
describe '#method_missing' do
|
45
44
|
it 'forwards to the relation' do
|
46
|
-
expect(
|
45
|
+
expect(users_relation.by_name.dataset).to eql(users_relation.dataset)
|
47
46
|
end
|
48
47
|
|
49
48
|
it 'does not forward to the relation when method is auto-curried' do
|
50
|
-
expect {
|
49
|
+
expect { users_relation.by_name.find }.to raise_error(NoMethodError, /find/)
|
51
50
|
end
|
52
51
|
end
|
53
52
|
end
|
@@ -1,36 +1,36 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe ROM::Relation::Graph do
|
4
|
-
|
5
|
-
|
4
|
+
include_context 'gateway only'
|
6
5
|
include_context 'users and tasks'
|
7
6
|
|
8
|
-
|
9
|
-
|
10
|
-
T(:combine, [[:tasks, name: :name]])
|
11
|
-
end
|
12
|
-
|
13
|
-
let(:relation) do
|
14
|
-
ROM::Relation::Graph.new(users.by_name('Jane'), [tasks.for_users]) >> mapper
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
before do
|
19
|
-
setup.relation(:users) do
|
7
|
+
let(:users_relation) do
|
8
|
+
Class.new(ROM::Memory::Relation) do
|
20
9
|
def by_name(name)
|
21
10
|
restrict(name: name)
|
22
11
|
end
|
23
|
-
end
|
12
|
+
end.new(users_dataset)
|
13
|
+
end
|
24
14
|
|
25
|
-
|
15
|
+
let(:tasks_relation) do
|
16
|
+
Class.new(ROM::Memory::Relation) do
|
26
17
|
def for_users(_users)
|
27
18
|
self
|
28
19
|
end
|
29
|
-
end
|
20
|
+
end.new(tasks_dataset)
|
30
21
|
end
|
31
22
|
|
32
|
-
|
33
|
-
|
23
|
+
subject(:graph) { ROM::Relation::Graph.new(users_relation, [tasks_relation.for_users]) }
|
24
|
+
|
25
|
+
it_behaves_like 'materializable relation' do
|
26
|
+
let(:mapper) do
|
27
|
+
T(:combine, [[:tasks, name: :name]])
|
28
|
+
end
|
29
|
+
|
30
|
+
let(:relation) do
|
31
|
+
ROM::Relation::Graph.new(users_relation.by_name('Jane'), [tasks_relation.for_users]) >> mapper
|
32
|
+
end
|
33
|
+
end
|
34
34
|
|
35
35
|
describe '#method_missing' do
|
36
36
|
it 'responds to the root methods' do
|
@@ -42,11 +42,11 @@ describe ROM::Relation::Graph do
|
|
42
42
|
end
|
43
43
|
|
44
44
|
it 'forwards methods to the root and decorates curried response' do
|
45
|
-
expect((
|
45
|
+
expect((users_relation.combine(tasks_relation.for_users)).by_name).to be_instance_of(ROM::Relation::Graph)
|
46
46
|
end
|
47
47
|
|
48
48
|
it 'returns original response from the root' do
|
49
|
-
expect(graph.mappers).to eql(
|
49
|
+
expect(graph.mappers).to eql(users_relation.mappers)
|
50
50
|
end
|
51
51
|
|
52
52
|
it 'raises method error' do
|
@@ -57,8 +57,8 @@ describe ROM::Relation::Graph do
|
|
57
57
|
describe '#call' do
|
58
58
|
it 'materializes relations' do
|
59
59
|
expect(graph.call).to match_array([
|
60
|
-
|
61
|
-
[
|
60
|
+
users_relation,
|
61
|
+
[tasks_relation]
|
62
62
|
])
|
63
63
|
end
|
64
64
|
end
|
@@ -66,16 +66,16 @@ describe ROM::Relation::Graph do
|
|
66
66
|
describe '#to_a' do
|
67
67
|
it 'coerces to an array' do
|
68
68
|
expect(graph).to match_array([
|
69
|
-
|
70
|
-
[
|
69
|
+
users_relation.to_a,
|
70
|
+
[tasks_relation.for_users(users_relation).to_a]
|
71
71
|
])
|
72
72
|
end
|
73
73
|
|
74
74
|
it 'returns empty arrays when left was empty' do
|
75
|
-
graph = ROM::Relation::Graph.new(
|
75
|
+
graph = ROM::Relation::Graph.new(users_relation.by_name('Not here'), [tasks_relation.for_users])
|
76
76
|
|
77
77
|
expect(graph).to match_array([
|
78
|
-
[], [ROM::Relation::Loaded.new(
|
78
|
+
[], [ROM::Relation::Loaded.new(tasks_relation.for_users, [])]
|
79
79
|
])
|
80
80
|
end
|
81
81
|
end
|
@@ -1,23 +1,31 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe ROM::Relation, '#combine' do
|
4
|
+
include_context 'gateway only'
|
4
5
|
include_context 'users and tasks'
|
5
6
|
|
6
|
-
|
7
|
-
|
7
|
+
let(:tags_dataset) { gateway.dataset(:tags) }
|
8
|
+
|
9
|
+
let(:users_relation) do
|
10
|
+
Class.new(ROM::Memory::Relation) do
|
8
11
|
def by_name(name)
|
9
12
|
restrict(name: name)
|
10
13
|
end
|
11
|
-
end
|
14
|
+
end.new(users_dataset)
|
15
|
+
end
|
12
16
|
|
13
|
-
|
17
|
+
let(:tasks_relation) do
|
18
|
+
Class.new(ROM::Memory::Relation) do
|
14
19
|
def for_users(users)
|
15
20
|
names = users.map { |user| user[:name] }
|
16
21
|
restrict { |task| names.include?(task[:name]) }
|
17
22
|
end
|
18
|
-
end
|
23
|
+
end.new(tasks_dataset)
|
24
|
+
end
|
19
25
|
|
20
|
-
|
26
|
+
let(:tags_relation) do
|
27
|
+
Class.new(ROM::Memory::Relation) do
|
28
|
+
attr_accessor :tasks
|
21
29
|
forward :map
|
22
30
|
|
23
31
|
def for_tasks(tasks)
|
@@ -34,15 +42,13 @@ describe ROM::Relation, '#combine' do
|
|
34
42
|
} [:name])
|
35
43
|
}
|
36
44
|
end
|
37
|
-
end
|
38
|
-
|
39
|
-
setup.gateways[:default].dataset(:tags).insert(task: 'be cool', name: 'red')
|
40
|
-
setup.gateways[:default].dataset(:tags).insert(task: 'be cool', name: 'green')
|
45
|
+
end.new(tags_dataset).tap { |r| r.tasks = tasks_relation }
|
41
46
|
end
|
42
47
|
|
43
|
-
|
44
|
-
|
45
|
-
|
48
|
+
before do
|
49
|
+
tags_dataset.insert(task: 'be cool', name: 'red')
|
50
|
+
tags_dataset.insert(task: 'be cool', name: 'green')
|
51
|
+
end
|
46
52
|
|
47
53
|
let(:map_users) {
|
48
54
|
proc { |users, tasks|
|
@@ -87,7 +93,7 @@ describe ROM::Relation, '#combine' do
|
|
87
93
|
|
88
94
|
it 'raises error when composite relation is passed as a node' do
|
89
95
|
expect {
|
90
|
-
|
96
|
+
users_relation.combine(tasks_relation >> proc {})
|
91
97
|
}.to raise_error(ROM::UnsupportedRelationError)
|
92
98
|
end
|
93
99
|
|
@@ -106,8 +112,8 @@ describe ROM::Relation, '#combine' do
|
|
106
112
|
}
|
107
113
|
]
|
108
114
|
|
109
|
-
user_with_tasks_and_tags =
|
110
|
-
.combine(
|
115
|
+
user_with_tasks_and_tags = users_relation.by_name('Jane')
|
116
|
+
.combine(tasks_relation.for_users, tags_relation.for_users)
|
111
117
|
|
112
118
|
result = user_with_tasks_and_tags >> map_user_with_tasks_and_tags
|
113
119
|
|
@@ -129,8 +135,8 @@ describe ROM::Relation, '#combine' do
|
|
129
135
|
}
|
130
136
|
]
|
131
137
|
|
132
|
-
user_with_tasks_and_tags =
|
133
|
-
.combine(
|
138
|
+
user_with_tasks_and_tags = users_relation.by_name('Jane')
|
139
|
+
.combine(tasks_relation.for_users).combine(tags_relation.for_users)
|
134
140
|
|
135
141
|
result = user_with_tasks_and_tags >> map_user_with_tasks_and_tags
|
136
142
|
|
@@ -149,8 +155,8 @@ describe ROM::Relation, '#combine' do
|
|
149
155
|
}
|
150
156
|
]
|
151
157
|
|
152
|
-
user_with_tasks =
|
153
|
-
.combine(
|
158
|
+
user_with_tasks = users_relation.by_name('Jane')
|
159
|
+
.combine(tasks_relation.for_users.combine(tags_relation.for_tasks))
|
154
160
|
|
155
161
|
result = user_with_tasks >> map_user_with_tasks
|
156
162
|
|
@@ -1,13 +1,11 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe ROM::Relation do
|
4
|
+
include_context 'gateway only'
|
4
5
|
include_context 'users and tasks'
|
5
6
|
|
6
|
-
let(:
|
7
|
-
|
8
|
-
|
9
|
-
before do
|
10
|
-
setup.relation(:users) do
|
7
|
+
let(:users_relation) do
|
8
|
+
Class.new(ROM::Memory::Relation) do
|
11
9
|
def by_name(name)
|
12
10
|
restrict(name: name)
|
13
11
|
end
|
@@ -35,31 +33,33 @@ describe ROM::Relation do
|
|
35
33
|
self
|
36
34
|
end
|
37
35
|
end
|
38
|
-
end
|
36
|
+
end.new(users_dataset)
|
37
|
+
end
|
39
38
|
|
40
|
-
|
39
|
+
let(:tasks_relation) do
|
40
|
+
Class.new(ROM::Memory::Relation) do
|
41
41
|
def for_users(users)
|
42
42
|
names = users.map { |u| u[:name] }
|
43
43
|
restrict { |t| names.include?(t[:name]) }
|
44
44
|
end
|
45
|
-
end
|
45
|
+
end.new(tasks_dataset)
|
46
46
|
end
|
47
47
|
|
48
48
|
it_behaves_like 'a relation that returns one tuple' do
|
49
|
-
let(:relation) {
|
49
|
+
let(:relation) { users_relation }
|
50
50
|
end
|
51
51
|
|
52
52
|
describe '#map_with' do
|
53
53
|
it 'raises error when unknown mapper was selected' do
|
54
54
|
expect {
|
55
|
-
|
55
|
+
users_relation.as(:not_here)
|
56
56
|
}.to raise_error(ROM::MapperMissingError, /not_here/)
|
57
57
|
end
|
58
58
|
end
|
59
59
|
|
60
60
|
describe '#method_missing' do
|
61
61
|
it 'forwards to relation and auto-curries' do
|
62
|
-
relation =
|
62
|
+
relation = users_relation.by_name_and_email_sorted('Jane')
|
63
63
|
|
64
64
|
expect(relation.name).to eql(:by_name_and_email_sorted)
|
65
65
|
expect(relation.curry_args).to eql(['Jane'])
|
@@ -70,46 +70,46 @@ describe ROM::Relation do
|
|
70
70
|
expect(relation.curry_args).to eql(['Jane', 'jane@doe.org'])
|
71
71
|
|
72
72
|
expect(relation[:email]).to match_array(
|
73
|
-
|
73
|
+
users_relation.by_name_and_email_sorted('Jane', 'jane@doe.org', :email)
|
74
74
|
)
|
75
75
|
end
|
76
76
|
|
77
77
|
it 'forwards to relation and does not auto-curry when it is not needed' do
|
78
|
-
relation =
|
78
|
+
relation = users_relation.by_name('Jane')
|
79
79
|
|
80
80
|
expect(relation).to_not be_curried
|
81
|
-
expect(relation).to match_array(
|
81
|
+
expect(relation).to match_array(users_relation.by_name('Jane'))
|
82
82
|
end
|
83
83
|
|
84
84
|
it 'forwards to relation and return lazy when arity is unknown' do
|
85
|
-
relation =
|
85
|
+
relation = users_relation.all(name: 'Jane')
|
86
86
|
expect(relation).to_not be_curried
|
87
|
-
expect(relation).to match_array(
|
87
|
+
expect(relation).to match_array(users_relation.by_name('Jane').to_a)
|
88
88
|
end
|
89
89
|
|
90
90
|
it 'returns original response if it is not a relation' do
|
91
|
-
expect(
|
91
|
+
expect(users_relation.gateway).to be(:default)
|
92
92
|
end
|
93
93
|
|
94
94
|
it 'raises NoMethodError when relation does not respond to a method' do
|
95
|
-
expect {
|
95
|
+
expect { users_relation.not_here }.to raise_error(NoMethodError, /not_here/)
|
96
96
|
end
|
97
97
|
end
|
98
98
|
|
99
99
|
describe '#call' do
|
100
100
|
it 'auto-curries' do
|
101
|
-
relation =
|
101
|
+
relation = users_relation.by_name
|
102
102
|
|
103
103
|
expect(relation.name).to eql(:by_name)
|
104
|
-
expect(relation['Jane'].to_a).to eql(
|
104
|
+
expect(relation['Jane'].to_a).to eql(users_relation.by_name('Jane').to_a)
|
105
105
|
end
|
106
106
|
|
107
107
|
it 'returns relation' do
|
108
|
-
expect(
|
108
|
+
expect(users_relation.call.to_a).to eql(users_relation.to_a)
|
109
109
|
end
|
110
110
|
|
111
111
|
describe 'using mappers' do
|
112
|
-
subject(:users) {
|
112
|
+
subject(:users) { users_relation.with(mappers: mappers) }
|
113
113
|
|
114
114
|
let(:name_list) { proc { |r| r.map { |t| t[:name] } } }
|
115
115
|
let(:upcaser) { proc { |r| r.map(&:upcase) } }
|
@@ -125,24 +125,24 @@ describe ROM::Relation do
|
|
125
125
|
|
126
126
|
describe '#first' do
|
127
127
|
it 'return first tuple' do
|
128
|
-
expect(
|
128
|
+
expect(users_relation.first).to eql(name: 'Joe', email: 'joe@doe.org')
|
129
129
|
end
|
130
130
|
|
131
131
|
it 'raises when relation is curried and arity does not match' do
|
132
|
-
expect {
|
133
|
-
ArgumentError,
|
132
|
+
expect { users_relation.by_name.first }.to raise_error(
|
133
|
+
ArgumentError, "#{users_relation.class.to_s}#by_name arity is 1 (0 args given)"
|
134
134
|
)
|
135
135
|
end
|
136
136
|
|
137
137
|
it 'does not raise when relation is curried and arity matches' do
|
138
|
-
expect {
|
138
|
+
expect { users_relation.by_name_sorted('Joe').first }.to_not raise_error
|
139
139
|
end
|
140
140
|
end
|
141
141
|
|
142
142
|
describe '#each' do
|
143
143
|
it 'yields relation tuples' do
|
144
144
|
result = []
|
145
|
-
|
145
|
+
users_relation.each do |tuple|
|
146
146
|
result << tuple
|
147
147
|
end
|
148
148
|
expect(result).to match_array([
|
@@ -152,45 +152,45 @@ describe ROM::Relation do
|
|
152
152
|
end
|
153
153
|
|
154
154
|
it 'returns an enumerator if block is not provided' do
|
155
|
-
expect(
|
155
|
+
expect(users_relation.each.to_a).to match_array([
|
156
156
|
{ name: 'Jane', email: 'jane@doe.org' },
|
157
157
|
{ name: 'Joe', email: 'joe@doe.org' }
|
158
158
|
])
|
159
159
|
end
|
160
160
|
|
161
161
|
it 'raises when relation is curried and arity does not match' do
|
162
|
-
expect {
|
163
|
-
ArgumentError,
|
162
|
+
expect { users_relation.by_name.each {} }.to raise_error(
|
163
|
+
ArgumentError, "#{users_relation.class.to_s}#by_name arity is 1 (0 args given)"
|
164
164
|
)
|
165
165
|
end
|
166
166
|
|
167
167
|
it 'does not raise when relation is curried and arity matches' do
|
168
|
-
expect {
|
168
|
+
expect { users_relation.by_name_sorted('Jane').first }.to_not raise_error
|
169
169
|
end
|
170
170
|
end
|
171
171
|
|
172
172
|
describe '#to_ary' do
|
173
173
|
it 'returns an array with relation tuples' do
|
174
|
-
expect(
|
174
|
+
expect(users_relation.to_ary).to match_array([
|
175
175
|
{ name: 'Jane', email: 'jane@doe.org' },
|
176
176
|
{ name: 'Joe', email: 'joe@doe.org' }
|
177
177
|
])
|
178
178
|
end
|
179
179
|
|
180
180
|
it 'raises when relation is curried and arity does not match' do
|
181
|
-
expect {
|
182
|
-
ArgumentError,
|
181
|
+
expect { users_relation.by_name.to_ary }.to raise_error(
|
182
|
+
ArgumentError, "#{users_relation.class.to_s}#by_name arity is 1 (0 args given)"
|
183
183
|
)
|
184
184
|
end
|
185
185
|
|
186
186
|
it 'does not raise when relation is curried and arity matches' do
|
187
|
-
expect {
|
187
|
+
expect { users_relation.by_name_sorted('Jane').first }.to_not raise_error
|
188
188
|
end
|
189
189
|
end
|
190
190
|
|
191
191
|
describe '#>>' do
|
192
192
|
it 'composes two relations' do
|
193
|
-
other =
|
193
|
+
other = users_relation.by_name('Jane') >> tasks_relation.for_users
|
194
194
|
|
195
195
|
expect(other).to match_array([
|
196
196
|
{ name: 'Jane', title: 'be cool', priority: 2 }
|
@@ -198,12 +198,12 @@ describe ROM::Relation do
|
|
198
198
|
end
|
199
199
|
|
200
200
|
it_behaves_like 'a relation that returns one tuple' do
|
201
|
-
let(:relation) {
|
201
|
+
let(:relation) { users_relation >> proc { |r| r } }
|
202
202
|
|
203
203
|
describe 'using a mapper' do
|
204
204
|
it 'returns one mapped tuple' do
|
205
205
|
mapper = proc { |r| r.map { |t| t[:name].upcase } }
|
206
|
-
relation =
|
206
|
+
relation = users_relation.by_name('Jane') >> mapper
|
207
207
|
|
208
208
|
expect(relation.one).to eql('JANE')
|
209
209
|
expect(relation.one!).to eql('JANE')
|