├── .github
└── workflows
│ └── actions.yml
├── .gitignore
├── Gemfile
├── Gemfile.lock
├── Rakefile
├── Readme.md
├── ar_after_transaction.gemspec
├── gemfiles
├── rails6.1.gemfile
├── rails6.1.gemfile.lock
├── rails7.0.gemfile
├── rails7.0.gemfile.lock
├── rails7.1.gemfile
├── rails7.1.gemfile.lock
├── rails7.2.gemfile
├── rails7.2.gemfile.lock
├── rails8.0.gemfile
└── rails8.0.gemfile.lock
├── lib
├── ar_after_transaction.rb
└── ar_after_transaction
│ └── version.rb
└── spec
├── after_initialize_spec.rb
├── ar_after_transaction_spec.rb
├── setup_database.rb
└── spec_helper.rb
/.github/workflows/actions.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 | on:
3 | push:
4 | branches: [master]
5 | pull_request:
6 | branches: [master]
7 | jobs:
8 | build:
9 | name: ruby${{ matrix.ruby }} rails${{ matrix.rails }} rake
10 | runs-on: ubuntu-latest
11 | strategy:
12 | matrix:
13 | ruby: ['3.1', '3.2', '3.3']
14 | rails: ['6.1', '7.0', '7.1', '7.2', '8.0']
15 | exclude:
16 | - ruby: '3.1'
17 | rails: '8.0'
18 | env:
19 | BUNDLE_GEMFILE: gemfiles/rails${{ matrix.rails }}.gemfile
20 | steps:
21 | - uses: actions/checkout@v2
22 | - uses: ruby/setup-ruby@v1
23 | with:
24 | ruby-version: ${{ matrix.ruby }}
25 | bundler-cache: true # runs 'bundle install' and caches installed gems automatically
26 | - run: bundle exec rake
27 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .bundle
2 | .ruby-version
3 | /gemfiles/.bundle
4 | /log
5 | /vendor/bundle
6 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | source 'https://rubygems.org'
4 |
5 | gemspec
6 |
--------------------------------------------------------------------------------
/Gemfile.lock:
--------------------------------------------------------------------------------
1 | PATH
2 | remote: .
3 | specs:
4 | ar_after_transaction (0.13.0)
5 | activerecord (>= 6.1.0, < 8.1)
6 |
7 | GEM
8 | remote: https://rubygems.org/
9 | specs:
10 | actioncable (7.2.0)
11 | actionpack (= 7.2.0)
12 | activesupport (= 7.2.0)
13 | nio4r (~> 2.0)
14 | websocket-driver (>= 0.6.1)
15 | zeitwerk (~> 2.6)
16 | actionmailbox (7.2.0)
17 | actionpack (= 7.2.0)
18 | activejob (= 7.2.0)
19 | activerecord (= 7.2.0)
20 | activestorage (= 7.2.0)
21 | activesupport (= 7.2.0)
22 | mail (>= 2.8.0)
23 | actionmailer (7.2.0)
24 | actionpack (= 7.2.0)
25 | actionview (= 7.2.0)
26 | activejob (= 7.2.0)
27 | activesupport (= 7.2.0)
28 | mail (>= 2.8.0)
29 | rails-dom-testing (~> 2.2)
30 | actionpack (7.2.0)
31 | actionview (= 7.2.0)
32 | activesupport (= 7.2.0)
33 | nokogiri (>= 1.8.5)
34 | racc
35 | rack (>= 2.2.4, < 3.2)
36 | rack-session (>= 1.0.1)
37 | rack-test (>= 0.6.3)
38 | rails-dom-testing (~> 2.2)
39 | rails-html-sanitizer (~> 1.6)
40 | useragent (~> 0.16)
41 | actiontext (7.2.0)
42 | actionpack (= 7.2.0)
43 | activerecord (= 7.2.0)
44 | activestorage (= 7.2.0)
45 | activesupport (= 7.2.0)
46 | globalid (>= 0.6.0)
47 | nokogiri (>= 1.8.5)
48 | actionview (7.2.0)
49 | activesupport (= 7.2.0)
50 | builder (~> 3.1)
51 | erubi (~> 1.11)
52 | rails-dom-testing (~> 2.2)
53 | rails-html-sanitizer (~> 1.6)
54 | activejob (7.2.0)
55 | activesupport (= 7.2.0)
56 | globalid (>= 0.3.6)
57 | activemodel (7.2.0)
58 | activesupport (= 7.2.0)
59 | activerecord (7.2.0)
60 | activemodel (= 7.2.0)
61 | activesupport (= 7.2.0)
62 | timeout (>= 0.4.0)
63 | activestorage (7.2.0)
64 | actionpack (= 7.2.0)
65 | activejob (= 7.2.0)
66 | activerecord (= 7.2.0)
67 | activesupport (= 7.2.0)
68 | marcel (~> 1.0)
69 | activesupport (7.2.0)
70 | base64
71 | bigdecimal
72 | concurrent-ruby (~> 1.0, >= 1.3.1)
73 | connection_pool (>= 2.2.5)
74 | drb
75 | i18n (>= 1.6, < 2)
76 | logger (>= 1.4.2)
77 | minitest (>= 5.1)
78 | securerandom (>= 0.3)
79 | tzinfo (~> 2.0, >= 2.0.5)
80 | base64 (0.2.0)
81 | bigdecimal (3.1.8)
82 | builder (3.3.0)
83 | bump (0.10.0)
84 | concurrent-ruby (1.3.4)
85 | connection_pool (2.4.1)
86 | crass (1.0.6)
87 | date (3.3.4)
88 | diff-lcs (1.5.1)
89 | drb (2.2.1)
90 | erubi (1.13.0)
91 | globalid (1.2.1)
92 | activesupport (>= 6.1)
93 | i18n (1.14.5)
94 | concurrent-ruby (~> 1.0)
95 | io-console (0.7.2)
96 | irb (1.14.0)
97 | rdoc (>= 4.0.0)
98 | reline (>= 0.4.2)
99 | logger (1.6.0)
100 | loofah (2.22.0)
101 | crass (~> 1.0.2)
102 | nokogiri (>= 1.12.0)
103 | mail (2.8.1)
104 | mini_mime (>= 0.1.1)
105 | net-imap
106 | net-pop
107 | net-smtp
108 | marcel (1.0.4)
109 | mini_mime (1.1.5)
110 | minitest (5.25.1)
111 | net-imap (0.4.14)
112 | date
113 | net-protocol
114 | net-pop (0.1.2)
115 | net-protocol
116 | net-protocol (0.2.2)
117 | timeout
118 | net-smtp (0.5.0)
119 | net-protocol
120 | nio4r (2.7.3)
121 | nokogiri (1.16.7-aarch64-linux)
122 | racc (~> 1.4)
123 | nokogiri (1.16.7-arm-linux)
124 | racc (~> 1.4)
125 | nokogiri (1.16.7-arm64-darwin)
126 | racc (~> 1.4)
127 | nokogiri (1.16.7-x86-linux)
128 | racc (~> 1.4)
129 | nokogiri (1.16.7-x86_64-darwin)
130 | racc (~> 1.4)
131 | nokogiri (1.16.7-x86_64-linux)
132 | racc (~> 1.4)
133 | psych (5.1.2)
134 | stringio
135 | racc (1.8.1)
136 | rack (3.1.7)
137 | rack-session (2.0.0)
138 | rack (>= 3.0.0)
139 | rack-test (2.1.0)
140 | rack (>= 1.3)
141 | rackup (2.1.0)
142 | rack (>= 3)
143 | webrick (~> 1.8)
144 | rails (7.2.0)
145 | actioncable (= 7.2.0)
146 | actionmailbox (= 7.2.0)
147 | actionmailer (= 7.2.0)
148 | actionpack (= 7.2.0)
149 | actiontext (= 7.2.0)
150 | actionview (= 7.2.0)
151 | activejob (= 7.2.0)
152 | activemodel (= 7.2.0)
153 | activerecord (= 7.2.0)
154 | activestorage (= 7.2.0)
155 | activesupport (= 7.2.0)
156 | bundler (>= 1.15.0)
157 | railties (= 7.2.0)
158 | rails-dom-testing (2.2.0)
159 | activesupport (>= 5.0.0)
160 | minitest
161 | nokogiri (>= 1.6)
162 | rails-html-sanitizer (1.6.0)
163 | loofah (~> 2.21)
164 | nokogiri (~> 1.14)
165 | railties (7.2.0)
166 | actionpack (= 7.2.0)
167 | activesupport (= 7.2.0)
168 | irb (~> 1.13)
169 | rackup (>= 1.0.0)
170 | rake (>= 12.2)
171 | thor (~> 1.0, >= 1.2.2)
172 | zeitwerk (~> 2.6)
173 | rake (13.2.1)
174 | rdoc (6.7.0)
175 | psych (>= 4.0.0)
176 | reline (0.5.9)
177 | io-console (~> 0.5)
178 | rspec (3.13.0)
179 | rspec-core (~> 3.13.0)
180 | rspec-expectations (~> 3.13.0)
181 | rspec-mocks (~> 3.13.0)
182 | rspec-core (3.13.0)
183 | rspec-support (~> 3.13.0)
184 | rspec-expectations (3.13.1)
185 | diff-lcs (>= 1.2.0, < 2.0)
186 | rspec-support (~> 3.13.0)
187 | rspec-mocks (3.13.1)
188 | diff-lcs (>= 1.2.0, < 2.0)
189 | rspec-support (~> 3.13.0)
190 | rspec-support (3.13.1)
191 | securerandom (0.3.1)
192 | sqlite3 (1.7.3-aarch64-linux)
193 | sqlite3 (1.7.3-arm-linux)
194 | sqlite3 (1.7.3-arm64-darwin)
195 | sqlite3 (1.7.3-x86-linux)
196 | sqlite3 (1.7.3-x86_64-darwin)
197 | sqlite3 (1.7.3-x86_64-linux)
198 | stringio (3.1.1)
199 | thor (1.3.1)
200 | timeout (0.4.1)
201 | tzinfo (2.0.6)
202 | concurrent-ruby (~> 1.0)
203 | useragent (0.16.10)
204 | webrick (1.8.1)
205 | websocket-driver (0.7.6)
206 | websocket-extensions (>= 0.1.0)
207 | websocket-extensions (0.1.5)
208 | wwtd (1.4.1)
209 | zeitwerk (2.6.17)
210 |
211 | PLATFORMS
212 | aarch64-linux
213 | arm-linux
214 | arm64-darwin
215 | x86-linux
216 | x86_64-darwin
217 | x86_64-linux
218 |
219 | DEPENDENCIES
220 | ar_after_transaction!
221 | bump
222 | rails
223 | rake
224 | rspec (~> 3)
225 | sqlite3 (~> 1.0)
226 | wwtd
227 |
228 | BUNDLED WITH
229 | 2.5.14
230 |
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'bundler/setup'
4 | require 'bundler/gem_tasks'
5 | require 'bump/tasks'
6 | Bump.replace_in_default = Dir["gemfiles/*.lock"]
7 |
8 | task default: :spec
9 | task :spec do
10 | sh 'rspec spec'
11 | end
12 |
13 | desc 'Bundle all gemfiles CMD=install'
14 | task :bundle_all do
15 | Bundler.with_original_env do
16 | Dir['gemfiles/*.gemfile'].each do |gemfile|
17 | sh "BUNDLE_GEMFILE=#{gemfile} bundle #{ENV["CMD"]}"
18 | end
19 | end
20 | end
21 |
--------------------------------------------------------------------------------
/Readme.md:
--------------------------------------------------------------------------------
1 | [](http://badge.fury.io/rb/ar_after_transaction)
2 | 
3 |
4 | Do something only after the currently open transactions have finished.
5 |
6 | Normally everything gets rolled back when a transaction fails, but you cannot roll back sending an email or adding a job to Resque.
7 |
8 | Install
9 | =======
10 |
11 | ```bash
12 | gem install ar_after_transaction
13 | ```
14 |
15 |
16 | Usage
17 | =====
18 |
19 | ### just-in-time callbacks
20 |
21 | ```ruby
22 | class User
23 | after_create :do_stuff, :oops
24 |
25 | def do_stuff
26 | after_transaction do
27 | send_an_email # cannot be rolled back
28 | end
29 | comments.create(...) # will be rolled back
30 | end
31 |
32 | def oops
33 | raise "do the rolback!"
34 | end
35 | end
36 | ```
37 |
38 | ### General 'this should be rolled back when in a transaction' code like jobs
39 |
40 | ```ruby
41 | class Resque
42 | def revertable_enqueue(*args)
43 | ActiveRecord::Base.after_transaction do
44 | enqueue(*args)
45 | end
46 | end
47 | end
48 | ```
49 |
50 | ### When not in a transaction
51 | after_transaction will perform the given block immediately
52 |
53 | ### Transactional fixtures <-> normally_open_transactions
54 | after_transaction assumes zero open transactions.
55 | If you use transactional fixtures you should change it in test mode.
56 |
57 | `Rspec:`
58 | ```ruby
59 | # spec/rails_helper.rb
60 | config.before(:suite) do
61 | ActiveRecord::Base.normally_open_transactions = 1
62 | end
63 | ```
64 |
65 | ### Adding new rails versions
66 |
67 | - bump in `ar_after_transaction.gemspec`
68 | - create a new gemfiles/.gemfile
69 | - `BUNDLE_GEMFILE=gemfiles/.gemfile bundle`
70 | - `BUNDLE_GEMFILE=gemfiles/.gemfile bundle exec rake`
71 | - update `.github/workflows/actions.yml`
72 | - make a PR
73 |
74 | Alternative
75 | ===========
76 |
77 | Rails 3+
78 | - basic support is built in, use it if you can!
79 | - `after_commit :foo`
80 | - `after_commit :bar, on: :create / :update`
81 | - [after_commit everywhere](https://dev.to/evilmartians/rails-aftercommit-everywhere--4j9g)
82 |
83 |
84 | [after_commit](https://github.com/pat/after_commit)
85 | - pro: threadsafe
86 | - pro: more fine-grained callbacks (before_commit, `after_commit`, before_rollback, after_rollback)
87 | - con: doesn't let you define `after_transaction` callbacks *anywhere* like `ar_after_transaction` does (*outside* of the `after_commit`, etc. callbacks which only happen at certain points in the model's life cycle)
88 | - con: more complex
89 |
90 | Authors
91 | =======
92 | [Original idea and code](https://rails.lighthouseapp.com/projects/8994/tickets/2991-after-transaction-patch) from [Jamis Buck](http://weblog.jamisbuck.org/) (post by Jeremy Kemper)
93 |
94 | ### [Contributors](http://github.com/grosser/ar_after_transaction/contributors)
95 | - [Bogdan Gusiev](http://gusiev.com)
96 | - [Benedikt Deicke](http://blog.synatic.net)
97 | - [Tyler Rick](https://github.com/TylerRick)
98 | - [Michael Wu](https://github.com/michaelmwu)
99 | - [C.W.](https://github.com/compwron)
100 | - [Ben Weintraub](https://github.com/benweint)
101 | - [Vladimir Temnikov](https://github.com/vladimirtemnikov)
102 | - [Mark Gangl](https://github.com/attack)
103 | - [Alex Vondrak](https://github.com/ajvondrak)
104 |
105 | [Michael Grosser](http://grosser.it)
106 | michael@grosser.it
107 | License: MIT
108 |
--------------------------------------------------------------------------------
/ar_after_transaction.gemspec:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require './lib/ar_after_transaction/version'
4 |
5 | Gem::Specification.new 'ar_after_transaction', ARAfterTransaction::VERSION do |s|
6 | s.summary = 'Execute irreversible actions only when transactions are not rolled back'
7 | s.authors = ['Michael Grosser']
8 | s.email = 'michael@grosser.it'
9 | s.homepage = 'http://github.com/grosser/ar_after_transaction'
10 | s.files = `git ls-files lib Readme.md`.split("\n")
11 | s.required_ruby_version = '>= 3.1.0'
12 | s.add_runtime_dependency 'activerecord', '>= 6.1.0', '< 8.1'
13 | s.add_development_dependency 'bump'
14 | s.add_development_dependency 'rails'
15 | s.add_development_dependency 'rake'
16 | s.add_development_dependency 'rspec', '~> 3'
17 | s.add_development_dependency 'sqlite3', '~> 1.0' # avoid 2.0 for now
18 | s.add_development_dependency 'wwtd'
19 | s.license = 'MIT'
20 | end
21 |
--------------------------------------------------------------------------------
/gemfiles/rails6.1.gemfile:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | source 'https://rubygems.org'
4 |
5 | gem 'activerecord', '~>6.1.0'
6 |
7 | gemspec path: '../'
8 |
--------------------------------------------------------------------------------
/gemfiles/rails6.1.gemfile.lock:
--------------------------------------------------------------------------------
1 | PATH
2 | remote: ..
3 | specs:
4 | ar_after_transaction (0.13.0)
5 | activerecord (>= 6.1.0, < 8.1)
6 |
7 | GEM
8 | remote: https://rubygems.org/
9 | specs:
10 | actioncable (6.1.4.4)
11 | actionpack (= 6.1.4.4)
12 | activesupport (= 6.1.4.4)
13 | nio4r (~> 2.0)
14 | websocket-driver (>= 0.6.1)
15 | actionmailbox (6.1.4.4)
16 | actionpack (= 6.1.4.4)
17 | activejob (= 6.1.4.4)
18 | activerecord (= 6.1.4.4)
19 | activestorage (= 6.1.4.4)
20 | activesupport (= 6.1.4.4)
21 | mail (>= 2.7.1)
22 | actionmailer (6.1.4.4)
23 | actionpack (= 6.1.4.4)
24 | actionview (= 6.1.4.4)
25 | activejob (= 6.1.4.4)
26 | activesupport (= 6.1.4.4)
27 | mail (~> 2.5, >= 2.5.4)
28 | rails-dom-testing (~> 2.0)
29 | actionpack (6.1.4.4)
30 | actionview (= 6.1.4.4)
31 | activesupport (= 6.1.4.4)
32 | rack (~> 2.0, >= 2.0.9)
33 | rack-test (>= 0.6.3)
34 | rails-dom-testing (~> 2.0)
35 | rails-html-sanitizer (~> 1.0, >= 1.2.0)
36 | actiontext (6.1.4.4)
37 | actionpack (= 6.1.4.4)
38 | activerecord (= 6.1.4.4)
39 | activestorage (= 6.1.4.4)
40 | activesupport (= 6.1.4.4)
41 | nokogiri (>= 1.8.5)
42 | actionview (6.1.4.4)
43 | activesupport (= 6.1.4.4)
44 | builder (~> 3.1)
45 | erubi (~> 1.4)
46 | rails-dom-testing (~> 2.0)
47 | rails-html-sanitizer (~> 1.1, >= 1.2.0)
48 | activejob (6.1.4.4)
49 | activesupport (= 6.1.4.4)
50 | globalid (>= 0.3.6)
51 | activemodel (6.1.4.4)
52 | activesupport (= 6.1.4.4)
53 | activerecord (6.1.4.4)
54 | activemodel (= 6.1.4.4)
55 | activesupport (= 6.1.4.4)
56 | activestorage (6.1.4.4)
57 | actionpack (= 6.1.4.4)
58 | activejob (= 6.1.4.4)
59 | activerecord (= 6.1.4.4)
60 | activesupport (= 6.1.4.4)
61 | marcel (~> 1.0.0)
62 | mini_mime (>= 1.1.0)
63 | activesupport (6.1.4.4)
64 | concurrent-ruby (~> 1.0, >= 1.0.2)
65 | i18n (>= 1.6, < 2)
66 | minitest (>= 5.1)
67 | tzinfo (~> 2.0)
68 | zeitwerk (~> 2.3)
69 | builder (3.2.4)
70 | bump (0.8.0)
71 | concurrent-ruby (1.1.9)
72 | crass (1.0.6)
73 | diff-lcs (1.4.4)
74 | erubi (1.10.0)
75 | globalid (1.0.0)
76 | activesupport (>= 5.0)
77 | i18n (1.8.11)
78 | concurrent-ruby (~> 1.0)
79 | loofah (2.13.0)
80 | crass (~> 1.0.2)
81 | nokogiri (>= 1.5.9)
82 | mail (2.7.1)
83 | mini_mime (>= 0.1.1)
84 | marcel (1.0.2)
85 | method_source (1.0.0)
86 | mini_mime (1.1.2)
87 | mini_portile2 (2.8.7)
88 | minitest (5.15.0)
89 | nio4r (2.5.8)
90 | nokogiri (1.16.7)
91 | mini_portile2 (~> 2.8.2)
92 | racc (~> 1.4)
93 | racc (1.8.1)
94 | rack (2.2.3)
95 | rack-test (1.1.0)
96 | rack (>= 1.0, < 3)
97 | rails (6.1.4.4)
98 | actioncable (= 6.1.4.4)
99 | actionmailbox (= 6.1.4.4)
100 | actionmailer (= 6.1.4.4)
101 | actionpack (= 6.1.4.4)
102 | actiontext (= 6.1.4.4)
103 | actionview (= 6.1.4.4)
104 | activejob (= 6.1.4.4)
105 | activemodel (= 6.1.4.4)
106 | activerecord (= 6.1.4.4)
107 | activestorage (= 6.1.4.4)
108 | activesupport (= 6.1.4.4)
109 | bundler (>= 1.15.0)
110 | railties (= 6.1.4.4)
111 | sprockets-rails (>= 2.0.0)
112 | rails-dom-testing (2.0.3)
113 | activesupport (>= 4.2.0)
114 | nokogiri (>= 1.6)
115 | rails-html-sanitizer (1.4.2)
116 | loofah (~> 2.3)
117 | railties (6.1.4.4)
118 | actionpack (= 6.1.4.4)
119 | activesupport (= 6.1.4.4)
120 | method_source
121 | rake (>= 0.13)
122 | thor (~> 1.0)
123 | rake (13.0.6)
124 | rspec (3.10.0)
125 | rspec-core (~> 3.10.0)
126 | rspec-expectations (~> 3.10.0)
127 | rspec-mocks (~> 3.10.0)
128 | rspec-core (3.10.0)
129 | rspec-support (~> 3.10.0)
130 | rspec-expectations (3.10.0)
131 | diff-lcs (>= 1.2.0, < 2.0)
132 | rspec-support (~> 3.10.0)
133 | rspec-mocks (3.10.0)
134 | diff-lcs (>= 1.2.0, < 2.0)
135 | rspec-support (~> 3.10.0)
136 | rspec-support (3.10.0)
137 | sprockets (4.0.2)
138 | concurrent-ruby (~> 1.0)
139 | rack (> 1, < 3)
140 | sprockets-rails (3.4.2)
141 | actionpack (>= 5.2)
142 | activesupport (>= 5.2)
143 | sprockets (>= 3.0.0)
144 | sqlite3 (1.4.4)
145 | thor (1.2.1)
146 | tzinfo (2.0.4)
147 | concurrent-ruby (~> 1.0)
148 | websocket-driver (0.7.5)
149 | websocket-extensions (>= 0.1.0)
150 | websocket-extensions (0.1.5)
151 | wwtd (1.3.0)
152 | zeitwerk (2.5.3)
153 |
154 | PLATFORMS
155 | ruby
156 |
157 | DEPENDENCIES
158 | activerecord (~> 6.1.0)
159 | ar_after_transaction!
160 | bump
161 | rails
162 | rake
163 | rspec (~> 3)
164 | sqlite3 (~> 1.0)
165 | wwtd
166 |
167 | BUNDLED WITH
168 | 2.3.12
169 |
--------------------------------------------------------------------------------
/gemfiles/rails7.0.gemfile:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | source 'https://rubygems.org'
4 |
5 | gem 'activerecord', '~>7.0.0'
6 |
7 | gemspec path: '../'
8 |
--------------------------------------------------------------------------------
/gemfiles/rails7.0.gemfile.lock:
--------------------------------------------------------------------------------
1 | PATH
2 | remote: ..
3 | specs:
4 | ar_after_transaction (0.13.0)
5 | activerecord (>= 6.1.0, < 8.1)
6 |
7 | GEM
8 | remote: https://rubygems.org/
9 | specs:
10 | actioncable (7.0.1)
11 | actionpack (= 7.0.1)
12 | activesupport (= 7.0.1)
13 | nio4r (~> 2.0)
14 | websocket-driver (>= 0.6.1)
15 | actionmailbox (7.0.1)
16 | actionpack (= 7.0.1)
17 | activejob (= 7.0.1)
18 | activerecord (= 7.0.1)
19 | activestorage (= 7.0.1)
20 | activesupport (= 7.0.1)
21 | mail (>= 2.7.1)
22 | net-imap
23 | net-pop
24 | net-smtp
25 | actionmailer (7.0.1)
26 | actionpack (= 7.0.1)
27 | actionview (= 7.0.1)
28 | activejob (= 7.0.1)
29 | activesupport (= 7.0.1)
30 | mail (~> 2.5, >= 2.5.4)
31 | net-imap
32 | net-pop
33 | net-smtp
34 | rails-dom-testing (~> 2.0)
35 | actionpack (7.0.1)
36 | actionview (= 7.0.1)
37 | activesupport (= 7.0.1)
38 | rack (~> 2.0, >= 2.2.0)
39 | rack-test (>= 0.6.3)
40 | rails-dom-testing (~> 2.0)
41 | rails-html-sanitizer (~> 1.0, >= 1.2.0)
42 | actiontext (7.0.1)
43 | actionpack (= 7.0.1)
44 | activerecord (= 7.0.1)
45 | activestorage (= 7.0.1)
46 | activesupport (= 7.0.1)
47 | globalid (>= 0.6.0)
48 | nokogiri (>= 1.8.5)
49 | actionview (7.0.1)
50 | activesupport (= 7.0.1)
51 | builder (~> 3.1)
52 | erubi (~> 1.4)
53 | rails-dom-testing (~> 2.0)
54 | rails-html-sanitizer (~> 1.1, >= 1.2.0)
55 | activejob (7.0.1)
56 | activesupport (= 7.0.1)
57 | globalid (>= 0.3.6)
58 | activemodel (7.0.1)
59 | activesupport (= 7.0.1)
60 | activerecord (7.0.1)
61 | activemodel (= 7.0.1)
62 | activesupport (= 7.0.1)
63 | activestorage (7.0.1)
64 | actionpack (= 7.0.1)
65 | activejob (= 7.0.1)
66 | activerecord (= 7.0.1)
67 | activesupport (= 7.0.1)
68 | marcel (~> 1.0)
69 | mini_mime (>= 1.1.0)
70 | activesupport (7.0.1)
71 | concurrent-ruby (~> 1.0, >= 1.0.2)
72 | i18n (>= 1.6, < 2)
73 | minitest (>= 5.1)
74 | tzinfo (~> 2.0)
75 | builder (3.2.4)
76 | bump (0.8.0)
77 | concurrent-ruby (1.1.9)
78 | crass (1.0.6)
79 | diff-lcs (1.4.4)
80 | digest (3.1.0)
81 | erubi (1.10.0)
82 | globalid (1.0.0)
83 | activesupport (>= 5.0)
84 | i18n (1.8.11)
85 | concurrent-ruby (~> 1.0)
86 | io-wait (0.2.1)
87 | loofah (2.13.0)
88 | crass (~> 1.0.2)
89 | nokogiri (>= 1.5.9)
90 | mail (2.7.1)
91 | mini_mime (>= 0.1.1)
92 | marcel (1.0.2)
93 | method_source (1.0.0)
94 | mini_mime (1.1.2)
95 | mini_portile2 (2.8.7)
96 | minitest (5.15.0)
97 | net-imap (0.2.3)
98 | digest
99 | net-protocol
100 | strscan
101 | net-pop (0.1.1)
102 | digest
103 | net-protocol
104 | timeout
105 | net-protocol (0.1.2)
106 | io-wait
107 | timeout
108 | net-smtp (0.3.1)
109 | digest
110 | net-protocol
111 | timeout
112 | nio4r (2.5.8)
113 | nokogiri (1.16.7)
114 | mini_portile2 (~> 2.8.2)
115 | racc (~> 1.4)
116 | racc (1.8.1)
117 | rack (2.2.3)
118 | rack-test (1.1.0)
119 | rack (>= 1.0, < 3)
120 | rails (7.0.1)
121 | actioncable (= 7.0.1)
122 | actionmailbox (= 7.0.1)
123 | actionmailer (= 7.0.1)
124 | actionpack (= 7.0.1)
125 | actiontext (= 7.0.1)
126 | actionview (= 7.0.1)
127 | activejob (= 7.0.1)
128 | activemodel (= 7.0.1)
129 | activerecord (= 7.0.1)
130 | activestorage (= 7.0.1)
131 | activesupport (= 7.0.1)
132 | bundler (>= 1.15.0)
133 | railties (= 7.0.1)
134 | rails-dom-testing (2.0.3)
135 | activesupport (>= 4.2.0)
136 | nokogiri (>= 1.6)
137 | rails-html-sanitizer (1.4.2)
138 | loofah (~> 2.3)
139 | railties (7.0.1)
140 | actionpack (= 7.0.1)
141 | activesupport (= 7.0.1)
142 | method_source
143 | rake (>= 12.2)
144 | thor (~> 1.0)
145 | zeitwerk (~> 2.5)
146 | rake (13.0.6)
147 | rspec (3.10.0)
148 | rspec-core (~> 3.10.0)
149 | rspec-expectations (~> 3.10.0)
150 | rspec-mocks (~> 3.10.0)
151 | rspec-core (3.10.0)
152 | rspec-support (~> 3.10.0)
153 | rspec-expectations (3.10.0)
154 | diff-lcs (>= 1.2.0, < 2.0)
155 | rspec-support (~> 3.10.0)
156 | rspec-mocks (3.10.0)
157 | diff-lcs (>= 1.2.0, < 2.0)
158 | rspec-support (~> 3.10.0)
159 | rspec-support (3.10.0)
160 | sqlite3 (1.4.4)
161 | strscan (3.0.1)
162 | thor (1.2.1)
163 | timeout (0.2.0)
164 | tzinfo (2.0.4)
165 | concurrent-ruby (~> 1.0)
166 | websocket-driver (0.7.5)
167 | websocket-extensions (>= 0.1.0)
168 | websocket-extensions (0.1.5)
169 | wwtd (1.3.0)
170 | zeitwerk (2.5.3)
171 |
172 | PLATFORMS
173 | ruby
174 |
175 | DEPENDENCIES
176 | activerecord (~> 7.0.0)
177 | ar_after_transaction!
178 | bump
179 | rails
180 | rake
181 | rspec (~> 3)
182 | sqlite3 (~> 1.0)
183 | wwtd
184 |
185 | BUNDLED WITH
186 | 2.3.12
187 |
--------------------------------------------------------------------------------
/gemfiles/rails7.1.gemfile:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | source 'https://rubygems.org'
4 |
5 | gem 'activerecord', '~>7.1.0'
6 |
7 | gemspec path: '../'
8 |
--------------------------------------------------------------------------------
/gemfiles/rails7.1.gemfile.lock:
--------------------------------------------------------------------------------
1 | PATH
2 | remote: ..
3 | specs:
4 | ar_after_transaction (0.13.0)
5 | activerecord (>= 6.1.0, < 8.1)
6 |
7 | GEM
8 | remote: https://rubygems.org/
9 | specs:
10 | actioncable (7.1.0)
11 | actionpack (= 7.1.0)
12 | activesupport (= 7.1.0)
13 | nio4r (~> 2.0)
14 | websocket-driver (>= 0.6.1)
15 | zeitwerk (~> 2.6)
16 | actionmailbox (7.1.0)
17 | actionpack (= 7.1.0)
18 | activejob (= 7.1.0)
19 | activerecord (= 7.1.0)
20 | activestorage (= 7.1.0)
21 | activesupport (= 7.1.0)
22 | mail (>= 2.7.1)
23 | net-imap
24 | net-pop
25 | net-smtp
26 | actionmailer (7.1.0)
27 | actionpack (= 7.1.0)
28 | actionview (= 7.1.0)
29 | activejob (= 7.1.0)
30 | activesupport (= 7.1.0)
31 | mail (~> 2.5, >= 2.5.4)
32 | net-imap
33 | net-pop
34 | net-smtp
35 | rails-dom-testing (~> 2.2)
36 | actionpack (7.1.0)
37 | actionview (= 7.1.0)
38 | activesupport (= 7.1.0)
39 | nokogiri (>= 1.8.5)
40 | rack (>= 2.2.4)
41 | rack-session (>= 1.0.1)
42 | rack-test (>= 0.6.3)
43 | rails-dom-testing (~> 2.2)
44 | rails-html-sanitizer (~> 1.6)
45 | actiontext (7.1.0)
46 | actionpack (= 7.1.0)
47 | activerecord (= 7.1.0)
48 | activestorage (= 7.1.0)
49 | activesupport (= 7.1.0)
50 | globalid (>= 0.6.0)
51 | nokogiri (>= 1.8.5)
52 | actionview (7.1.0)
53 | activesupport (= 7.1.0)
54 | builder (~> 3.1)
55 | erubi (~> 1.11)
56 | rails-dom-testing (~> 2.2)
57 | rails-html-sanitizer (~> 1.6)
58 | activejob (7.1.0)
59 | activesupport (= 7.1.0)
60 | globalid (>= 0.3.6)
61 | activemodel (7.1.0)
62 | activesupport (= 7.1.0)
63 | activerecord (7.1.0)
64 | activemodel (= 7.1.0)
65 | activesupport (= 7.1.0)
66 | timeout (>= 0.4.0)
67 | activestorage (7.1.0)
68 | actionpack (= 7.1.0)
69 | activejob (= 7.1.0)
70 | activerecord (= 7.1.0)
71 | activesupport (= 7.1.0)
72 | marcel (~> 1.0)
73 | activesupport (7.1.0)
74 | base64
75 | bigdecimal
76 | concurrent-ruby (~> 1.0, >= 1.0.2)
77 | connection_pool (>= 2.2.5)
78 | drb
79 | i18n (>= 1.6, < 2)
80 | minitest (>= 5.1)
81 | mutex_m
82 | tzinfo (~> 2.0)
83 | base64 (0.1.1)
84 | bigdecimal (3.1.4)
85 | builder (3.2.4)
86 | bump (0.10.0)
87 | concurrent-ruby (1.2.2)
88 | connection_pool (2.4.1)
89 | crass (1.0.6)
90 | date (3.3.3)
91 | diff-lcs (1.5.0)
92 | drb (2.1.1)
93 | ruby2_keywords
94 | erubi (1.12.0)
95 | globalid (1.2.1)
96 | activesupport (>= 6.1)
97 | i18n (1.14.1)
98 | concurrent-ruby (~> 1.0)
99 | io-console (0.6.0)
100 | irb (1.8.1)
101 | rdoc
102 | reline (>= 0.3.8)
103 | loofah (2.21.3)
104 | crass (~> 1.0.2)
105 | nokogiri (>= 1.12.0)
106 | mail (2.8.1)
107 | mini_mime (>= 0.1.1)
108 | net-imap
109 | net-pop
110 | net-smtp
111 | marcel (1.0.2)
112 | mini_mime (1.1.5)
113 | minitest (5.20.0)
114 | mutex_m (0.1.2)
115 | net-imap (0.4.0)
116 | date
117 | net-protocol
118 | net-pop (0.1.2)
119 | net-protocol
120 | net-protocol (0.2.1)
121 | timeout
122 | net-smtp (0.4.0)
123 | net-protocol
124 | nio4r (2.5.9)
125 | nokogiri (1.16.7-arm64-darwin)
126 | racc (~> 1.4)
127 | nokogiri (1.16.7-x86_64-linux)
128 | racc (~> 1.4)
129 | psych (5.1.0)
130 | stringio
131 | racc (1.8.1)
132 | rack (3.0.8)
133 | rack-session (2.0.0)
134 | rack (>= 3.0.0)
135 | rack-test (2.1.0)
136 | rack (>= 1.3)
137 | rackup (2.1.0)
138 | rack (>= 3)
139 | webrick (~> 1.8)
140 | rails (7.1.0)
141 | actioncable (= 7.1.0)
142 | actionmailbox (= 7.1.0)
143 | actionmailer (= 7.1.0)
144 | actionpack (= 7.1.0)
145 | actiontext (= 7.1.0)
146 | actionview (= 7.1.0)
147 | activejob (= 7.1.0)
148 | activemodel (= 7.1.0)
149 | activerecord (= 7.1.0)
150 | activestorage (= 7.1.0)
151 | activesupport (= 7.1.0)
152 | bundler (>= 1.15.0)
153 | railties (= 7.1.0)
154 | rails-dom-testing (2.2.0)
155 | activesupport (>= 5.0.0)
156 | minitest
157 | nokogiri (>= 1.6)
158 | rails-html-sanitizer (1.6.0)
159 | loofah (~> 2.21)
160 | nokogiri (~> 1.14)
161 | railties (7.1.0)
162 | actionpack (= 7.1.0)
163 | activesupport (= 7.1.0)
164 | irb
165 | rackup (>= 1.0.0)
166 | rake (>= 12.2)
167 | thor (~> 1.0, >= 1.2.2)
168 | zeitwerk (~> 2.6)
169 | rake (13.0.6)
170 | rdoc (6.5.0)
171 | psych (>= 4.0.0)
172 | reline (0.3.9)
173 | io-console (~> 0.5)
174 | rspec (3.12.0)
175 | rspec-core (~> 3.12.0)
176 | rspec-expectations (~> 3.12.0)
177 | rspec-mocks (~> 3.12.0)
178 | rspec-core (3.12.2)
179 | rspec-support (~> 3.12.0)
180 | rspec-expectations (3.12.3)
181 | diff-lcs (>= 1.2.0, < 2.0)
182 | rspec-support (~> 3.12.0)
183 | rspec-mocks (3.12.6)
184 | diff-lcs (>= 1.2.0, < 2.0)
185 | rspec-support (~> 3.12.0)
186 | rspec-support (3.12.1)
187 | ruby2_keywords (0.0.5)
188 | sqlite3 (1.7.3-arm64-darwin)
189 | sqlite3 (1.7.3-x86_64-linux)
190 | stringio (3.0.8)
191 | thor (1.2.2)
192 | timeout (0.4.0)
193 | tzinfo (2.0.6)
194 | concurrent-ruby (~> 1.0)
195 | webrick (1.8.1)
196 | websocket-driver (0.7.6)
197 | websocket-extensions (>= 0.1.0)
198 | websocket-extensions (0.1.5)
199 | wwtd (1.4.1)
200 | zeitwerk (2.6.12)
201 |
202 | PLATFORMS
203 | arm64-darwin-21
204 | arm64-darwin-23
205 | x86_64-linux
206 |
207 | DEPENDENCIES
208 | activerecord (~> 7.1.0)
209 | ar_after_transaction!
210 | bump
211 | rails
212 | rake
213 | rspec (~> 3)
214 | sqlite3 (~> 1.0)
215 | wwtd
216 |
217 | BUNDLED WITH
218 | 2.3.12
219 |
--------------------------------------------------------------------------------
/gemfiles/rails7.2.gemfile:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | source 'https://rubygems.org'
4 |
5 | gem 'activerecord', '~>7.2.0'
6 |
7 | gemspec path: '../'
8 |
--------------------------------------------------------------------------------
/gemfiles/rails7.2.gemfile.lock:
--------------------------------------------------------------------------------
1 | PATH
2 | remote: ..
3 | specs:
4 | ar_after_transaction (0.13.0)
5 | activerecord (>= 6.1.0, < 8.1)
6 |
7 | GEM
8 | remote: https://rubygems.org/
9 | specs:
10 | actioncable (7.2.0)
11 | actionpack (= 7.2.0)
12 | activesupport (= 7.2.0)
13 | nio4r (~> 2.0)
14 | websocket-driver (>= 0.6.1)
15 | zeitwerk (~> 2.6)
16 | actionmailbox (7.2.0)
17 | actionpack (= 7.2.0)
18 | activejob (= 7.2.0)
19 | activerecord (= 7.2.0)
20 | activestorage (= 7.2.0)
21 | activesupport (= 7.2.0)
22 | mail (>= 2.8.0)
23 | actionmailer (7.2.0)
24 | actionpack (= 7.2.0)
25 | actionview (= 7.2.0)
26 | activejob (= 7.2.0)
27 | activesupport (= 7.2.0)
28 | mail (>= 2.8.0)
29 | rails-dom-testing (~> 2.2)
30 | actionpack (7.2.0)
31 | actionview (= 7.2.0)
32 | activesupport (= 7.2.0)
33 | nokogiri (>= 1.8.5)
34 | racc
35 | rack (>= 2.2.4, < 3.2)
36 | rack-session (>= 1.0.1)
37 | rack-test (>= 0.6.3)
38 | rails-dom-testing (~> 2.2)
39 | rails-html-sanitizer (~> 1.6)
40 | useragent (~> 0.16)
41 | actiontext (7.2.0)
42 | actionpack (= 7.2.0)
43 | activerecord (= 7.2.0)
44 | activestorage (= 7.2.0)
45 | activesupport (= 7.2.0)
46 | globalid (>= 0.6.0)
47 | nokogiri (>= 1.8.5)
48 | actionview (7.2.0)
49 | activesupport (= 7.2.0)
50 | builder (~> 3.1)
51 | erubi (~> 1.11)
52 | rails-dom-testing (~> 2.2)
53 | rails-html-sanitizer (~> 1.6)
54 | activejob (7.2.0)
55 | activesupport (= 7.2.0)
56 | globalid (>= 0.3.6)
57 | activemodel (7.2.0)
58 | activesupport (= 7.2.0)
59 | activerecord (7.2.0)
60 | activemodel (= 7.2.0)
61 | activesupport (= 7.2.0)
62 | timeout (>= 0.4.0)
63 | activestorage (7.2.0)
64 | actionpack (= 7.2.0)
65 | activejob (= 7.2.0)
66 | activerecord (= 7.2.0)
67 | activesupport (= 7.2.0)
68 | marcel (~> 1.0)
69 | activesupport (7.2.0)
70 | base64
71 | bigdecimal
72 | concurrent-ruby (~> 1.0, >= 1.3.1)
73 | connection_pool (>= 2.2.5)
74 | drb
75 | i18n (>= 1.6, < 2)
76 | logger (>= 1.4.2)
77 | minitest (>= 5.1)
78 | securerandom (>= 0.3)
79 | tzinfo (~> 2.0, >= 2.0.5)
80 | base64 (0.2.0)
81 | bigdecimal (3.1.8)
82 | builder (3.3.0)
83 | bump (0.10.0)
84 | concurrent-ruby (1.3.4)
85 | connection_pool (2.4.1)
86 | crass (1.0.6)
87 | date (3.3.4)
88 | diff-lcs (1.5.1)
89 | drb (2.2.1)
90 | erubi (1.13.0)
91 | globalid (1.2.1)
92 | activesupport (>= 6.1)
93 | i18n (1.14.5)
94 | concurrent-ruby (~> 1.0)
95 | io-console (0.7.2)
96 | irb (1.14.0)
97 | rdoc (>= 4.0.0)
98 | reline (>= 0.4.2)
99 | logger (1.6.0)
100 | loofah (2.22.0)
101 | crass (~> 1.0.2)
102 | nokogiri (>= 1.12.0)
103 | mail (2.8.1)
104 | mini_mime (>= 0.1.1)
105 | net-imap
106 | net-pop
107 | net-smtp
108 | marcel (1.0.4)
109 | mini_mime (1.1.5)
110 | minitest (5.25.1)
111 | net-imap (0.4.14)
112 | date
113 | net-protocol
114 | net-pop (0.1.2)
115 | net-protocol
116 | net-protocol (0.2.2)
117 | timeout
118 | net-smtp (0.5.0)
119 | net-protocol
120 | nio4r (2.7.3)
121 | nokogiri (1.16.7-aarch64-linux)
122 | racc (~> 1.4)
123 | nokogiri (1.16.7-arm-linux)
124 | racc (~> 1.4)
125 | nokogiri (1.16.7-arm64-darwin)
126 | racc (~> 1.4)
127 | nokogiri (1.16.7-x86-linux)
128 | racc (~> 1.4)
129 | nokogiri (1.16.7-x86_64-darwin)
130 | racc (~> 1.4)
131 | nokogiri (1.16.7-x86_64-linux)
132 | racc (~> 1.4)
133 | psych (5.1.2)
134 | stringio
135 | racc (1.8.1)
136 | rack (3.1.7)
137 | rack-session (2.0.0)
138 | rack (>= 3.0.0)
139 | rack-test (2.1.0)
140 | rack (>= 1.3)
141 | rackup (2.1.0)
142 | rack (>= 3)
143 | webrick (~> 1.8)
144 | rails (7.2.0)
145 | actioncable (= 7.2.0)
146 | actionmailbox (= 7.2.0)
147 | actionmailer (= 7.2.0)
148 | actionpack (= 7.2.0)
149 | actiontext (= 7.2.0)
150 | actionview (= 7.2.0)
151 | activejob (= 7.2.0)
152 | activemodel (= 7.2.0)
153 | activerecord (= 7.2.0)
154 | activestorage (= 7.2.0)
155 | activesupport (= 7.2.0)
156 | bundler (>= 1.15.0)
157 | railties (= 7.2.0)
158 | rails-dom-testing (2.2.0)
159 | activesupport (>= 5.0.0)
160 | minitest
161 | nokogiri (>= 1.6)
162 | rails-html-sanitizer (1.6.0)
163 | loofah (~> 2.21)
164 | nokogiri (~> 1.14)
165 | railties (7.2.0)
166 | actionpack (= 7.2.0)
167 | activesupport (= 7.2.0)
168 | irb (~> 1.13)
169 | rackup (>= 1.0.0)
170 | rake (>= 12.2)
171 | thor (~> 1.0, >= 1.2.2)
172 | zeitwerk (~> 2.6)
173 | rake (13.2.1)
174 | rdoc (6.7.0)
175 | psych (>= 4.0.0)
176 | reline (0.5.9)
177 | io-console (~> 0.5)
178 | rspec (3.13.0)
179 | rspec-core (~> 3.13.0)
180 | rspec-expectations (~> 3.13.0)
181 | rspec-mocks (~> 3.13.0)
182 | rspec-core (3.13.0)
183 | rspec-support (~> 3.13.0)
184 | rspec-expectations (3.13.1)
185 | diff-lcs (>= 1.2.0, < 2.0)
186 | rspec-support (~> 3.13.0)
187 | rspec-mocks (3.13.1)
188 | diff-lcs (>= 1.2.0, < 2.0)
189 | rspec-support (~> 3.13.0)
190 | rspec-support (3.13.1)
191 | securerandom (0.3.1)
192 | sqlite3 (1.7.3-aarch64-linux)
193 | sqlite3 (1.7.3-arm-linux)
194 | sqlite3 (1.7.3-arm64-darwin)
195 | sqlite3 (1.7.3-x86-linux)
196 | sqlite3 (1.7.3-x86_64-darwin)
197 | sqlite3 (1.7.3-x86_64-linux)
198 | stringio (3.1.1)
199 | thor (1.3.1)
200 | timeout (0.4.1)
201 | tzinfo (2.0.6)
202 | concurrent-ruby (~> 1.0)
203 | useragent (0.16.10)
204 | webrick (1.8.1)
205 | websocket-driver (0.7.6)
206 | websocket-extensions (>= 0.1.0)
207 | websocket-extensions (0.1.5)
208 | wwtd (1.4.1)
209 | zeitwerk (2.6.17)
210 |
211 | PLATFORMS
212 | aarch64-linux
213 | arm-linux
214 | arm64-darwin
215 | x86-linux
216 | x86_64-darwin
217 | x86_64-linux
218 |
219 | DEPENDENCIES
220 | activerecord (~> 7.2.0)
221 | ar_after_transaction!
222 | bump
223 | rails
224 | rake
225 | rspec (~> 3)
226 | sqlite3 (~> 1.0)
227 | wwtd
228 |
229 | BUNDLED WITH
230 | 2.5.14
231 |
--------------------------------------------------------------------------------
/gemfiles/rails8.0.gemfile:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | source 'https://rubygems.org'
4 |
5 | gem 'activerecord', '~>8.0.0'
6 | gem 'sqlite3', '~> 2.1'
7 |
8 | gemspec path: '../'
9 |
--------------------------------------------------------------------------------
/gemfiles/rails8.0.gemfile.lock:
--------------------------------------------------------------------------------
1 | PATH
2 | remote: ..
3 | specs:
4 | ar_after_transaction (0.13.0)
5 | activerecord (>= 6.1.0, < 8.1)
6 |
7 | GEM
8 | remote: https://rubygems.org/
9 | specs:
10 | actioncable (8.0.0)
11 | actionpack (= 8.0.0)
12 | activesupport (= 8.0.0)
13 | nio4r (~> 2.0)
14 | websocket-driver (>= 0.6.1)
15 | zeitwerk (~> 2.6)
16 | actionmailbox (8.0.0)
17 | actionpack (= 8.0.0)
18 | activejob (= 8.0.0)
19 | activerecord (= 8.0.0)
20 | activestorage (= 8.0.0)
21 | activesupport (= 8.0.0)
22 | mail (>= 2.8.0)
23 | actionmailer (8.0.0)
24 | actionpack (= 8.0.0)
25 | actionview (= 8.0.0)
26 | activejob (= 8.0.0)
27 | activesupport (= 8.0.0)
28 | mail (>= 2.8.0)
29 | rails-dom-testing (~> 2.2)
30 | actionpack (8.0.0)
31 | actionview (= 8.0.0)
32 | activesupport (= 8.0.0)
33 | nokogiri (>= 1.8.5)
34 | rack (>= 2.2.4)
35 | rack-session (>= 1.0.1)
36 | rack-test (>= 0.6.3)
37 | rails-dom-testing (~> 2.2)
38 | rails-html-sanitizer (~> 1.6)
39 | useragent (~> 0.16)
40 | actiontext (8.0.0)
41 | actionpack (= 8.0.0)
42 | activerecord (= 8.0.0)
43 | activestorage (= 8.0.0)
44 | activesupport (= 8.0.0)
45 | globalid (>= 0.6.0)
46 | nokogiri (>= 1.8.5)
47 | actionview (8.0.0)
48 | activesupport (= 8.0.0)
49 | builder (~> 3.1)
50 | erubi (~> 1.11)
51 | rails-dom-testing (~> 2.2)
52 | rails-html-sanitizer (~> 1.6)
53 | activejob (8.0.0)
54 | activesupport (= 8.0.0)
55 | globalid (>= 0.3.6)
56 | activemodel (8.0.0)
57 | activesupport (= 8.0.0)
58 | activerecord (8.0.0)
59 | activemodel (= 8.0.0)
60 | activesupport (= 8.0.0)
61 | timeout (>= 0.4.0)
62 | activestorage (8.0.0)
63 | actionpack (= 8.0.0)
64 | activejob (= 8.0.0)
65 | activerecord (= 8.0.0)
66 | activesupport (= 8.0.0)
67 | marcel (~> 1.0)
68 | activesupport (8.0.0)
69 | base64
70 | benchmark (>= 0.3)
71 | bigdecimal
72 | concurrent-ruby (~> 1.0, >= 1.3.1)
73 | connection_pool (>= 2.2.5)
74 | drb
75 | i18n (>= 1.6, < 2)
76 | logger (>= 1.4.2)
77 | minitest (>= 5.1)
78 | securerandom (>= 0.3)
79 | tzinfo (~> 2.0, >= 2.0.5)
80 | uri (>= 0.13.1)
81 | base64 (0.2.0)
82 | benchmark (0.4.0)
83 | bigdecimal (3.1.8)
84 | builder (3.3.0)
85 | bump (0.10.0)
86 | concurrent-ruby (1.3.4)
87 | connection_pool (2.4.1)
88 | crass (1.0.6)
89 | date (3.4.1)
90 | diff-lcs (1.5.1)
91 | drb (2.2.1)
92 | erubi (1.13.0)
93 | globalid (1.2.1)
94 | activesupport (>= 6.1)
95 | i18n (1.14.6)
96 | concurrent-ruby (~> 1.0)
97 | io-console (0.8.0)
98 | irb (1.14.1)
99 | rdoc (>= 4.0.0)
100 | reline (>= 0.4.2)
101 | logger (1.6.2)
102 | loofah (2.23.1)
103 | crass (~> 1.0.2)
104 | nokogiri (>= 1.12.0)
105 | mail (2.8.1)
106 | mini_mime (>= 0.1.1)
107 | net-imap
108 | net-pop
109 | net-smtp
110 | marcel (1.0.4)
111 | mini_mime (1.1.5)
112 | minitest (5.25.4)
113 | net-imap (0.5.1)
114 | date
115 | net-protocol
116 | net-pop (0.1.2)
117 | net-protocol
118 | net-protocol (0.2.2)
119 | timeout
120 | net-smtp (0.5.0)
121 | net-protocol
122 | nio4r (2.7.4)
123 | nokogiri (1.17.1-aarch64-linux)
124 | racc (~> 1.4)
125 | nokogiri (1.17.1-arm-linux)
126 | racc (~> 1.4)
127 | nokogiri (1.17.1-arm64-darwin)
128 | racc (~> 1.4)
129 | nokogiri (1.17.1-x86-linux)
130 | racc (~> 1.4)
131 | nokogiri (1.17.1-x86_64-darwin)
132 | racc (~> 1.4)
133 | nokogiri (1.17.1-x86_64-linux)
134 | racc (~> 1.4)
135 | psych (5.2.1)
136 | date
137 | stringio
138 | racc (1.8.1)
139 | rack (3.1.8)
140 | rack-session (2.0.0)
141 | rack (>= 3.0.0)
142 | rack-test (2.1.0)
143 | rack (>= 1.3)
144 | rackup (2.2.1)
145 | rack (>= 3)
146 | rails (8.0.0)
147 | actioncable (= 8.0.0)
148 | actionmailbox (= 8.0.0)
149 | actionmailer (= 8.0.0)
150 | actionpack (= 8.0.0)
151 | actiontext (= 8.0.0)
152 | actionview (= 8.0.0)
153 | activejob (= 8.0.0)
154 | activemodel (= 8.0.0)
155 | activerecord (= 8.0.0)
156 | activestorage (= 8.0.0)
157 | activesupport (= 8.0.0)
158 | bundler (>= 1.15.0)
159 | railties (= 8.0.0)
160 | rails-dom-testing (2.2.0)
161 | activesupport (>= 5.0.0)
162 | minitest
163 | nokogiri (>= 1.6)
164 | rails-html-sanitizer (1.6.1)
165 | loofah (~> 2.21)
166 | nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0)
167 | railties (8.0.0)
168 | actionpack (= 8.0.0)
169 | activesupport (= 8.0.0)
170 | irb (~> 1.13)
171 | rackup (>= 1.0.0)
172 | rake (>= 12.2)
173 | thor (~> 1.0, >= 1.2.2)
174 | zeitwerk (~> 2.6)
175 | rake (13.2.1)
176 | rdoc (6.8.1)
177 | psych (>= 4.0.0)
178 | reline (0.5.12)
179 | io-console (~> 0.5)
180 | rspec (3.13.0)
181 | rspec-core (~> 3.13.0)
182 | rspec-expectations (~> 3.13.0)
183 | rspec-mocks (~> 3.13.0)
184 | rspec-core (3.13.2)
185 | rspec-support (~> 3.13.0)
186 | rspec-expectations (3.13.3)
187 | diff-lcs (>= 1.2.0, < 2.0)
188 | rspec-support (~> 3.13.0)
189 | rspec-mocks (3.13.2)
190 | diff-lcs (>= 1.2.0, < 2.0)
191 | rspec-support (~> 3.13.0)
192 | rspec-support (3.13.2)
193 | securerandom (0.4.0)
194 | sqlite3 (2.4.1-aarch64-linux-gnu)
195 | sqlite3 (2.4.1-arm-linux-gnu)
196 | sqlite3 (2.4.1-arm64-darwin)
197 | sqlite3 (2.4.1-x86-linux-gnu)
198 | sqlite3 (2.4.1-x86_64-darwin)
199 | sqlite3 (2.4.1-x86_64-linux-gnu)
200 | stringio (3.1.2)
201 | thor (1.3.2)
202 | timeout (0.4.2)
203 | tzinfo (2.0.6)
204 | concurrent-ruby (~> 1.0)
205 | uri (1.0.2)
206 | useragent (0.16.11)
207 | websocket-driver (0.7.6)
208 | websocket-extensions (>= 0.1.0)
209 | websocket-extensions (0.1.5)
210 | wwtd (1.4.1)
211 | zeitwerk (2.7.1)
212 |
213 | PLATFORMS
214 | aarch64-linux
215 | arm-linux
216 | arm64-darwin
217 | x86-linux
218 | x86_64-darwin
219 | x86_64-linux
220 |
221 | DEPENDENCIES
222 | activerecord (~> 8.0.0)
223 | ar_after_transaction!
224 | bump
225 | rails
226 | rake
227 | rspec (~> 3)
228 | sqlite3 (~> 2.1)
229 | wwtd
230 |
231 | BUNDLED WITH
232 | 2.5.22
233 |
--------------------------------------------------------------------------------
/lib/ar_after_transaction.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'active_record'
4 | require 'ar_after_transaction/version'
5 |
6 | module ARAfterTransaction
7 | module ClassMethods
8 | def after_transaction(&block)
9 | connection.after_transaction(&block)
10 | end
11 |
12 | def normally_open_transactions
13 | connection.normally_open_transactions ||= 0
14 | end
15 |
16 | delegate :normally_open_transactions=, to: :connection
17 |
18 | private
19 |
20 | def transactions_open?
21 | connection.send :transactions_open?
22 | end
23 | end
24 |
25 | module InstanceMethods
26 | def after_transaction(&block)
27 | self.class.connection.after_transaction(&block)
28 | end
29 | end
30 | end
31 |
32 | module ARAfterTransactionConnection
33 | def self.included(base)
34 | base.class_eval do
35 | attr_accessor :normally_open_transactions
36 | attr_accessor :after_transaction_callbacks
37 |
38 | alias_method :transaction_without_after, :transaction
39 | alias_method :transaction, :transaction_with_after
40 | end
41 | end
42 |
43 | def transaction_with_after(**args)
44 | clean = true
45 | transaction_without_after(**args) do
46 | yield
47 | rescue ActiveRecord::Rollback
48 | clean = false
49 | raise
50 | end
51 | rescue Exception
52 | clean = false
53 | raise
54 | ensure
55 | unless transactions_open?
56 | callbacks = delete_after_transaction_callbacks
57 | callbacks.each(&:call) if clean
58 | end
59 | end
60 |
61 | def after_transaction(&block)
62 | if transactions_open?
63 | self.after_transaction_callbacks ||= []
64 | self.after_transaction_callbacks << block
65 | else
66 | yield
67 | end
68 | end
69 |
70 | private
71 |
72 | def transactions_open?
73 | return false unless active?
74 |
75 | self.normally_open_transactions ||= 0
76 | open_transactions > normally_open_transactions
77 | end
78 |
79 | def delete_after_transaction_callbacks
80 | result = after_transaction_callbacks || []
81 | self.after_transaction_callbacks = []
82 | result
83 | end
84 | end
85 |
86 | ActiveRecord::Base.extend ARAfterTransaction::ClassMethods
87 | ActiveRecord::Base.include ARAfterTransaction::InstanceMethods
88 | ActiveRecord::ConnectionAdapters::AbstractAdapter.include ARAfterTransactionConnection
89 |
--------------------------------------------------------------------------------
/lib/ar_after_transaction/version.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module ARAfterTransaction
4 | VERSION = '0.13.0'
5 | end
6 |
--------------------------------------------------------------------------------
/spec/after_initialize_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'active_record'
4 | require 'rails'
5 | require_relative 'setup_database'
6 |
7 | if ActiveRecord::VERSION::MAJOR > 2
8 | require 'action_controller/railtie' if ActiveRecord::VERSION::MAJOR < 4
9 |
10 | module Passthrough
11 | def self.extended(base)
12 | base.class_eval do
13 | class << self
14 | alias_method :transaction_without_passthrough, :transaction
15 | alias_method :transaction, :transaction_with_passthrough
16 | end
17 | end
18 | end
19 |
20 | def transaction_with_passthrough(**args, &block)
21 | transaction_without_passthrough(**args, &block)
22 | end
23 | end
24 |
25 | class Railtie < ::Rails::Railtie
26 | config.after_initialize do
27 | ActiveRecord::Base.extend Passthrough
28 | end
29 | end
30 |
31 | module ARAfterTransaction
32 | class Application < ::Rails::Application
33 | config.eager_load = false
34 | config.active_support.deprecation = :log
35 |
36 | config.after_initialize do
37 | require 'ar_after_transaction'
38 | end
39 | end
40 | end
41 |
42 | if defined?(Rack::Session::Cookie)
43 | Rack::Session::Cookie.send(:define_method, :warn) { |_| } # silence secret warning
44 | end
45 | ARAfterTransaction::Application.initialize! # initialize app
46 |
47 | class AnExpectedError < RuntimeError; end
48 |
49 | class User
50 | cattr_accessor :test_callbacks, :test_stack
51 | self.test_stack = []
52 | self.test_callbacks = []
53 |
54 | after_create :do_it
55 | def do_it
56 | self.class.test_callbacks.map { |callback| send(callback) }.last
57 | end
58 |
59 | def do_after
60 | after_transaction do
61 | ActiveRecord::Base.transaction do
62 | # nested transaction should not cause infinitive recursion
63 | end
64 | self.class.test_stack << :after
65 | end
66 | end
67 |
68 | def do_normal
69 | self.class.test_stack << :normal
70 | end
71 |
72 | def oops
73 | raise AnExpectedError
74 | end
75 |
76 | def raise_rollback
77 | raise ActiveRecord::Rollback
78 | end
79 | end
80 |
81 | describe ARAfterTransaction do
82 | before do
83 | User.normally_open_transactions = nil
84 | expect(User.send(:transactions_open?)).to be_falsey
85 | User.test_stack.clear
86 | User.test_callbacks.clear
87 | end
88 |
89 | it 'has a VERSION' do
90 | expect(ARAfterTransaction::VERSION).to match(/^\d+\.\d+\.\d+$/)
91 | end
92 |
93 | it 'executes after a transaction' do
94 | User.test_callbacks = [:do_after, :do_normal]
95 | User.create!
96 | expect(User.test_stack).to eq [:normal, :after]
97 | end
98 | end
99 | end
100 |
--------------------------------------------------------------------------------
/spec/ar_after_transaction_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 |
5 | class AnExpectedError < RuntimeError; end
6 |
7 | class User
8 | cattr_accessor :test_callbacks, :test_stack
9 | self.test_stack = []
10 | self.test_callbacks = []
11 |
12 | after_create :do_it
13 | def do_it
14 | self.class.test_callbacks.map { |callback| send(callback) }.last
15 | end
16 |
17 | def do_after
18 | after_transaction do
19 | ActiveRecord::Base.transaction do
20 | # nested transaction should not cause infinitive recursion
21 | end
22 | self.class.test_stack << :after
23 | end
24 | end
25 |
26 | def do_normal
27 | self.class.test_stack << :normal
28 | end
29 |
30 | def oops
31 | raise AnExpectedError
32 | end
33 |
34 | def raise_rollback
35 | raise ActiveRecord::Rollback
36 | end
37 |
38 | def sigterm
39 | raise SignalException.new('TERM')
40 | end
41 | end
42 |
43 | describe ARAfterTransaction do
44 | before do
45 | User.normally_open_transactions = nil
46 | expect(User.send(:transactions_open?)).to be_falsey
47 | User.test_stack.clear
48 | User.test_callbacks.clear
49 | end
50 |
51 | it 'has a VERSION' do
52 | expect(ARAfterTransaction::VERSION).to match(/^\d+\.\d+\.\d+$/)
53 | end
54 |
55 | it 'executes after a transaction' do
56 | User.test_callbacks = [:do_after, :do_normal]
57 | User.create!
58 | expect(User.test_stack).to eq [:normal, :after]
59 | end
60 |
61 | it 'does not execute when transaction was rolled back by a StandardError' do
62 | User.test_callbacks = [:do_after, :do_normal, :oops]
63 | expect(-> { User.create! }).to raise_error(AnExpectedError)
64 | expect(User.test_stack).to eq [:normal]
65 | end
66 |
67 | it 'does not execute when transaction was rolled back by an Exception' do
68 | User.test_callbacks = [:do_after, :do_normal, :sigterm]
69 | expect(-> { User.create! }).to raise_error(SignalException)
70 | expect(User.test_stack).to eq [:normal]
71 | end
72 |
73 | it 'does not execute when transaction gets rolled back by ActiveRecord::Rollback '\
74 | 'raised in an after_create callback' do
75 | User.test_callbacks = [:do_after, :do_normal, :raise_rollback]
76 | User.create!
77 | expect(User.test_stack).to eq [:normal]
78 | end
79 |
80 | it 'does not execute when transaction gets rolled back by ActiveRecord::Rollback outside of the model' do
81 | User.test_callbacks = [:do_after, :do_normal]
82 | user = nil
83 | ActiveRecord::Base.transaction do
84 | user = User.create!
85 | raise ActiveRecord::Rollback
86 | end
87 | expect(User.test_stack).to eq [:normal]
88 | end
89 |
90 | it 'clears transaction callbacks when transaction fails' do
91 | User.test_callbacks = [:do_after, :do_normal, :oops]
92 | expect(-> { User.create! }).to raise_error(AnExpectedError)
93 | User.test_callbacks = [:do_normal]
94 | User.create!
95 | expect(User.test_stack).to eq [:normal, :normal]
96 | end
97 |
98 | it 'executes when no transaction is open' do
99 | user = User.new
100 | user.do_after
101 | user.do_normal
102 | expect(User.test_stack).to eq [:after, :normal]
103 | end
104 |
105 | it 'executes when open transactions are normal' do
106 | User.normally_open_transactions = 1
107 | User.test_callbacks = [:do_after, :do_normal]
108 | User.create!
109 | expect(User.test_stack).to eq [:after, :normal]
110 | end
111 |
112 | it 'does not execute the same callback twice when successful' do
113 | User.test_callbacks = [:do_after, :do_normal]
114 | User.create!
115 | User.create!
116 | expect(User.test_stack).to eq [:normal, :after, :normal, :after]
117 | end
118 |
119 | it 'does not execute the same callback twice when failed' do
120 | User.test_callbacks = [:do_after, :do_normal, :oops]
121 | expect(-> { User.create! }).to raise_error(AnExpectedError)
122 | expect(-> { User.create! }).to raise_error(AnExpectedError)
123 | expect(User.test_stack).to eq [:normal, :normal]
124 | end
125 |
126 | it 'does not crash with additional options' do
127 | expect(-> { User.transaction(requires_new: true) { true } }).not_to raise_error
128 | end
129 |
130 | describe '.normally_open_transactions' do
131 | subject(:transactions) { User.normally_open_transactions }
132 |
133 | it 'uses 0 by default' do
134 | expect(transactions).to eq 0
135 | end
136 |
137 | it 'can set normally open transactions' do
138 | User.normally_open_transactions = 5
139 | expect(transactions).to eq 5
140 | end
141 |
142 | it 'sets them globally' do
143 | User.normally_open_transactions = 5
144 | expect(ActiveRecord::Base.normally_open_transactions).to eq 5
145 | end
146 | end
147 | end
148 |
149 | describe 'A normal ActiveRecord subclass' do
150 | it 'does not get polluted' do
151 | expect(User.const_defined?('VERSION')).to be_falsey
152 | end
153 | end
154 |
--------------------------------------------------------------------------------
/spec/setup_database.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | ActiveRecord::Base.establish_connection(
4 | adapter: 'sqlite3',
5 | database: ':memory:'
6 | )
7 |
8 | ActiveRecord::Migration.verbose = false
9 | ActiveRecord::Schema.define(version: 1) do
10 | create_table :users do |t|
11 | t.string :name
12 | t.timestamps null: false
13 | end
14 | end
15 |
16 | # for detailed debugging:
17 | # require 'logger'
18 | # ActiveRecord::Base.logger = Logger.new(STDOUT)
19 |
20 | class User < ActiveRecord::Base; end
21 |
--------------------------------------------------------------------------------
/spec/spec_helper.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'bundler/setup'
4 | require 'ar_after_transaction'
5 | require_relative 'setup_database'
6 |
--------------------------------------------------------------------------------