rom-repository 1.0.0.beta2 → 1.0.0.beta3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: cdb0dfc90b48097d286f0d5b79790560d79c8fdd
4
- data.tar.gz: ed15356517cc1dff17729d851e53b77f75727075
3
+ metadata.gz: 8deef9fc5ae64394c2845f34d1575ff4f55d503d
4
+ data.tar.gz: 746ac682b439a3ffd603cd79e64b2bf52ead6d8b
5
5
  SHA512:
6
- metadata.gz: cc5b70717bbfb200cad2dc539f89c438398ae3dd3c6fb3f10f8d1c58c48e2be2b5d7bc01a729f738400e9b5021dbb070aa14fbdaec98c5ec8f30b57511e6448c
7
- data.tar.gz: 88d6e30ab3107d583119ab1ed2a48bb83e138b2bc5026235acbb1a6932302a34037bb5315de976479d0c58895cb841026fe3239f8c3326e2093d882faf84942e
6
+ metadata.gz: c970db02832c84c5287a4c537bcc851abd07013947fdaeccccf6db117bf5b7817b4b10dbbfa0efc6683be30830e826eeaf5aba504b3e47663348a94291c05b06
7
+ data.tar.gz: 410546d65acdec9fedb221809ed1e2b098621da1b034eb8580b34c333931fdee16ba5ece929f9ccdfbc9be52150eb7fe89c5531ebea852c2cbd3c090f8a3bc44
data/.travis.yml CHANGED
@@ -21,6 +21,7 @@ env:
21
21
  matrix:
22
22
  allow_failures:
23
23
  - rvm: rbx-3
24
+ - rvm: jruby-9.1.6.0
24
25
  notifications:
25
26
  webhooks:
26
27
  urls:
data/.yardopts ADDED
@@ -0,0 +1,2 @@
1
+ --query '@api.text != "private"'
2
+ --embed-mixins
data/CHANGELOG.md CHANGED
@@ -2,15 +2,17 @@
2
2
 
3
3
  ### Added
4
4
 
5
- * New `Repository#session` API for building transactions using changesets (solnic)
6
- * Support for inferring typed structs based on relation schemas (solnic)
5
+ * New `Repository#transaction` API for executing operations inside a database transaction (flash-gordon+solnic)
7
6
  * `aggregate` and `combine` support nested association specs, ie `combine(users: [tasks: :tags])` (beauby)
8
7
  * Changesets support data as arrays too (solnic)
9
8
  * Changesets support custom command types via `Changeset#with(command_type: :my_command)` (solnic)
10
9
  * `Changeset::Delete` was added and is accessible via `repo.changeset(delete: some_relation.by_pk(1))` (solnic)
11
- * Ability to define custom changeset classes that can be instantiated via `repo.changeset(MyChangesetClass[:rel_name]).data(some_data)` where `MyChangesetClass` inherits from a core changeset class (solnic)
10
+ * Ability to define custom changeset classes that can be instantiated via `repo.changeset(MyChangesetClass[:rel_name]).data(some_data)` or `root_repo.changeset(MyChangesetClass)` where `MyChangesetClass` inherits from a core changeset class (solnic)
12
11
  * `Changeset.map` which accepts a block and exposes a DSL for data transformations (all [transproc hash methods](https://github.com/solnic/transproc)) are available (solnic)
12
+ * `Changeset.map` which accepts a custom block that can transform data (executed in the context of a changeset object) (solnic)
13
+ * Support for composing multiple mappings via `Changeset.map` (solnic)
13
14
  * `Changeset#associate` method that accepts another changeset or parent data and an association identifier, ie `post_changeset.associate(user, :author)` (solnic)
15
+ * Support for inferring typed structs based on relation schemas (solnic)
14
16
  * You can now use `wrap_parent` in combined relations too (which is gazillion times faster than `combine_parents`) (solnic)
15
17
 
16
18
  ### Changed
@@ -20,7 +22,7 @@
20
22
 
21
23
  ### Fixed
22
24
 
23
- * Auto-mapping to structs ignores FK attributes consistently (solnic)
25
+ * FKs are always included in auto-generated structs used in aggregates (solnic)
24
26
 
25
27
  [Compare v0.3.1...v1.0.0](https://github.com/rom-rb/rom-repository/compare/v0.3.1...v1.0.0)
26
28
 
@@ -27,6 +27,14 @@ module ROM
27
27
  self.class[name]
28
28
  end
29
29
 
30
+ def bind(context)
31
+ if processor.is_a?(Proc)
32
+ self.class.new(Pipe[-> *args { context.instance_exec(*args, &processor) }])
33
+ else
34
+ self
35
+ end
36
+ end
37
+
30
38
  def >>(other)
31
39
  if processor
32
40
  Pipe.new(processor >> other)
@@ -8,6 +8,19 @@ module ROM
8
8
  # @return [Symbol] The name of the relation's primary key attribute
9
9
  option :primary_key, reader: true
10
10
 
11
+ # Commit update changeset if there's a diff
12
+ #
13
+ # This returns original tuple if there's no diff
14
+ #
15
+ # @return [Hash]
16
+ #
17
+ # @see Changeset#commit
18
+ #
19
+ # @api public
20
+ def commit
21
+ diff? ? super : original
22
+ end
23
+
11
24
  # Return true
12
25
  #
13
26
  # @return [TrueClass]
@@ -23,7 +23,7 @@ module ROM
23
23
  # @!attribute [r] pipe
24
24
  # @return [Changeset::Pipe] data transformation pipe
25
25
  option :pipe, reader: true, accept: [Proc, Pipe], default: -> changeset {
26
- changeset.class.default_pipe
26
+ changeset.class.default_pipe(changeset)
27
27
  }
28
28
 
29
29
  # @!attribute [r] command_compiler
@@ -44,14 +44,50 @@ module ROM
44
44
  #
45
45
  # @api public
46
46
  def self.[](relation_name)
47
- fetch_or_store(relation_name) {
47
+ fetch_or_store([relation_name, self]) {
48
48
  Class.new(self) { relation(relation_name) }
49
49
  }
50
50
  end
51
51
 
52
+ # Define a changeset mapping
53
+ #
54
+ # Subsequent mapping definitions will be composed together
55
+ # and applied in the order they way defined
56
+ #
57
+ # @example Transformation DSL
58
+ # class NewUser < ROM::Changeset::Create
59
+ # map do
60
+ # unwrap :address, prefix: true
61
+ # end
62
+ # end
63
+ #
64
+ # @example Using custom block
65
+ # class NewUser < ROM::Changeset::Create
66
+ # map do |tuple|
67
+ # tuple.merge(created_at: Time.now)
68
+ # end
69
+ # end
70
+ #
71
+ # @example Multiple mappings (executed in the order of definition)
72
+ # class NewUser < ROM::Changeset::Create
73
+ # map do
74
+ # unwrap :address, prefix: true
75
+ # end
76
+ #
77
+ # map do |tuple|
78
+ # tuple.merge(created_at: Time.now)
79
+ # end
80
+ # end
81
+ #
82
+ # @return [Array<Pipe, Transproc::Function>]
83
+ #
52
84
  # @api public
53
85
  def self.map(&block)
54
- @pipe = Class.new(Pipe, &block).new
86
+ if block.arity.zero?
87
+ pipes << Class.new(Pipe, &block).new
88
+ else
89
+ pipes << Pipe.new(block)
90
+ end
55
91
  end
56
92
 
57
93
  # Build default pipe object
@@ -59,8 +95,20 @@ module ROM
59
95
  # This can be overridden in a custom changeset subclass
60
96
  #
61
97
  # @return [Pipe]
62
- def self.default_pipe
63
- @pipe || Pipe.new
98
+ def self.default_pipe(context)
99
+ pipes.size > 0 ? pipes.map { |p| p.bind(context) }.reduce(:>>) : Pipe.new
100
+ end
101
+
102
+ # @api private
103
+ def self.inherited(klass)
104
+ return if klass == ROM::Changeset
105
+ super
106
+ klass.instance_variable_set(:@__pipes__, pipes ? pipes.dup : [])
107
+ end
108
+
109
+ # @api private
110
+ def self.pipes
111
+ @__pipes__
64
112
  end
65
113
 
66
114
  # Pipe changeset's data using custom steps define on the pipe
@@ -124,6 +172,20 @@ module ROM
124
172
  with(__data__: data)
125
173
  end
126
174
 
175
+ # Persist changeset
176
+ #
177
+ # @example
178
+ # changeset = user_repo.changeset(name: 'Jane')
179
+ # changeset.commit
180
+ # # => { id: 1, name: 'Jane' }
181
+ #
182
+ # @return [Hash, Array]
183
+ #
184
+ # @api public
185
+ def commit
186
+ command.call
187
+ end
188
+
127
189
  # Return command result type
128
190
  #
129
191
  # @return [Symbol]
@@ -112,8 +112,12 @@ module ROM
112
112
 
113
113
  # @api private
114
114
  def define_command_method(type, **opts)
115
- define_method(type) do |*args|
116
- command(type => self.class.root, **opts).call(*args)
115
+ define_method(type) do |input|
116
+ if input.is_a?(Changeset)
117
+ map_tuple(input.relation, input.commit)
118
+ else
119
+ command(type => self.class.root, **opts).call(input)
120
+ end
117
121
  end
118
122
  end
119
123
 
@@ -127,8 +131,8 @@ module ROM
127
131
 
128
132
  changeset = input.first
129
133
 
130
- if changeset.is_a?(Changeset) && changeset.clean?
131
- map_tuple(changeset.relation, changeset.original)
134
+ if changeset.is_a?(Changeset)
135
+ map_tuple(changeset.relation, changeset.commit)
132
136
  else
133
137
  command(type => self.class.root, **opts)
134
138
  .public_send(view_name, *view_args)
@@ -61,9 +61,23 @@ module ROM
61
61
  #
62
62
  # @param *associations [Array<Symbol>] A list of association names
63
63
  #
64
+ # @overload aggregate(*associations, *assoc_opts)
65
+ # Composes an aggregate from configured associations and assoc opts
66
+ # on the root relation
67
+ #
68
+ # @example
69
+ # user_repo.aggregate(:tasks, posts: :tags)
70
+ #
71
+ # @param *associations [Array<Symbol>] A list of association names
72
+ # @param [Hash] Association options for nested aggregates
73
+ #
64
74
  # @overload aggregate(options)
65
75
  # Composes an aggregate by delegating to combine_children method.
66
76
  #
77
+ # @example
78
+ # user_repo.aggregate(tasks: :labels)
79
+ # user_repo.aggregate(posts: [:tags, :comments])
80
+ #
67
81
  # @param options [Hash] An option hash
68
82
  #
69
83
  # @see RelationProxy::Combine#combine_children
@@ -72,33 +86,60 @@ module ROM
72
86
  #
73
87
  # @api public
74
88
  def aggregate(*args)
75
- root.combine(*args)
89
+ if args.all? { |arg| arg.is_a?(Symbol) }
90
+ root.combine(*args)
91
+ else
92
+ args.reduce(root) { |a, e| a.combine(e) }
93
+ end
76
94
  end
77
95
 
78
96
  # @overload changeset(name, *args)
79
97
  # Delegate to Repository#changeset
98
+ #
80
99
  # @see Repository#changeset
81
100
  #
82
101
  # @overload changeset(data)
83
102
  # Builds a create changeset for the root relation
103
+ #
84
104
  # @example
85
105
  # user_repo.changeset(name: "Jane")
106
+ #
86
107
  # @param data [Hash] New data
108
+ #
87
109
  # @return [Changeset::Create]
88
110
  #
89
- # @overload changeset(restriction_arg, data)
111
+ # @overload changeset(primary_key, data)
90
112
  # Builds an update changeset for the root relation
113
+ #
91
114
  # @example
92
115
  # user_repo.changeset(1, name: "Jane Doe")
93
- # @param restriction_arg [Object] An argument for the restriction view
116
+ #
117
+ # @param primary_key [Object] Primary key for restricting relation
118
+ #
94
119
  # @return [Changeset::Update]
95
120
  #
121
+ # @overload changeset(changeset_class)
122
+ # Return a changeset prepared for repo's root relation
123
+ #
124
+ # @example
125
+ # changeset = user_repo.changeset(MyChangeset)
126
+ #
127
+ # changeset.relation == user_repo.root
128
+ # # true
129
+ #
130
+ # @param [Class] changeset_class Your custom changeset class
131
+ #
132
+ # @return [Changeset]
133
+ #
96
134
  # @override Repository#changeset
97
135
  #
98
136
  # @api public
99
137
  def changeset(*args)
100
138
  if args.first.is_a?(Symbol) && relations.key?(args.first)
101
139
  super
140
+ elsif args.first.is_a?(Class)
141
+ klass, *rest = args
142
+ super(klass[self.class.root], *rest)
102
143
  else
103
144
  super(root.name, *args)
104
145
  end
@@ -22,7 +22,7 @@ module ROM
22
22
  end
23
23
 
24
24
  def commit!
25
- queue.map(&:command).compact.each(&:call)
25
+ queue.each(&:commit)
26
26
 
27
27
  @status = :success
28
28
 
@@ -1,5 +1,5 @@
1
1
  module ROM
2
2
  class Repository
3
- VERSION = '1.0.0.beta2'.freeze
3
+ VERSION = '1.0.0.beta3'.freeze
4
4
  end
5
5
  end
@@ -139,7 +139,7 @@ module ROM
139
139
  end
140
140
 
141
141
  # @overload changeset(name, attributes)
142
- # Returns a create changeset for a given relation identifier
142
+ # Return a create changeset for a given relation identifier
143
143
  #
144
144
  # @example
145
145
  # repo.changeset(:users, name: "Jane")
@@ -149,8 +149,8 @@ module ROM
149
149
  #
150
150
  # @return [Changeset::Create]
151
151
  #
152
- # @overload changeset(name, restriction_arg, attributes)
153
- # Returns an update changeset for a given relation identifier
152
+ # @overload changeset(name, primary_key, attributes)
153
+ # Return an update changeset for a given relation identifier
154
154
  #
155
155
  # @example
156
156
  # repo.changeset(:users, 1, name: "Jane Doe")
@@ -160,6 +160,16 @@ module ROM
160
160
  #
161
161
  # @return [Changeset::Update]
162
162
  #
163
+ # @overload changeset(changeset_class)
164
+ # Return a changeset object using provided class
165
+ #
166
+ # @example
167
+ # repo.changeset(NewUserChangeset).data(attributes)
168
+ #
169
+ # @param [Class] changeset_class Custom changeset class
170
+ #
171
+ # @return [Changeset]
172
+ #
163
173
  # @api public
164
174
  def changeset(*args)
165
175
  opts = { command_compiler: command_compiler }
@@ -84,6 +84,46 @@ RSpec.describe 'ROM repository' do
84
84
  expect(jane.posts.first.title).to eql('Hello From Jane')
85
85
  end
86
86
 
87
+ it 'loads an aggregate via assoc options' do
88
+ jane = repo.aggregate(posts: :labels).where(name: 'Jane').one
89
+
90
+ expect(jane.name).to eql('Jane')
91
+ expect(jane.posts.size).to be(1)
92
+ expect(jane.posts.first.title).to eql('Hello From Jane')
93
+ expect(jane.posts[0].labels.size).to be(2)
94
+ expect(jane.posts[0].labels[0].name).to eql('red')
95
+ expect(jane.posts[0].labels[1].name).to eql('blue')
96
+ end
97
+
98
+ it 'loads an aggregate with multiple assoc options' do
99
+ jane = repo.aggregate(:labels, posts: :labels).where(name: 'Jane').one
100
+
101
+ expect(jane.name).to eql('Jane')
102
+
103
+ expect(jane.labels.size).to be(2)
104
+ expect(jane.labels[0].name).to eql('red')
105
+ expect(jane.labels[1].name).to eql('blue')
106
+
107
+ expect(jane.posts.size).to be(1)
108
+ expect(jane.posts[0].title).to eql('Hello From Jane')
109
+
110
+ expect(jane.posts[0].labels.size).to be(2)
111
+ expect(jane.posts[0].labels[0].name).to eql('red')
112
+ expect(jane.posts[0].labels[1].name).to eql('blue')
113
+ end
114
+
115
+ it 'loads an aggregate with deeply nested assoc options' do
116
+ jane = repo.aggregate(posts: [{ author: :labels }]).where(name: 'Jane').one
117
+
118
+ expect(jane.posts.size).to be(1)
119
+ expect(jane.posts[0].title).to eql('Hello From Jane')
120
+
121
+ expect(jane.posts[0].author.id).to eql(jane.id)
122
+ expect(jane.posts[0].author.labels.size).to be(2)
123
+ expect(jane.posts[0].author.labels[0].name).to eql('red')
124
+ expect(jane.posts[0].author.labels[1].name).to eql('blue')
125
+ end
126
+
87
127
  it 'loads an aggregate with multiple associations' do
88
128
  jane = repo.aggregate(:posts, :labels).where(name: 'Jane').one
89
129
 
@@ -45,6 +45,17 @@ RSpec.describe ROM::Repository::Root do
45
45
  end
46
46
  end
47
47
 
48
+ describe '#changeset' do
49
+ it 'returns a changeset automatically set for root relation' do
50
+ klass = Class.new(ROM::Changeset::Create)
51
+
52
+ changeset = repo.changeset(klass)
53
+
54
+ expect(changeset.relation).to be(repo.users)
55
+ expect(changeset).to be_kind_of(klass)
56
+ end
57
+ end
58
+
48
59
  describe '#aggregate' do
49
60
  include_context 'seeds'
50
61
 
@@ -1,42 +1,84 @@
1
1
  RSpec.describe ROM::Changeset, '.map' do
2
- subject(:changeset) do
3
- Class.new(ROM::Changeset) do
4
- map do
5
- unwrap :address
6
- rename_keys street: :address_street, city: :address_city, country: :address_country
2
+ context 'single mapping with transaction DSL' do
3
+ subject(:changeset) do
4
+ Class.new(ROM::Changeset::Create[:users]) do
5
+ map do
6
+ unwrap :address
7
+ rename_keys street: :address_street, city: :address_city, country: :address_country
8
+ end
9
+
10
+ def default_command_type
11
+ :test
12
+ end
13
+ end.new(relation, __data__: user_data)
14
+ end
15
+
16
+ let(:relation) { double(:relation) }
17
+
18
+ context 'with a hash' do
19
+ let(:user_data) do
20
+ { name: 'Jane', address: { street: 'Street 1', city: 'NYC', country: 'US' } }
7
21
  end
8
22
 
9
- def default_command_type
10
- :test
23
+ it 'sets up custom data pipe' do
24
+ expect(changeset.to_h)
25
+ .to eql(name: 'Jane', address_street: 'Street 1', address_city: 'NYC', address_country: 'US' )
11
26
  end
12
- end.new(relation, __data__: user_data)
13
- end
27
+ end
14
28
 
15
- let(:relation) { double(:relation) }
29
+ context 'with an array' do
30
+ let(:user_data) do
31
+ [{ name: 'Jane', address: { street: 'Street 1', city: 'NYC', country: 'US' } },
32
+ { name: 'Joe', address: { street: 'Street 2', city: 'KRK', country: 'PL' } }]
33
+ end
16
34
 
17
- context 'with a hash' do
18
- let(:user_data) do
19
- { name: 'Jane', address: { street: 'Street 1', city: 'NYC', country: 'US' } }
35
+ it 'sets up custom data pipe' do
36
+ expect(changeset.to_a)
37
+ .to eql([
38
+ { name: 'Jane', address_street: 'Street 1', address_city: 'NYC', address_country: 'US' },
39
+ { name: 'Joe', address_street: 'Street 2', address_city: 'KRK', address_country: 'PL' }
40
+ ])
41
+ end
20
42
  end
43
+ end
44
+
45
+ context 'multi mapping with custom blocks' do
46
+ subject(:changeset) do
47
+ Class.new(ROM::Changeset::Create[:users]) do
48
+ map do |tuple|
49
+ tuple.merge(one: next_value)
50
+ end
51
+
52
+ map do |tuple|
53
+ tuple.merge(two: next_value)
54
+ end
55
+
56
+ def initialize(*args)
57
+ super
58
+ @counter = 0
59
+ end
21
60
 
22
- it 'sets up custom data pipe' do
23
- expect(changeset.to_h)
24
- .to eql(name: 'Jane', address_street: 'Street 1', address_city: 'NYC', address_country: 'US' )
61
+ def default_command_type
62
+ :test
63
+ end
64
+
65
+ def next_value
66
+ @counter += 1
67
+ end
68
+ end.new(relation).data(user_data)
25
69
  end
26
- end
27
70
 
28
- context 'with an array' do
29
- let(:user_data) do
30
- [{ name: 'Jane', address: { street: 'Street 1', city: 'NYC', country: 'US' } },
31
- { name: 'Joe', address: { street: 'Street 2', city: 'KRK', country: 'PL' } }]
71
+ let(:relation) { double(:relation) }
72
+ let(:user_data) { { name: 'Jane' } }
73
+
74
+ it 'applies mappings in order of definition' do
75
+ expect(changeset.to_h).to eql(name: 'Jane', one: 1, two: 2)
32
76
  end
33
77
 
34
- it 'sets up custom data pipe' do
35
- expect(changeset.to_a)
36
- .to eql([
37
- { name: 'Jane', address_street: 'Street 1', address_city: 'NYC', address_country: 'US' },
38
- { name: 'Joe', address_street: 'Street 2', address_city: 'KRK', address_country: 'PL' }
39
- ])
78
+ it 'inherits pipes' do
79
+ klass = Class.new(changeset.class)
80
+
81
+ expect(klass.pipes).to eql(changeset.class.pipes)
40
82
  end
41
83
  end
42
84
  end
@@ -2,6 +2,26 @@ RSpec.describe ROM::Changeset do
2
2
  let(:jane) { { id: 2, name: "Jane" } }
3
3
  let(:relation) { double(ROM::Relation, primary_key: :id) }
4
4
 
5
+ describe '.[]' do
6
+ it 'returns a changeset preconfigured for a specific relation' do
7
+ klass = ROM::Changeset::Create[:users]
8
+
9
+ expect(klass.relation).to be(:users)
10
+ expect(klass < ROM::Changeset::Create).to be(true)
11
+ end
12
+
13
+ it 'caches results' do
14
+ create = ROM::Changeset::Create[:users]
15
+ update = ROM::Changeset::Update[:users]
16
+
17
+ expect(create).to be(ROM::Changeset::Create[:users])
18
+ expect(create < ROM::Changeset::Create).to be(true)
19
+
20
+ expect(update).to be(ROM::Changeset::Update[:users])
21
+ expect(update < ROM::Changeset::Update).to be(true)
22
+ end
23
+ end
24
+
5
25
  describe '#diff' do
6
26
  it 'returns a hash with changes' do
7
27
  expect(relation).to receive(:fetch).with(2).and_return(jane)
@@ -0,0 +1,28 @@
1
+ RSpec.describe ROM::Repository, '#transaction' do
2
+ let(:user_repo) do
3
+ Class.new(ROM::Repository[:users]) { commands :create }.new(rom)
4
+ end
5
+
6
+ let(:task_repo) do
7
+ Class.new(ROM::Repository[:tasks]) { commands :create }.new(rom)
8
+ end
9
+
10
+ include_context 'database'
11
+ include_context 'relations'
12
+
13
+ it 'creating user with tasks' do
14
+ user, task = user_repo.transaction do
15
+ user_changeset = user_repo.changeset(name: 'Jane')
16
+ task_changeset = task_repo.changeset(title: 'Task One')
17
+
18
+ user = user_repo.create(user_changeset)
19
+ task = task_repo.create(task_changeset.associate(user, :user))
20
+
21
+ [user, task]
22
+ end
23
+
24
+ expect(user.name).to eql('Jane')
25
+ expect(task.user_id).to be(user.id)
26
+ expect(task.title).to eql('Task One')
27
+ end
28
+ end
@@ -7,8 +7,6 @@ RSpec.describe ROM::Session do
7
7
  let(:create_changeset) { instance_double(ROM::Changeset::Create, relation: relation) }
8
8
  let(:delete_changeset) { instance_double(ROM::Changeset::Delete, relation: relation) }
9
9
  let(:relation) { double.as_null_object }
10
- let(:create_command) { spy(:create_command) }
11
- let(:delete_command) { spy(:delete_command) }
12
10
 
13
11
  describe '#pending?' do
14
12
  it 'returns true before commit' do
@@ -22,21 +20,17 @@ RSpec.describe ROM::Session do
22
20
 
23
21
  describe '#commit!' do
24
22
  it 'executes ops and restores pristine state' do
25
- expect(create_changeset).to receive(:command).and_return(create_command)
23
+ expect(create_changeset).to receive(:commit).and_return(true)
26
24
 
27
25
  session.add(create_changeset).commit!
28
26
  session.commit!
29
27
 
30
28
  expect(session).to be_success
31
-
32
- expect(create_command).to have_received(:call)
33
29
  end
34
30
 
35
31
  it 'executes ops and restores pristine state when exception was raised' do
36
- expect(create_changeset).to receive(:command).and_return(create_command)
37
- expect(delete_changeset).to receive(:command).and_return(delete_command)
38
-
39
- expect(delete_command).to receive(:call).and_raise(StandardError, 'oops')
32
+ expect(create_changeset).to_not receive(:commit)
33
+ expect(delete_changeset).to receive(:commit).and_raise(StandardError, 'oops')
40
34
 
41
35
  expect {
42
36
  session.add(delete_changeset)
@@ -47,8 +41,6 @@ RSpec.describe ROM::Session do
47
41
  expect(session).to be_failure
48
42
 
49
43
  session.commit!
50
-
51
- expect(create_command).not_to have_received(:call)
52
44
  end
53
45
  end
54
46
  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.beta2
4
+ version: 1.0.0.beta3
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-19 00:00:00.000000000 Z
11
+ date: 2017-01-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rom
@@ -110,6 +110,7 @@ files:
110
110
  - ".gitignore"
111
111
  - ".rspec"
112
112
  - ".travis.yml"
113
+ - ".yardopts"
113
114
  - CHANGELOG.md
114
115
  - Gemfile
115
116
  - LICENSE.txt
@@ -161,6 +162,7 @@ files:
161
162
  - spec/unit/repository/changeset_spec.rb
162
163
  - spec/unit/repository/inspect_spec.rb
163
164
  - spec/unit/repository/session_spec.rb
165
+ - spec/unit/repository/transaction_spec.rb
164
166
  - spec/unit/session_spec.rb
165
167
  - spec/unit/struct_builder_spec.rb
166
168
  homepage: http://rom-rb.org