rom-repository 1.4.0 → 2.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +14 -6
- data/{LICENSE.txt → LICENSE} +1 -1
- data/README.md +18 -1
- data/lib/rom-repository.rb +1 -2
- data/lib/rom/repository.rb +9 -216
- data/lib/rom/repository/class_interface.rb +16 -33
- data/lib/rom/repository/relation_reader.rb +46 -0
- data/lib/rom/repository/root.rb +3 -59
- data/lib/rom/repository/version.rb +1 -1
- metadata +9 -98
- data/.gitignore +0 -3
- data/.rspec +0 -3
- data/.travis.yml +0 -27
- data/.yardopts +0 -2
- data/Gemfile +0 -38
- data/Rakefile +0 -19
- data/lib/rom/open_struct.rb +0 -35
- data/lib/rom/repository/changeset.rb +0 -155
- data/lib/rom/repository/changeset/associated.rb +0 -100
- data/lib/rom/repository/changeset/create.rb +0 -16
- data/lib/rom/repository/changeset/delete.rb +0 -17
- data/lib/rom/repository/changeset/pipe.rb +0 -97
- data/lib/rom/repository/changeset/restricted.rb +0 -28
- data/lib/rom/repository/changeset/stateful.rb +0 -282
- data/lib/rom/repository/changeset/update.rb +0 -82
- data/lib/rom/repository/command_compiler.rb +0 -257
- data/lib/rom/repository/command_proxy.rb +0 -26
- data/lib/rom/repository/header_builder.rb +0 -65
- data/lib/rom/repository/mapper_builder.rb +0 -23
- data/lib/rom/repository/relation_proxy.rb +0 -337
- data/lib/rom/repository/relation_proxy/combine.rb +0 -320
- data/lib/rom/repository/relation_proxy/wrap.rb +0 -78
- data/lib/rom/repository/struct_builder.rb +0 -83
- data/lib/rom/struct.rb +0 -113
- data/log/.gitkeep +0 -0
- data/rom-repository.gemspec +0 -23
- data/spec/integration/changeset_spec.rb +0 -193
- data/spec/integration/command_macros_spec.rb +0 -191
- data/spec/integration/command_spec.rb +0 -228
- data/spec/integration/multi_adapter_spec.rb +0 -73
- data/spec/integration/repository/aggregate_spec.rb +0 -58
- data/spec/integration/repository_spec.rb +0 -406
- data/spec/integration/root_repository_spec.rb +0 -106
- data/spec/integration/typed_structs_spec.rb +0 -64
- data/spec/shared/database.rb +0 -79
- data/spec/shared/mappers.rb +0 -35
- data/spec/shared/models.rb +0 -41
- data/spec/shared/plugins.rb +0 -66
- data/spec/shared/relations.rb +0 -115
- data/spec/shared/repo.rb +0 -86
- data/spec/shared/seeds.rb +0 -30
- data/spec/shared/structs.rb +0 -140
- data/spec/spec_helper.rb +0 -83
- data/spec/support/mapper_registry.rb +0 -9
- data/spec/support/mutant.rb +0 -10
- data/spec/unit/changeset/associate_spec.rb +0 -120
- data/spec/unit/changeset/map_spec.rb +0 -111
- data/spec/unit/changeset_spec.rb +0 -186
- data/spec/unit/relation_proxy_spec.rb +0 -202
- data/spec/unit/repository/changeset_spec.rb +0 -197
- data/spec/unit/repository/inspect_spec.rb +0 -18
- data/spec/unit/repository/session_spec.rb +0 -251
- data/spec/unit/repository/transaction_spec.rb +0 -42
- data/spec/unit/session_spec.rb +0 -46
- data/spec/unit/struct_builder_spec.rb +0 -128
@@ -1,191 +0,0 @@
|
|
1
|
-
RSpec.describe ROM::Repository, '.command' do
|
2
|
-
include_context 'database'
|
3
|
-
include_context 'relations'
|
4
|
-
|
5
|
-
it 'allows configuring a create command' do
|
6
|
-
repo = Class.new(ROM::Repository[:users]) do
|
7
|
-
commands :create
|
8
|
-
end.new(rom)
|
9
|
-
|
10
|
-
user = repo.create(name: 'Jane')
|
11
|
-
|
12
|
-
expect(user.id).to_not be(nil)
|
13
|
-
expect(user.name).to eql('Jane')
|
14
|
-
end
|
15
|
-
|
16
|
-
it 'allows configuring an update and delete commands' do
|
17
|
-
repo = Class.new(ROM::Repository[:users]) do
|
18
|
-
commands :create, update: :by_pk, delete: :by_pk
|
19
|
-
end.new(rom)
|
20
|
-
|
21
|
-
user = repo.create(name: 'Jane')
|
22
|
-
|
23
|
-
repo.update(user.id, name: 'Jane Doe')
|
24
|
-
|
25
|
-
user = repo.users.by_pk(user.id).one
|
26
|
-
|
27
|
-
expect(user.name).to eql('Jane Doe')
|
28
|
-
|
29
|
-
repo.delete(user.id)
|
30
|
-
|
31
|
-
expect(repo.users.by_pk(user.id).one).to be(nil)
|
32
|
-
end
|
33
|
-
|
34
|
-
it 'configures an update command with custom restriction' do
|
35
|
-
repo = Class.new(ROM::Repository[:users]) do
|
36
|
-
commands update: :by_name
|
37
|
-
end.new(rom)
|
38
|
-
|
39
|
-
repo.relations.users.insert(name: 'Jade')
|
40
|
-
|
41
|
-
user = repo.update('Jade', name: 'Jade Doe')
|
42
|
-
expect(user.name).to eql('Jade Doe')
|
43
|
-
|
44
|
-
expect(repo.update('Oops', name: 'Jade')).to be(nil)
|
45
|
-
end
|
46
|
-
|
47
|
-
it 'allows to configure update command without create one' do
|
48
|
-
repo = Class.new(ROM::Repository[:users]) do
|
49
|
-
commands update: :by_pk
|
50
|
-
end.new(rom)
|
51
|
-
|
52
|
-
user = repo.command(create: :users)[name: 'Jane']
|
53
|
-
|
54
|
-
repo.update(user.id, name: 'Jane Doe')
|
55
|
-
|
56
|
-
updated_user = repo.users.by_pk(user.id).one
|
57
|
-
|
58
|
-
expect(updated_user.name).to eql('Jane Doe')
|
59
|
-
end
|
60
|
-
|
61
|
-
it 'allows to configure :delete command without args' do
|
62
|
-
repo = Class.new(ROM::Repository[:users]) do
|
63
|
-
commands :delete
|
64
|
-
end.new(rom)
|
65
|
-
|
66
|
-
repo.users.insert(name: 'Jane')
|
67
|
-
repo.users.insert(name: 'John')
|
68
|
-
|
69
|
-
repo.delete
|
70
|
-
|
71
|
-
expect(repo.users.count).to be_zero
|
72
|
-
end
|
73
|
-
|
74
|
-
it 'allows defining a single command with multiple views' do
|
75
|
-
repo = Class.new(ROM::Repository[:users]) do
|
76
|
-
commands :create, update: [:by_pk, :by_name]
|
77
|
-
end.new(rom)
|
78
|
-
|
79
|
-
user = repo.create(name: 'Jane')
|
80
|
-
|
81
|
-
repo.update_by_pk(user.id, name: 'Jane Doe')
|
82
|
-
user = repo.users.by_pk(user.id).one
|
83
|
-
expect(user.name).to eql('Jane Doe')
|
84
|
-
|
85
|
-
repo.update_by_name(user.name, name: 'Jane')
|
86
|
-
user = repo.users.by_pk(user.id).one
|
87
|
-
expect(user.name).to eql('Jane')
|
88
|
-
end
|
89
|
-
|
90
|
-
it 'uses a mapper built from AST by default' do
|
91
|
-
repo = Class.new(ROM::Repository[:users]) do
|
92
|
-
commands :create
|
93
|
-
end.new(rom)
|
94
|
-
|
95
|
-
user = repo.create(name: 'Jane')
|
96
|
-
|
97
|
-
expect(user).to be_kind_of Dry::Struct
|
98
|
-
|
99
|
-
struct_definition = [:users, [:header, [
|
100
|
-
[:attribute, repo.users.schema[:id]],
|
101
|
-
[:attribute, repo.users.schema[:name]]]]]
|
102
|
-
|
103
|
-
expect(user).to be_an_instance_of ROM::Repository::StructBuilder.cache[struct_definition.hash]
|
104
|
-
end
|
105
|
-
|
106
|
-
describe 'using plugins' do
|
107
|
-
include_context 'plugins'
|
108
|
-
|
109
|
-
before do
|
110
|
-
conn.alter_table :users do
|
111
|
-
add_column :created_at, :timestamp, null: false
|
112
|
-
add_column :updated_at, :timestamp, null: false
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
it 'allows to use plugins in generated commands' do
|
117
|
-
repo = Class.new(ROM::Repository[:users]) do
|
118
|
-
commands :create, update: :by_pk, use: :timestamps
|
119
|
-
end.new(rom)
|
120
|
-
|
121
|
-
user = repo.create(name: 'Jane')
|
122
|
-
expect(user.created_at).to be_within(1).of Time.now
|
123
|
-
expect(user.created_at).to eql(user.updated_at)
|
124
|
-
|
125
|
-
repo.update(user.id, **user, name: 'Jane Doe')
|
126
|
-
updated_user = repo.users.by_pk(user.id).one
|
127
|
-
expect(updated_user.created_at).to eql(user.created_at)
|
128
|
-
expect(updated_user.updated_at).to be > updated_user.created_at
|
129
|
-
end
|
130
|
-
|
131
|
-
it 'allows to use several plugins' do
|
132
|
-
repo = Class.new(ROM::Repository[:users]) do
|
133
|
-
commands :create, use: %i(upcase_name timestamps)
|
134
|
-
end.new(rom)
|
135
|
-
|
136
|
-
user = repo.create(name: 'Jane')
|
137
|
-
expect(user.created_at).to be_within(1).of Time.now
|
138
|
-
expect(user.name).to eql('JANE')
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
describe 'using custom mappers' do
|
143
|
-
before do
|
144
|
-
configuration.mappers do
|
145
|
-
register :users,
|
146
|
-
name_list: -> users { users.map { |u| u[:name] } },
|
147
|
-
id_list: -> users { users.map { |u| u[:id] } }
|
148
|
-
end
|
149
|
-
end
|
150
|
-
|
151
|
-
it 'allows to use named mapper in commands' do
|
152
|
-
repo = Class.new(ROM::Repository[:users]).new(rom)
|
153
|
-
|
154
|
-
name = repo.command(create: :users, mapper: :name_list).call(name: 'Jane')
|
155
|
-
|
156
|
-
expect(name).to eql('Jane')
|
157
|
-
end
|
158
|
-
|
159
|
-
it 'caches command pipeline using mapper option' do
|
160
|
-
repo = Class.new(ROM::Repository[:users]).new(rom)
|
161
|
-
|
162
|
-
c1 = repo.command(create: :users, mapper: :name_list)
|
163
|
-
c2 = repo.command(create: :users, mapper: :name_list)
|
164
|
-
c3 = repo.command(create: :users, mapper: :id_list)
|
165
|
-
|
166
|
-
name = c1.call(name: 'Jane')
|
167
|
-
id = c3.call(name: 'John')
|
168
|
-
|
169
|
-
expect(c1).to be c2
|
170
|
-
expect(c3).not_to be c1
|
171
|
-
|
172
|
-
expect(name).to eql('Jane')
|
173
|
-
expect(id).to eql(2)
|
174
|
-
end
|
175
|
-
|
176
|
-
it 'allows to set a mapper with a class-level macro' do
|
177
|
-
repo = Class.new(ROM::Repository[:users]) do
|
178
|
-
commands :create, update: :by_pk, delete: :by_pk, mapper: :name_list
|
179
|
-
end.new(rom)
|
180
|
-
|
181
|
-
name = repo.create(name: 'Jane')
|
182
|
-
expect(name).to eql('Jane')
|
183
|
-
|
184
|
-
updated_name = repo.update(1, name: 'Jane Doe')
|
185
|
-
expect(updated_name).to eql('Jane Doe')
|
186
|
-
|
187
|
-
deleted_name = repo.delete(1)
|
188
|
-
expect(deleted_name).to eql('Jane Doe')
|
189
|
-
end
|
190
|
-
end
|
191
|
-
end
|
@@ -1,228 +0,0 @@
|
|
1
|
-
RSpec.describe ROM::Repository, '#command' do
|
2
|
-
include_context 'database'
|
3
|
-
include_context 'relations'
|
4
|
-
include_context 'repo'
|
5
|
-
|
6
|
-
context 'accessing custom command from the registry' do
|
7
|
-
before do
|
8
|
-
configuration.commands(:users) do
|
9
|
-
define(:upsert, type: ROM::SQL::Commands::Create)
|
10
|
-
define(:create)
|
11
|
-
end
|
12
|
-
|
13
|
-
configuration.commands(:tasks) do
|
14
|
-
define(:create)
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
it 'returns registered command' do
|
19
|
-
expect(repo.command(:users).upsert).to be(rom.command(:users).upsert)
|
20
|
-
expect(repo.command(:users)[:upsert]).to be(rom.command(:users).upsert)
|
21
|
-
end
|
22
|
-
|
23
|
-
it 'exposes command builder DSL' do
|
24
|
-
command = repo.command.create(user: :users) { |user| user.create(:tasks) }
|
25
|
-
|
26
|
-
expect(command).to be_instance_of(ROM::Command::Graph)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
context ':create' do
|
31
|
-
it 'builds Create command for a relation' do
|
32
|
-
create_user = repo.command(create: :users)
|
33
|
-
|
34
|
-
user = create_user.call(name: 'Jane Doe')
|
35
|
-
|
36
|
-
expect(user.id).to_not be(nil)
|
37
|
-
expect(user.name).to eql('Jane Doe')
|
38
|
-
end
|
39
|
-
|
40
|
-
it 'uses input_schema for command input' do
|
41
|
-
create_user = repo.command(create: :users)
|
42
|
-
expect(create_user.input).to eql(repo.users.input_schema)
|
43
|
-
end
|
44
|
-
|
45
|
-
it 'caches commands' do
|
46
|
-
create_user = -> { repo.command(create: :users) }
|
47
|
-
|
48
|
-
expect(create_user.()).to be(create_user.())
|
49
|
-
end
|
50
|
-
|
51
|
-
it 'builds Create command for a relation graph with one-to-one' do
|
52
|
-
create_user = repo.command(
|
53
|
-
:create,
|
54
|
-
repo.users.combine_children(one: repo.tasks)
|
55
|
-
)
|
56
|
-
|
57
|
-
user = create_user.call(name: 'Jane Doe', task: { title: 'Task one' })
|
58
|
-
|
59
|
-
expect(user.id).to_not be(nil)
|
60
|
-
expect(user.name).to eql('Jane Doe')
|
61
|
-
expect(user.task.title).to eql('Task one')
|
62
|
-
end
|
63
|
-
|
64
|
-
it 'builds Create command for a deeply nested relation graph' do
|
65
|
-
create_user = repo.command(
|
66
|
-
:create,
|
67
|
-
repo.users.combine_children(one: repo.tasks.combine_children(many: repo.tags))
|
68
|
-
)
|
69
|
-
|
70
|
-
user = create_user.call(
|
71
|
-
name: 'Jane Doe', task: { title: 'Task one', tags: [{ name: 'red' }] }
|
72
|
-
)
|
73
|
-
|
74
|
-
expect(user.id).to_not be(nil)
|
75
|
-
expect(user.name).to eql('Jane Doe')
|
76
|
-
expect(user.task.title).to eql('Task one')
|
77
|
-
expect(user.task.tags).to be_instance_of(Array)
|
78
|
-
expect(user.task.tags.first.name).to eql('red')
|
79
|
-
end
|
80
|
-
|
81
|
-
it 'builds Create command for a relation graph with one-to-many' do
|
82
|
-
create_user = repo.command(
|
83
|
-
:create,
|
84
|
-
repo.users.combine_children(many: repo.tasks)
|
85
|
-
)
|
86
|
-
|
87
|
-
user = create_user.call(name: 'Jane Doe', tasks: [{ title: 'Task one' }])
|
88
|
-
|
89
|
-
expect(user.id).to_not be(nil)
|
90
|
-
expect(user.name).to eql('Jane Doe')
|
91
|
-
expect(user.tasks).to be_instance_of(Array)
|
92
|
-
expect(user.tasks.first.title).to eql('Task one')
|
93
|
-
end
|
94
|
-
|
95
|
-
it 'builds Create command for a relation graph with one-to-many with aliased association' do
|
96
|
-
create_user = repo.command(:create, repo.users.combine(:aliased_posts))
|
97
|
-
|
98
|
-
user = create_user.call(name: 'Jane Doe', aliased_posts: [{ title: 'Post one' }, { title: 'Post two' }])
|
99
|
-
|
100
|
-
expect(user.id).to_not be(nil)
|
101
|
-
expect(user.name).to eql('Jane Doe')
|
102
|
-
expect(user.aliased_posts.size).to be(2)
|
103
|
-
end
|
104
|
-
|
105
|
-
it 'builds Create command for a deeply nested graph with one-to-many' do
|
106
|
-
create_user = repo.command(
|
107
|
-
:create,
|
108
|
-
repo.aggregate(many: repo.tasks.combine_children(many: repo.tags))
|
109
|
-
)
|
110
|
-
|
111
|
-
user = create_user.call(
|
112
|
-
name: 'Jane',
|
113
|
-
tasks: [{ title: 'Task', tags: [{ name: 'red' }]}]
|
114
|
-
)
|
115
|
-
|
116
|
-
expect(user.id).to_not be(nil)
|
117
|
-
expect(user.name).to eql('Jane')
|
118
|
-
expect(user.tasks).to be_instance_of(Array)
|
119
|
-
expect(user.tasks.first.title).to eql('Task')
|
120
|
-
expect(user.tasks.first.tags).to be_instance_of(Array)
|
121
|
-
expect(user.tasks.first.tags.first.name).to eql('red')
|
122
|
-
end
|
123
|
-
|
124
|
-
it 'builds Create command for a deeply nested graph with many-to-one & one-to-many' do
|
125
|
-
create_user = repo.command(
|
126
|
-
:create,
|
127
|
-
repo.aggregate(one: repo.tasks.combine_children(many: repo.tags))
|
128
|
-
)
|
129
|
-
|
130
|
-
user = create_user.call(
|
131
|
-
name: 'Jane', task: { title: 'Task', tags: [{ name: 'red' }, { name: 'blue' }] }
|
132
|
-
)
|
133
|
-
|
134
|
-
expect(user.id).to_not be(nil)
|
135
|
-
expect(user.name).to eql('Jane')
|
136
|
-
expect(user.task.title).to eql('Task')
|
137
|
-
expect(user.task.tags).to be_instance_of(Array)
|
138
|
-
expect(user.task.tags.size).to be(2)
|
139
|
-
expect(user.task.tags[0].name).to eql('red')
|
140
|
-
expect(user.task.tags[1].name).to eql('blue')
|
141
|
-
end
|
142
|
-
|
143
|
-
it 'builds Create command for a deeply nested graph with many-to-one' do
|
144
|
-
create_user = repo.command(
|
145
|
-
:create,
|
146
|
-
repo.aggregate(one: repo.tasks.combine_children(one: repo.tags))
|
147
|
-
)
|
148
|
-
|
149
|
-
user = create_user.call(
|
150
|
-
name: 'Jane', task: { title: 'Task', tag: { name: 'red' } }
|
151
|
-
)
|
152
|
-
|
153
|
-
expect(user.id).to_not be(nil)
|
154
|
-
expect(user.name).to eql('Jane')
|
155
|
-
expect(user.task.id).to_not be(nil)
|
156
|
-
expect(user.task.title).to eql('Task')
|
157
|
-
expect(user.task.tag.id).to_not be(nil)
|
158
|
-
expect(user.task.tag.name).to eql('red')
|
159
|
-
end
|
160
|
-
|
161
|
-
it 'builds Create command for a nested graph with many-to-many' do
|
162
|
-
user = repo.command(:create, repo.users).(name: 'Jane')
|
163
|
-
|
164
|
-
create_post = repo.command(
|
165
|
-
:create, repo.posts.combine_children(many: { labels: repo.labels })
|
166
|
-
)
|
167
|
-
|
168
|
-
post = create_post.call(
|
169
|
-
author_id: user.id, title: 'Jane post', labels: [{ name: 'red' }]
|
170
|
-
)
|
171
|
-
|
172
|
-
expect(post.labels.size).to be(1)
|
173
|
-
end
|
174
|
-
|
175
|
-
context 'relation with a custom dataset name' do
|
176
|
-
it 'allows configuring a create command' do
|
177
|
-
create_comment = comments_repo.command(create: :comments)
|
178
|
-
|
179
|
-
comment = create_comment.(author: 'gerybabooma', body: 'DIS GUY MUST BE A ALIEN OR SUTIN')
|
180
|
-
|
181
|
-
expect(comment.message_id).to eql(1)
|
182
|
-
expect(comment.author).to eql('gerybabooma')
|
183
|
-
expect(comment.body).to eql('DIS GUY MUST BE A ALIEN OR SUTIN')
|
184
|
-
end
|
185
|
-
|
186
|
-
it 'allows configuring a create command with aliased one-to-many' do
|
187
|
-
pending 'custom association names in the input are not yet support'
|
188
|
-
|
189
|
-
create_comment = comments_repo.command(:create, comments_repo.comments.combine(:emotions))
|
190
|
-
|
191
|
-
comment = create_comment.(author: 'Jane',
|
192
|
-
body: 'Hello Joe',
|
193
|
-
emotions: [{ author: 'Joe' }])
|
194
|
-
|
195
|
-
expect(comment.message_id).to eql(1)
|
196
|
-
expect(comment.author).to eql('Jane')
|
197
|
-
expect(comment.body).to eql('Hello Joe')
|
198
|
-
expect(comment.emotions.size).to eql(1)
|
199
|
-
expect(comment.emotions[0].author).to eql('Joe')
|
200
|
-
end
|
201
|
-
end
|
202
|
-
end
|
203
|
-
|
204
|
-
context ':update' do
|
205
|
-
it 'builds Update command for a relation' do
|
206
|
-
repo.users.insert(id: 3, name: 'Jane')
|
207
|
-
|
208
|
-
update_user = repo.command(:update, repo.users)
|
209
|
-
|
210
|
-
user = update_user.by_pk(3).call(name: 'Jane Doe')
|
211
|
-
|
212
|
-
expect(user.id).to be(3)
|
213
|
-
expect(user.name).to eql('Jane Doe')
|
214
|
-
end
|
215
|
-
end
|
216
|
-
|
217
|
-
context ':delete' do
|
218
|
-
it 'builds Delete command for a relation' do
|
219
|
-
repo.users.insert(id: 3, name: 'Jane')
|
220
|
-
|
221
|
-
delete_user = repo.command(:delete, repo.users)
|
222
|
-
|
223
|
-
delete_user.by_pk(3).call
|
224
|
-
|
225
|
-
expect(repo.users.by_pk(3).one).to be(nil)
|
226
|
-
end
|
227
|
-
end
|
228
|
-
end
|
@@ -1,73 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
RSpec.describe 'Repository with multi-adapters configuration' do
|
3
|
-
let(:configuration) {
|
4
|
-
ROM::Configuration.new(default: [:sql, DB_URI], memory: [:memory])
|
5
|
-
}
|
6
|
-
|
7
|
-
let(:sql_conn) { configuration.gateways[:default].connection }
|
8
|
-
|
9
|
-
let(:rom) { ROM.container(configuration) }
|
10
|
-
|
11
|
-
let(:users) { rom.relation(:sql_users) }
|
12
|
-
let(:tasks) { rom.relation(:memory_tasks) }
|
13
|
-
|
14
|
-
let(:repo) { Test::Repository.new(rom) }
|
15
|
-
|
16
|
-
before do
|
17
|
-
[:tags, :tasks, :posts, :books, :users, :posts_labels, :labels,
|
18
|
-
:reactions, :messages].each { |table| sql_conn.drop_table?(table) }
|
19
|
-
|
20
|
-
sql_conn.create_table :users do
|
21
|
-
primary_key :id
|
22
|
-
column :name, String
|
23
|
-
end
|
24
|
-
|
25
|
-
module Test
|
26
|
-
class Users < ROM::Relation[:sql]
|
27
|
-
schema(:users, as: :sql_users, infer: true)
|
28
|
-
end
|
29
|
-
|
30
|
-
class Tasks < ROM::Relation[:memory]
|
31
|
-
schema(:tasks, as: :memory_tasks) do
|
32
|
-
attribute :user_id, ROM::Types::Int
|
33
|
-
attribute :title, ROM::Types::String
|
34
|
-
end
|
35
|
-
|
36
|
-
gateway :memory
|
37
|
-
|
38
|
-
use :key_inference
|
39
|
-
|
40
|
-
view(:base, [:user_id, :title]) do
|
41
|
-
self
|
42
|
-
end
|
43
|
-
|
44
|
-
def for_users(users)
|
45
|
-
restrict(user_id: users.pluck(:id))
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
class Repository < ROM::Repository[:sql_users]
|
50
|
-
relations :memory_tasks
|
51
|
-
|
52
|
-
def users_with_tasks(id)
|
53
|
-
aggregate(many: { tasks: memory_tasks }).where(id: id)
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
configuration.register_relation(Test::Users)
|
59
|
-
configuration.register_relation(Test::Tasks)
|
60
|
-
|
61
|
-
user_id = configuration.gateways[:default].dataset(:users).insert(name: 'Jane')
|
62
|
-
configuration.gateways[:memory].dataset(:tasks).insert(user_id: user_id, title: 'Jane Task')
|
63
|
-
end
|
64
|
-
|
65
|
-
specify 'ᕕ⁞ ᵒ̌ 〜 ᵒ̌ ⁞ᕗ' do
|
66
|
-
user = repo.users_with_tasks(users.last[:id]).first
|
67
|
-
|
68
|
-
expect(user.name).to eql('Jane')
|
69
|
-
|
70
|
-
expect(user.tasks[0].user_id).to eql(user.id)
|
71
|
-
expect(user.tasks[0].title).to eql('Jane Task')
|
72
|
-
end
|
73
|
-
end
|