activerecord-transactionable 2.0.0 → 2.0.1
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 -1
- data/README.md +41 -7
- data/lib/activerecord/transactionable.rb +16 -13
- data/lib/activerecord/transactionable/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ebf67428aaf44c1ac7ffb5b7515c8e5d927f4966
|
4
|
+
data.tar.gz: fe553cbee8e6502b5b68ba04c0a3d296032f1cf4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 27f1f73531b9efc309d056c44603c882b4f08e731fb5ed65fd170432aa4a3e64dd4f12785171a36e0828e625b6093ea6edd63a4bea0b3287b67ac4fd9e29fe9b
|
7
|
+
data.tar.gz: 70451d8c0c5f4fe156a6153307aad8eca3ff61d063fa0d2b8c3d222897918c7d75cca8ee0f924e1a83c7bb8b4d6af7fc3bf50eb6d8327d3ea0b62e93d585ab49
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -65,7 +65,7 @@ Or install it yourself as:
|
|
65
65
|
|
66
66
|
## Usage
|
67
67
|
|
68
|
-
```
|
68
|
+
```ruby
|
69
69
|
class Car < ActiveRecord::Base
|
70
70
|
include Activerecord::Transactionable # Note lowercase "r" in Activerecord (different namespace than rails' module)
|
71
71
|
|
@@ -76,7 +76,8 @@ end
|
|
76
76
|
When creating, saving, deleting within the transaction make sure to use the bang methods (`!`) in order to ensure a rollback on failure.
|
77
77
|
|
78
78
|
When everything works:
|
79
|
-
|
79
|
+
|
80
|
+
```ruby
|
80
81
|
car = Car.new(name: "Fiesta")
|
81
82
|
car.transaction_wrapper do
|
82
83
|
car.save!
|
@@ -85,7 +86,8 @@ car.persisted? # => true
|
|
85
86
|
```
|
86
87
|
|
87
88
|
When something goes wrong:
|
88
|
-
|
89
|
+
|
90
|
+
```ruby
|
89
91
|
car = Car.new(name: nil)
|
90
92
|
car.transaction_wrapper do
|
91
93
|
car.save!
|
@@ -99,7 +101,8 @@ These examples are too simple to be useful with transactions, but if you are wor
|
|
99
101
|
Also see the specs.
|
100
102
|
|
101
103
|
If you need to lock the car as well as have a transaction (note: will reload the `car`):
|
102
|
-
|
104
|
+
|
105
|
+
```ruby
|
103
106
|
car = Car.new(name: nil)
|
104
107
|
car.transaction_wrapper(lock: true) do # uses ActiveRecord's with_lock
|
105
108
|
car.save!
|
@@ -109,7 +112,8 @@ car.errors.full_messages # => ["Name can't be blank"]
|
|
109
112
|
```
|
110
113
|
|
111
114
|
If you need to know if the transaction succeeded:
|
112
|
-
|
115
|
+
|
116
|
+
```ruby
|
113
117
|
car = Car.new(name: nil)
|
114
118
|
result = car.transaction_wrapper(lock: true) do # uses ActiveRecord's with_lock
|
115
119
|
car.save!
|
@@ -126,7 +130,7 @@ Meanings of `transaction_wrapper` return values:
|
|
126
130
|
|
127
131
|
## Update Example
|
128
132
|
|
129
|
-
```
|
133
|
+
```ruby
|
130
134
|
@client = Client.find(params[:id])
|
131
135
|
transaction_result = @client.transaction_wrapper(lock: true) do
|
132
136
|
@client.assign_attributes(client_params)
|
@@ -140,11 +144,41 @@ else
|
|
140
144
|
end
|
141
145
|
```
|
142
146
|
|
147
|
+
## Find or create
|
148
|
+
|
149
|
+
NOTE: The `is_retry` is passed to the block by the gem, and indicates whether the block is running for the first time or the second time.
|
150
|
+
The block will never be retried more than once.
|
151
|
+
|
152
|
+
```ruby
|
153
|
+
Car.transaction_wrapper(outside_retriable_errors: ActivRecord::RecordNotFound) do |is_retry|
|
154
|
+
if is_retry
|
155
|
+
Car.create!(vin: vin)
|
156
|
+
else
|
157
|
+
Car.find_by!(vin: vin)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
```
|
161
|
+
|
162
|
+
## Create or find
|
163
|
+
|
164
|
+
NOTE: The `is_retry` is passed to the block by the gem, and indicates whether the block is running for the first time or the second time.
|
165
|
+
The block will never be retried more than once.
|
166
|
+
|
167
|
+
```ruby
|
168
|
+
Car.transaction_wrapper(outside_retriable_errors: ActivRecord::RecordNotUnique) do |is_retry|
|
169
|
+
if is_retry
|
170
|
+
Car.find_by!(vin: vin)
|
171
|
+
else
|
172
|
+
Car.create!(vin: vin)
|
173
|
+
end
|
174
|
+
end
|
175
|
+
```
|
176
|
+
|
143
177
|
## Reporting to SAAS Error Tools (like Raygun, etc)
|
144
178
|
|
145
179
|
Hopefully there will be a better integration at some point, but for now, somewhere in your code do:
|
146
180
|
|
147
|
-
```
|
181
|
+
```ruby
|
148
182
|
module SendToRaygun
|
149
183
|
def transaction_error_logger(**args)
|
150
184
|
super
|
@@ -74,8 +74,8 @@ module Activerecord # Note lowercase "r" in Activerecord (different namespace th
|
|
74
74
|
end
|
75
75
|
end
|
76
76
|
error_handler_outside_transaction(object: object, transaction_open: transaction_open, **outside_args) do
|
77
|
-
run_inside_transaction_block(transaction_args: transaction_args, inside_args: inside_args, lock: lock, transaction_open: transaction_open, object: object) do
|
78
|
-
yield
|
77
|
+
run_inside_transaction_block(transaction_args: transaction_args, inside_args: inside_args, lock: lock, transaction_open: transaction_open, object: object) do |is_retry|
|
78
|
+
yield is_retry
|
79
79
|
end
|
80
80
|
end
|
81
81
|
end
|
@@ -88,22 +88,22 @@ module Activerecord # Note lowercase "r" in Activerecord (different namespace th
|
|
88
88
|
# Note: with_lock will reload object!
|
89
89
|
# Note: with_lock does not accept arguments like transaction does.
|
90
90
|
object.with_lock do
|
91
|
-
error_handler_inside_transaction(object: object, transaction_open: transaction_open, **inside_args) do
|
92
|
-
yield
|
91
|
+
error_handler_inside_transaction(object: object, transaction_open: transaction_open, **inside_args) do |is_retry|
|
92
|
+
yield is_retry
|
93
93
|
end
|
94
94
|
end
|
95
95
|
else
|
96
96
|
object.transaction(**transaction_args) do
|
97
|
-
error_handler_inside_transaction(object: object, transaction_open: transaction_open, **inside_args) do
|
98
|
-
yield
|
97
|
+
error_handler_inside_transaction(object: object, transaction_open: transaction_open, **inside_args) do |is_retry|
|
98
|
+
yield is_retry
|
99
99
|
end
|
100
100
|
end
|
101
101
|
end
|
102
102
|
else
|
103
103
|
raise ArgumentError, "No object to lock!" if lock
|
104
104
|
ActiveRecord::Base.transaction(**transaction_args) do
|
105
|
-
error_handler_inside_transaction(object: object, transaction_open: transaction_open, **inside_args) do
|
106
|
-
yield
|
105
|
+
error_handler_inside_transaction(object: object, transaction_open: transaction_open, **inside_args) do |is_retry|
|
106
|
+
yield is_retry
|
107
107
|
end
|
108
108
|
end
|
109
109
|
end
|
@@ -125,8 +125,8 @@ module Activerecord # Note lowercase "r" in Activerecord (different namespace th
|
|
125
125
|
prepared_errors.concat(DEFAULT_ERRORS_PREPARE_ON_SELF_INSIDE)
|
126
126
|
already_been_added_to_self, needing_added_to_self = rescued_errors.partition {|error_class| prepared_errors.include?(error_class)}
|
127
127
|
local_context = INSIDE_CONTEXT
|
128
|
-
run_block_with_retry(object, local_context, transaction_open, retriable_errors, reraisable_errors, already_been_added_to_self, needing_added_to_self) do
|
129
|
-
yield
|
128
|
+
run_block_with_retry(object, local_context, transaction_open, retriable_errors, reraisable_errors, already_been_added_to_self, needing_added_to_self) do |is_retry|
|
129
|
+
yield is_retry
|
130
130
|
end
|
131
131
|
end
|
132
132
|
|
@@ -139,8 +139,8 @@ module Activerecord # Note lowercase "r" in Activerecord (different namespace th
|
|
139
139
|
prepared_errors.concat(DEFAULT_ERRORS_PREPARE_ON_SELF_OUTSIDE)
|
140
140
|
already_been_added_to_self, needing_added_to_self = rescued_errors.partition {|error_class| prepared_errors.include?(error_class)}
|
141
141
|
local_context = OUTSIDE_CONTEXT
|
142
|
-
run_block_with_retry(object, local_context, transaction_open, retriable_errors, reraisable_errors, already_been_added_to_self, needing_added_to_self) do
|
143
|
-
yield
|
142
|
+
run_block_with_retry(object, local_context, transaction_open, retriable_errors, reraisable_errors, already_been_added_to_self, needing_added_to_self) do |is_retry|
|
143
|
+
yield is_retry
|
144
144
|
end
|
145
145
|
end
|
146
146
|
|
@@ -153,7 +153,10 @@ module Activerecord # Note lowercase "r" in Activerecord (different namespace th
|
|
153
153
|
# If the error is not rescued higher up the error will continue to bubble
|
154
154
|
# If we were already inside a transaction, such that this one is nested,
|
155
155
|
# then the result of the yield is what we want to return, to preserve the innermost result
|
156
|
-
|
156
|
+
# We pass the retry state along to yield so that the code implementing
|
157
|
+
# the transaction_wrapper can switch behavior on a retry
|
158
|
+
# (e.g. create => find)
|
159
|
+
result = yield re_try
|
157
160
|
# When in the outside context we need to preserve the inside result so it bubbles up unmolested with the "meaningful" result of the transaction.
|
158
161
|
if result.is_a?(Activerecord::Transactionable::Result)
|
159
162
|
result # <= preserve the meaningful return value
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activerecord-transactionable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Peter Boling
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-01-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activemodel
|