rom-repository 1.0.0.beta3 → 1.0.0.rc1
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/.gitignore +1 -0
- data/.travis.yml +3 -7
- data/CHANGELOG.md +1 -0
- data/README.md +1 -1
- data/lib/rom/repository/changeset/associated.rb +76 -0
- data/lib/rom/repository/changeset/create.rb +2 -52
- data/lib/rom/repository/changeset/delete.rb +7 -9
- data/lib/rom/repository/changeset/pipe.rb +3 -0
- data/lib/rom/repository/changeset/stateful.rb +240 -0
- data/lib/rom/repository/changeset/update.rb +11 -34
- data/lib/rom/repository/changeset.rb +64 -144
- data/lib/rom/repository/class_interface.rb +4 -4
- data/lib/rom/repository/command_compiler.rb +17 -15
- data/lib/rom/repository/command_proxy.rb +2 -0
- data/lib/rom/repository/relation_proxy/combine.rb +3 -4
- data/lib/rom/repository/relation_proxy.rb +24 -7
- data/lib/rom/repository/root.rb +14 -1
- data/lib/rom/repository/session.rb +3 -0
- data/lib/rom/repository/struct_builder.rb +1 -1
- data/lib/rom/repository/version.rb +1 -1
- data/lib/rom/repository.rb +92 -32
- data/lib/rom/struct.rb +40 -2
- data/rom-repository.gemspec +2 -2
- data/spec/integration/changeset_spec.rb +27 -0
- data/spec/unit/changeset_spec.rb +45 -7
- data/spec/unit/repository/changeset_spec.rb +59 -22
- data/spec/unit/repository/transaction_spec.rb +15 -1
- metadata +8 -6
data/lib/rom/repository.rb
CHANGED
@@ -12,23 +12,15 @@ require 'rom/repository/session'
|
|
12
12
|
module ROM
|
13
13
|
# Abstract repository class to inherit from
|
14
14
|
#
|
15
|
-
# A repository provides access to composable relations and
|
16
|
-
# to provide application-specific data that is already materialized, so that
|
15
|
+
# A repository provides access to composable relations, commands and changesets.
|
16
|
+
# Its job is to provide application-specific data that is already materialized, so that
|
17
17
|
# relations don't leak into your application layer.
|
18
18
|
#
|
19
|
-
# Typically, you're going to work with Repository::Root that
|
20
|
-
# use a single relation as its root, and compose aggregates and use commands
|
19
|
+
# Typically, you're going to work with Repository::Root that is configured to
|
20
|
+
# use a single relation as its root, and compose aggregates and use changesets and commands
|
21
21
|
# against the root relation.
|
22
22
|
#
|
23
23
|
# @example
|
24
|
-
# class MyRepo < ROM::Repository[:users]
|
25
|
-
# relations :users, :tasks
|
26
|
-
#
|
27
|
-
# def users_with_tasks
|
28
|
-
# users.combine_children(tasks: tasks).to_a
|
29
|
-
# end
|
30
|
-
# end
|
31
|
-
#
|
32
24
|
# rom = ROM.container(:sql, 'sqlite::memory') do |conf|
|
33
25
|
# conf.default.create_table(:users) do
|
34
26
|
# primary_key :id
|
@@ -40,15 +32,36 @@ module ROM
|
|
40
32
|
# column :user_id, Integer
|
41
33
|
# column :title, String
|
42
34
|
# end
|
35
|
+
#
|
36
|
+
# conf.relation(:users) do
|
37
|
+
# associations do
|
38
|
+
# has_many :tasks
|
39
|
+
# end
|
40
|
+
# end
|
41
|
+
# end
|
42
|
+
#
|
43
|
+
# class UserRepo < ROM::Repository[:users]
|
44
|
+
# relations :tasks
|
45
|
+
#
|
46
|
+
# def users_with_tasks
|
47
|
+
# aggregate(:tasks).to_a
|
48
|
+
# end
|
43
49
|
# end
|
44
50
|
#
|
45
|
-
#
|
46
|
-
#
|
51
|
+
# user_repo = UserRepo.new(rom)
|
52
|
+
# user_repo.users_with_tasks
|
47
53
|
#
|
48
54
|
# @see Repository::Root
|
49
55
|
#
|
50
56
|
# @api public
|
51
57
|
class Repository
|
58
|
+
# Mapping for supported changeset classes used in #changeset(type => relation) method
|
59
|
+
CHANGESET_TYPES = {
|
60
|
+
create: Changeset::Create,
|
61
|
+
update: Changeset::Update,
|
62
|
+
delete: Changeset::Delete
|
63
|
+
}.freeze
|
64
|
+
|
52
65
|
extend ClassInterface
|
53
66
|
|
54
67
|
# @!attribute [r] container
|
@@ -63,7 +76,8 @@ module ROM
|
|
63
76
|
# @return [MapperBuilder] The auto-generated mappers for repo relations
|
64
77
|
attr_reader :mappers
|
65
78
|
|
66
|
-
#
|
79
|
+
# @!attribute [r] commmand_compiler
|
80
|
+
# @return [Method] Function for compiling commands bound to a repo instance
|
67
81
|
attr_reader :command_compiler
|
68
82
|
|
69
83
|
# Initializes a new repo by establishing configured relation proxies from
|
@@ -91,6 +105,8 @@ module ROM
|
|
91
105
|
@command_compiler = method(:command)
|
92
106
|
end
|
93
107
|
|
108
|
+
# Return a command for a relation
|
109
|
+
#
|
94
110
|
# @overload command(type, relation)
|
95
111
|
# Returns a command for a relation
|
96
112
|
#
|
@@ -138,6 +154,8 @@ module ROM
|
|
138
154
|
end
|
139
155
|
end
|
140
156
|
|
157
|
+
# Return a changeset for a relation
|
158
|
+
#
|
141
159
|
# @overload changeset(name, attributes)
|
142
160
|
# Return a create changeset for a given relation identifier
|
143
161
|
#
|
@@ -170,6 +188,16 @@ module ROM
|
|
170
188
|
#
|
171
189
|
# @return [Changeset]
|
172
190
|
#
|
191
|
+
# @overload changeset(opts)
|
192
|
+
# Return a changeset object using provided changeset type and relation
|
193
|
+
#
|
194
|
+
# @example
|
195
|
+
# repo.changeset(delete: repo.users.where { id > 10 })
|
196
|
+
#
|
197
|
+
# @param [Hash<Symbol=>Relation] opts Command type => Relation config
|
198
|
+
#
|
199
|
+
# @return [Changeset]
|
200
|
+
#
|
173
201
|
# @api public
|
174
202
|
def changeset(*args)
|
175
203
|
opts = { command_compiler: command_compiler }
|
@@ -179,10 +207,14 @@ module ROM
|
|
179
207
|
elsif args.size == 3
|
180
208
|
name, pk, data = args
|
181
209
|
elsif args.size == 1
|
182
|
-
|
210
|
+
if args[0].is_a?(Class)
|
211
|
+
klass = args[0]
|
183
212
|
|
184
|
-
|
185
|
-
|
213
|
+
if klass < Changeset
|
214
|
+
return klass.new(relations[klass.relation], opts)
|
215
|
+
else
|
216
|
+
raise ArgumentError, "+#{klass.name}+ is not a Changeset subclass"
|
217
|
+
end
|
186
218
|
else
|
187
219
|
type, relation = args[0].to_a[0]
|
188
220
|
end
|
@@ -191,41 +223,69 @@ module ROM
|
|
191
223
|
end
|
192
224
|
|
193
225
|
if type
|
194
|
-
|
195
|
-
|
196
|
-
|
226
|
+
klass = CHANGESET_TYPES.fetch(type) {
|
227
|
+
raise ArgumentError, "+#{type.inspect}+ is not a valid changeset type. Must be one of: #{CHANGESET_TYPES.keys.inspect}"
|
228
|
+
}
|
229
|
+
|
230
|
+
klass.new(relation, opts)
|
197
231
|
else
|
198
232
|
relation = relations[name]
|
199
233
|
|
200
234
|
if pk
|
201
|
-
Changeset::Update.new(relation, opts.
|
235
|
+
Changeset::Update.new(relation.by_pk(pk), opts.update(__data__: data))
|
202
236
|
else
|
203
|
-
Changeset::Create.new(relation, opts.
|
237
|
+
Changeset::Create.new(relation, opts.update(__data__: data))
|
204
238
|
end
|
205
239
|
end
|
206
240
|
end
|
207
241
|
|
208
|
-
#
|
242
|
+
# Open a database transaction
|
209
243
|
#
|
210
|
-
# @
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
#
|
244
|
+
# @example commited transaction
|
245
|
+
# user = transaction do |t|
|
246
|
+
# create(changeset(name: 'Jane'))
|
247
|
+
# end
|
248
|
+
#
|
249
|
+
# user
|
250
|
+
# # => #<ROM::Struct[User] id=1 name="Jane">
|
251
|
+
#
|
252
|
+
# @example with a rollback
|
253
|
+
# user = transaction do |t|
|
254
|
+
# changeset(name: 'Jane').commit
|
255
|
+
# t.rollback!
|
256
|
+
# end
|
257
|
+
#
|
258
|
+
# user
|
259
|
+
# # nil
|
218
260
|
#
|
219
261
|
# @api public
|
220
262
|
def transaction(&block)
|
221
263
|
container.gateways[:default].transaction(&block)
|
222
264
|
end
|
223
265
|
|
266
|
+
# Return a string representation of a repository object
|
267
|
+
#
|
268
|
+
# @return [String]
|
269
|
+
#
|
224
270
|
# @api public
|
225
271
|
def inspect
|
226
272
|
%(#<#{self.class} relations=[#{self.class.relations.map(&:inspect).join(' ')}]>)
|
227
273
|
end
|
228
274
|
|
275
|
+
# Start a session for multiple changesets
|
276
|
+
#
|
277
|
+
# TODO: this is partly done, needs tweaks in changesets so that we can gather
|
278
|
+
# command results and return them in a nice way
|
279
|
+
#
|
280
|
+
# @!visibility private
|
281
|
+
#
|
282
|
+
# @api public
|
283
|
+
def session(&block)
|
284
|
+
session = Session.new(self)
|
285
|
+
yield(session)
|
286
|
+
transaction { session.commit! }
|
287
|
+
end
|
288
|
+
|
229
289
|
private
|
230
290
|
|
231
291
|
# Local command cache
|
data/lib/rom/struct.rb
CHANGED
@@ -1,9 +1,47 @@
|
|
1
1
|
require 'dry/struct'
|
2
2
|
|
3
3
|
module ROM
|
4
|
-
# Simple data-struct
|
4
|
+
# Simple data-struct class
|
5
5
|
#
|
6
|
-
#
|
6
|
+
# ROM structs are plain data structures loaded by repositories.
|
7
|
+
# They implement Hash protocol which means that they can be used
|
8
|
+
# in places where Hash-like objects are supported.
|
9
|
+
#
|
10
|
+
# Repositories define subclasses of ROM::Struct automatically, they are not
|
11
|
+
# defined as constants in any module, instead, generated mappers are configured
|
12
|
+
# to use anonymous struct classes as models.
|
13
|
+
#
|
14
|
+
# Structs are based on dry-struct gem, they include `schema` with detailed information
|
15
|
+
# about attribute types returned from relations, thus can be introspected to build
|
16
|
+
# additional functionality when desired.
|
17
|
+
#
|
18
|
+
# @example accessing relation struct model
|
19
|
+
# rom = ROM.container(:sql, 'sqlite::memory') do |conf|
|
20
|
+
# conf.default.create_table(:users) do
|
21
|
+
# primary_key :id
|
22
|
+
# column :name, String
|
23
|
+
# end
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
# class UserRepo < ROM::Repository[:users]
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
# user_repo = UserRepo.new(rom)
|
30
|
+
#
|
31
|
+
# # get auto-generated User struct
|
32
|
+
# model = user_repo.users.mapper.model
|
33
|
+
# # => ROM::Struct[User]
|
34
|
+
#
|
35
|
+
# # see struct's schema attributes
|
36
|
+
#
|
37
|
+
# # model.schema[:id]
|
38
|
+
# # => #<Dry::Types::Constrained type=#<Dry::Types::Definition primitive=Integer options={}> options={:rule=>#<Dry::Logic::Rule::Predicate predicate=#<Method: Module(Dry::Logic::Predicates::Methods)#gt?> options={:args=>[0]}>, :meta=>{:primary_key=>true, :name=>:id, :source=>ROM::Relation::Name(users)}} rule=#<Dry::Logic::Rule::Predicate predicate=#<Method: Module(Dry::Logic::Predicates::Methods)#gt?> options={:args=>[0]}>>
|
39
|
+
#
|
40
|
+
# model.schema[:name]
|
41
|
+
# # => #<Dry::Types::Sum left=#<Dry::Types::Constrained type=#<Dry::Types::Definition primitive=NilClass options={}> options={:rule=>#<Dry::Logic::Rule::Predicate predicate=#<Method: Module(Dry::Logic::Predicates::Methods)#type?> options={:args=>[NilClass]}>} rule=#<Dry::Logic::Rule::Predicate predicate=#<Method: Module(Dry::Logic::Predicates::Methods)#type?> options={:args=>[NilClass]}>> right=#<Dry::Types::Definition primitive=String options={}> options={:meta=>{:name=>:name, :source=>ROM::Relation::Name(users)}}>
|
42
|
+
#
|
43
|
+
# @see http://dry-rb.org/gems/dry-struct dry-struct
|
44
|
+
# @see http://dry-rb.org/gems/dry-types dry-types
|
7
45
|
#
|
8
46
|
# @api public
|
9
47
|
class Struct < Dry::Struct
|
data/rom-repository.gemspec
CHANGED
@@ -15,8 +15,8 @@ Gem::Specification.new do |gem|
|
|
15
15
|
gem.test_files = `git ls-files -- {spec}/*`.split("\n")
|
16
16
|
gem.license = 'MIT'
|
17
17
|
|
18
|
-
gem.add_runtime_dependency 'rom', '~> 3.0.0.
|
19
|
-
gem.add_runtime_dependency 'rom-mapper', '~> 0.5.0.
|
18
|
+
gem.add_runtime_dependency 'rom', '~> 3.0.0.rc'
|
19
|
+
gem.add_runtime_dependency 'rom-mapper', '~> 0.5.0.rc'
|
20
20
|
gem.add_runtime_dependency 'dry-core', '~> 0.2', '>= 0.2.1'
|
21
21
|
gem.add_runtime_dependency 'dry-struct', '~> 0.1'
|
22
22
|
|
@@ -43,6 +43,33 @@ RSpec.describe 'Using changesets' do
|
|
43
43
|
expect(result.created_at).to be_instance_of(Time)
|
44
44
|
expect(result.updated_at).to be_instance_of(Time)
|
45
45
|
end
|
46
|
+
|
47
|
+
it 'preprocesses data using custom block' do
|
48
|
+
changeset = repo.
|
49
|
+
changeset(:books, title: "rom-rb is awesome").
|
50
|
+
map { |tuple| tuple.merge(created_at: Time.now) }
|
51
|
+
|
52
|
+
command = repo.command(:create, repo.books)
|
53
|
+
result = command.(changeset)
|
54
|
+
|
55
|
+
expect(result.id).to_not be(nil)
|
56
|
+
expect(result.title).to eql("rom-rb is awesome")
|
57
|
+
expect(result.created_at).to be_instance_of(Time)
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'preprocesses data using built-in steps and custom block' do
|
61
|
+
changeset = repo.
|
62
|
+
changeset(:books, title: "rom-rb is awesome").
|
63
|
+
map(:touch) { |tuple| tuple.merge(created_at: Time.now) }
|
64
|
+
|
65
|
+
command = repo.command(:create, repo.books)
|
66
|
+
result = command.(changeset)
|
67
|
+
|
68
|
+
expect(result.id).to_not be(nil)
|
69
|
+
expect(result.title).to eql("rom-rb is awesome")
|
70
|
+
expect(result.created_at).to be_instance_of(Time)
|
71
|
+
expect(result.updated_at).to be_instance_of(Time)
|
72
|
+
end
|
46
73
|
end
|
47
74
|
|
48
75
|
describe 'Update' do
|
data/spec/unit/changeset_spec.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
RSpec.describe ROM::Changeset do
|
2
2
|
let(:jane) { { id: 2, name: "Jane" } }
|
3
|
-
let(:relation) { double(ROM::Relation,
|
3
|
+
let(:relation) { double(ROM::Relation, name: :users) }
|
4
4
|
|
5
5
|
describe '.[]' do
|
6
6
|
it 'returns a changeset preconfigured for a specific relation' do
|
@@ -24,9 +24,9 @@ RSpec.describe ROM::Changeset do
|
|
24
24
|
|
25
25
|
describe '#diff' do
|
26
26
|
it 'returns a hash with changes' do
|
27
|
-
expect(relation).to receive(:
|
27
|
+
expect(relation).to receive(:one).and_return(jane)
|
28
28
|
|
29
|
-
changeset = ROM::Changeset::Update.new(relation, __data__: { name: "Jane Doe" }
|
29
|
+
changeset = ROM::Changeset::Update.new(relation, __data__: { name: "Jane Doe" })
|
30
30
|
|
31
31
|
expect(changeset.diff).to eql(name: "Jane Doe")
|
32
32
|
end
|
@@ -34,22 +34,40 @@ RSpec.describe ROM::Changeset do
|
|
34
34
|
|
35
35
|
describe '#diff?' do
|
36
36
|
it 'returns true when data differs from the original tuple' do
|
37
|
-
expect(relation).to receive(:
|
37
|
+
expect(relation).to receive(:one).and_return(jane)
|
38
38
|
|
39
|
-
changeset = ROM::Changeset::Update.new(relation, __data__: { name: "Jane Doe" }
|
39
|
+
changeset = ROM::Changeset::Update.new(relation, __data__: { name: "Jane Doe" })
|
40
40
|
|
41
41
|
expect(changeset).to be_diff
|
42
42
|
end
|
43
43
|
|
44
44
|
it 'returns false when data are equal to the original tuple' do
|
45
|
-
expect(relation).to receive(:
|
45
|
+
expect(relation).to receive(:one).and_return(jane)
|
46
46
|
|
47
|
-
changeset = ROM::Changeset::Update.new(relation, __data__: { name: "Jane" }
|
47
|
+
changeset = ROM::Changeset::Update.new(relation, __data__: { name: "Jane" })
|
48
48
|
|
49
49
|
expect(changeset).to_not be_diff
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
53
|
+
describe '#clean?' do
|
54
|
+
it 'returns true when data are equal to the original tuple' do
|
55
|
+
expect(relation).to receive(:one).and_return(jane)
|
56
|
+
|
57
|
+
changeset = ROM::Changeset::Update.new(relation, __data__: { name: "Jane" })
|
58
|
+
|
59
|
+
expect(changeset).to be_clean
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'returns false when data differs from the original tuple' do
|
63
|
+
expect(relation).to receive(:one).and_return(jane)
|
64
|
+
|
65
|
+
changeset = ROM::Changeset::Update.new(relation, __data__: { name: "Jane Doe" })
|
66
|
+
|
67
|
+
expect(changeset).to_not be_clean
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
53
71
|
describe 'quacks like a hash' do
|
54
72
|
subject(:changeset) { ROM::Changeset::Create.new(relation, __data__: data) }
|
55
73
|
|
@@ -101,4 +119,24 @@ RSpec.describe ROM::Changeset do
|
|
101
119
|
expect { changeset.not_here }.to raise_error(NoMethodError, /not_here/)
|
102
120
|
end
|
103
121
|
end
|
122
|
+
|
123
|
+
describe '#inspect' do
|
124
|
+
context 'with a stateful changeset' do
|
125
|
+
subject(:changeset) { ROM::Changeset::Create.new(relation).data(name: 'Jane') }
|
126
|
+
|
127
|
+
specify do
|
128
|
+
expect(changeset.inspect).
|
129
|
+
to eql('#<ROM::Changeset::Create relation=:users data={:name=>"Jane"}>')
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
context 'with a data-less changeset' do
|
134
|
+
subject(:changeset) { ROM::Changeset::Delete.new(relation) }
|
135
|
+
|
136
|
+
specify do
|
137
|
+
expect(changeset.inspect).
|
138
|
+
to eql('#<ROM::Changeset::Delete relation=:users>')
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
104
142
|
end
|
@@ -20,8 +20,8 @@ RSpec.describe ROM::Repository, '#changeset' do
|
|
20
20
|
expect(changeset.relation).to be(repo.users)
|
21
21
|
end
|
22
22
|
|
23
|
-
it 'can
|
24
|
-
expect(changeset.
|
23
|
+
it 'can be commited' do
|
24
|
+
expect(changeset.commit).to eql(id: 1, name: 'Jane')
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
@@ -42,35 +42,53 @@ RSpec.describe ROM::Repository, '#changeset' do
|
|
42
42
|
expect(changeset.relation).to be(repo.users)
|
43
43
|
end
|
44
44
|
|
45
|
-
it 'can
|
46
|
-
expect(changeset.
|
45
|
+
it 'can be commited' do
|
46
|
+
expect(changeset.commit).to eql([{ id: 1, name: 'Jane' }, { id: 2, name: 'Joe' }])
|
47
47
|
end
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
51
51
|
describe ROM::Changeset::Update do
|
52
|
-
let(:
|
53
|
-
|
52
|
+
let(:data) do
|
53
|
+
{ name: 'Jane Doe' }
|
54
54
|
end
|
55
55
|
|
56
|
-
|
57
|
-
|
58
|
-
|
56
|
+
shared_context 'a valid update changeset' do
|
57
|
+
let(:user) do
|
58
|
+
repo.command(:create, repo.users).call(name: 'Jane')
|
59
|
+
end
|
59
60
|
|
60
|
-
|
61
|
-
|
62
|
-
|
61
|
+
it 'has data' do
|
62
|
+
expect(changeset.to_h).to eql(name: 'Jane Doe')
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'has diff' do
|
66
|
+
expect(changeset.diff).to eql(name: 'Jane Doe')
|
67
|
+
end
|
63
68
|
|
64
|
-
|
65
|
-
|
69
|
+
it 'has relation' do
|
70
|
+
expect(changeset.relation.one).to eql(repo.users.by_pk(user[:id]).one)
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'can return be commited' do
|
74
|
+
expect(changeset.commit).to eql(id: 1, name: 'Jane Doe')
|
75
|
+
end
|
66
76
|
end
|
67
77
|
|
68
|
-
|
69
|
-
|
78
|
+
context 'using PK to restrict a relation' do
|
79
|
+
let(:changeset) do
|
80
|
+
repo.changeset(:users, user[:id], data)
|
81
|
+
end
|
82
|
+
|
83
|
+
include_context 'a valid update changeset'
|
70
84
|
end
|
71
85
|
|
72
|
-
|
73
|
-
|
86
|
+
context 'using custom relation' do
|
87
|
+
let(:changeset) do
|
88
|
+
repo.changeset(update: repo.users.by_pk(user[:id])).data(data)
|
89
|
+
end
|
90
|
+
|
91
|
+
include_context 'a valid update changeset'
|
74
92
|
end
|
75
93
|
end
|
76
94
|
|
@@ -91,8 +109,8 @@ RSpec.describe ROM::Repository, '#changeset' do
|
|
91
109
|
expect(changeset.relation).to eql(relation)
|
92
110
|
end
|
93
111
|
|
94
|
-
it 'can
|
95
|
-
expect(changeset.
|
112
|
+
it 'can be commited' do
|
113
|
+
expect(changeset.commit.to_h).to eql(id: 1, name: 'Jane')
|
96
114
|
expect(relation.one).to be(nil)
|
97
115
|
end
|
98
116
|
end
|
@@ -118,8 +136,27 @@ RSpec.describe ROM::Repository, '#changeset' do
|
|
118
136
|
expect(changeset.relation).to be(repo.users)
|
119
137
|
end
|
120
138
|
|
121
|
-
it 'can
|
122
|
-
expect(changeset.
|
139
|
+
it 'can be commited' do
|
140
|
+
expect(changeset.commit).to eql(id: 1, name: 'Jane')
|
123
141
|
end
|
124
142
|
end
|
143
|
+
|
144
|
+
it 'raises ArgumentError when unknown type was used' do
|
145
|
+
expect { repo.changeset(not_here: repo.users) }.
|
146
|
+
to raise_error(
|
147
|
+
ArgumentError,
|
148
|
+
'+:not_here+ is not a valid changeset type. Must be one of: [:create, :update, :delete]'
|
149
|
+
)
|
150
|
+
end
|
151
|
+
|
152
|
+
it 'raises ArgumentError when unknown class was used' do
|
153
|
+
klass = Class.new {
|
154
|
+
def self.name
|
155
|
+
'SomeClass'
|
156
|
+
end
|
157
|
+
}
|
158
|
+
|
159
|
+
expect { repo.changeset(klass) }.
|
160
|
+
to raise_error(ArgumentError, /SomeClass/)
|
161
|
+
end
|
125
162
|
end
|
@@ -4,7 +4,7 @@ RSpec.describe ROM::Repository, '#transaction' do
|
|
4
4
|
end
|
5
5
|
|
6
6
|
let(:task_repo) do
|
7
|
-
Class.new(ROM::Repository[:tasks]) { commands :create }.new(rom)
|
7
|
+
Class.new(ROM::Repository[:tasks]) { commands :create, :update }.new(rom)
|
8
8
|
end
|
9
9
|
|
10
10
|
include_context 'database'
|
@@ -25,4 +25,18 @@ RSpec.describe ROM::Repository, '#transaction' do
|
|
25
25
|
expect(task.user_id).to be(user.id)
|
26
26
|
expect(task.title).to eql('Task One')
|
27
27
|
end
|
28
|
+
|
29
|
+
it 'updating tasks user' do
|
30
|
+
jane = user_repo.create(name: 'Jane')
|
31
|
+
john = user_repo.create(name: 'John')
|
32
|
+
task = task_repo.create(title: 'Jane Task', user_id: jane.id)
|
33
|
+
|
34
|
+
task = task_repo.transaction do
|
35
|
+
task_changeset = task_repo.changeset(task.id, title: 'John Task').associate(john, :user).commit
|
36
|
+
task_repo.update(task_changeset)
|
37
|
+
end
|
38
|
+
|
39
|
+
expect(task.user_id).to be(john.id)
|
40
|
+
expect(task.title).to eql('John Task')
|
41
|
+
end
|
28
42
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rom-repository
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.0.
|
4
|
+
version: 1.0.0.rc1
|
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-01-
|
11
|
+
date: 2017-01-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rom
|
@@ -16,28 +16,28 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 3.0.0.
|
19
|
+
version: 3.0.0.rc
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 3.0.0.
|
26
|
+
version: 3.0.0.rc
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rom-mapper
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 0.5.0.
|
33
|
+
version: 0.5.0.rc
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: 0.5.0.
|
40
|
+
version: 0.5.0.rc
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: dry-core
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -119,9 +119,11 @@ files:
|
|
119
119
|
- lib/rom-repository.rb
|
120
120
|
- lib/rom/repository.rb
|
121
121
|
- lib/rom/repository/changeset.rb
|
122
|
+
- lib/rom/repository/changeset/associated.rb
|
122
123
|
- lib/rom/repository/changeset/create.rb
|
123
124
|
- lib/rom/repository/changeset/delete.rb
|
124
125
|
- lib/rom/repository/changeset/pipe.rb
|
126
|
+
- lib/rom/repository/changeset/stateful.rb
|
125
127
|
- lib/rom/repository/changeset/update.rb
|
126
128
|
- lib/rom/repository/class_interface.rb
|
127
129
|
- lib/rom/repository/command_compiler.rb
|