rom-repository 1.0.0.beta2 → 1.0.0.beta3

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 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