trx_ext 1.0.6 → 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/.rspec +1 -1
- data/.ruby-version +1 -1
- data/CHANGELOG.md +24 -2
- data/Gemfile +20 -3
- data/README.md +39 -15
- data/bin/console +0 -9
- data/bin/rails +9 -0
- data/bin/test_all_ar_versions +1 -1
- data/docker/my.cnf +13 -0
- data/docker/mysqld.sh +22 -0
- data/docker-compose.yml +14 -2
- data/dummy_app/.gitattributes +7 -0
- data/dummy_app/.gitignore +38 -0
- data/dummy_app/README.md +24 -0
- data/dummy_app/Rakefile +6 -0
- data/dummy_app/app/controllers/application_controller.rb +2 -0
- data/dummy_app/app/models/application_mysql_record.rb +7 -0
- data/dummy_app/app/models/application_pg_record.rb +7 -0
- data/dummy_app/app/models/application_sqlite_record.rb +7 -0
- data/dummy_app/app/models/application_trilogy_record.rb +7 -0
- data/dummy_app/app/models/dummy_mysql_record.rb +11 -0
- data/dummy_app/app/models/dummy_pg_record.rb +11 -0
- data/dummy_app/app/models/dummy_sqlite_record.rb +11 -0
- data/dummy_app/app/models/dummy_trilogy_record.rb +11 -0
- data/dummy_app/bin/bundle +109 -0
- data/dummy_app/bin/rails +4 -0
- data/dummy_app/bin/rake +4 -0
- data/dummy_app/bin/setup +33 -0
- data/dummy_app/config/application.rb +51 -0
- data/dummy_app/config/boot.rb +4 -0
- data/dummy_app/config/credentials.yml +0 -0
- data/dummy_app/config/database.yml +70 -0
- data/dummy_app/config/environment.rb +5 -0
- data/dummy_app/config/environments/development.rb +66 -0
- data/dummy_app/config/environments/test.rb +61 -0
- data/dummy_app/config/initializers/.keep +0 -0
- data/dummy_app/config/locales/en.yml +2 -0
- data/dummy_app/config/locales/fr-CH.yml +2 -0
- data/dummy_app/config/puma.rb +43 -0
- data/dummy_app/config/routes.rb +5 -0
- data/dummy_app/config.ru +6 -0
- data/dummy_app/db/migrate/.keep +0 -0
- data/dummy_app/db/migrate/20240128111549_create_dummy_record.rb +10 -0
- data/dummy_app/db/primary_mysql/20240128111549_create_dummy_mysql_record.rb +10 -0
- data/dummy_app/db/primary_sqlite/20240128111549_create_dummy_sqlite_record.rb +10 -0
- data/dummy_app/db/primary_trilogy/20240128111549_create_dummy_trilogy_record.rb +10 -0
- data/dummy_app/db/seeds.rb +7 -0
- data/dummy_app/lib/tasks/.keep +0 -0
- data/dummy_app/log/.keep +0 -0
- data/dummy_app/public/robots.txt +1 -0
- data/dummy_app/storage/.keep +0 -0
- data/dummy_app/tmp/.keep +0 -0
- data/dummy_app/vendor/.keep +0 -0
- data/lib/trx_ext/object_ext.rb +12 -7
- data/lib/trx_ext/retry.rb +14 -16
- data/lib/trx_ext/transaction.rb +1 -1
- data/lib/trx_ext/version.rb +1 -1
- data/lib/trx_ext.rb +18 -21
- data/trx_ext.gemspec +1 -7
- metadata +57 -93
- data/Dockerfile +0 -3
- data/bin/setup +0 -8
- data/lib/trx_ext/railtie.rb +0 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b300fb55d7310a3e3f4d3a8860044f48deec84791caf6303d7a6b01a2e2728b7
|
4
|
+
data.tar.gz: 2e6d704c74c209b515dfc3a04d06ca549322a0e33d1037a414d779df1c063afd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 45c7190466168fe05b18ad69f084152b638235f9fab14edaa0eb6962449a2012b71e6e2b991fb319f73080cd7e3aba2f6700203a362cd86483d91f8ca606b66c
|
7
|
+
data.tar.gz: ce496ee423f04d12b9f92af4373e460edc31048d90908333f8449d98d70eb61053fd675c94f2345e767c5a43ae5535fa6b0e964f179dce604513aa782a8466e4
|
data/.rspec
CHANGED
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.
|
1
|
+
3.3.0
|
data/CHANGELOG.md
CHANGED
@@ -1,8 +1,30 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
-
|
3
|
+
## [2.0.1] - 2024-09-20
|
4
|
+
- Restrict rails version to `< 7.2`. Rails v7.2 has suddenly released its own transaction callbacks which interferes with `trx_ext` transaction callbacks. Example of rails v7.2 transaction callbacks:
|
4
5
|
|
5
|
-
|
6
|
+
```ruby
|
7
|
+
Article.transaction do |transaction|
|
8
|
+
article.update(published: true)
|
9
|
+
transaction.after_commit do
|
10
|
+
PublishNotificationMailer.with(article: article).deliver_later
|
11
|
+
end
|
12
|
+
end
|
13
|
+
```
|
14
|
+
|
15
|
+
Next major version of `trx_ext` will drop its own transaction callbacks implementation and will start relying on rails' transaction callbacks.
|
16
|
+
|
17
|
+
## [2.0.0] - 2024-04-14
|
18
|
+
|
19
|
+
- `trx_ext` now supports any adapter(except `mysql`; `mysql2` is supported though), supported by rails
|
20
|
+
- **Requirement is rails v7.1+ now**. This is because rails v7.1 introduced unification of connection adapters which allowed to implement the integration with all of them
|
21
|
+
- Support multiple databases configurations
|
22
|
+
|
23
|
+
## [1.0.6] - 2023-08-25
|
24
|
+
|
25
|
+
- Refactoring the retry implementation
|
26
|
+
|
27
|
+
## [1.0.5] - 2023-05-11
|
6
28
|
|
7
29
|
- Load `Object` extension earlier
|
8
30
|
|
data/Gemfile
CHANGED
@@ -5,12 +5,29 @@ source "https://rubygems.org"
|
|
5
5
|
# Specify your gem's dependencies in trx_ext.gemspec
|
6
6
|
gemspec
|
7
7
|
|
8
|
-
gem "rake", "~> 13.0"
|
9
|
-
|
10
8
|
if ENV['AR_VERSION']
|
11
9
|
# Given ENV['AR_VERSION'] to equal "6.0" will produce
|
12
10
|
# ```ruby
|
13
11
|
# gem 'activerecord', "~> 6.0", "< 6.1"
|
14
12
|
# ```
|
15
|
-
gem '
|
13
|
+
gem 'rails', "~> #{ENV['AR_VERSION']}", "< #{ENV['AR_VERSION'].next}"
|
14
|
+
else
|
15
|
+
gem 'rails'
|
16
16
|
end
|
17
|
+
|
18
|
+
gem "rake", "~> 13.0"
|
19
|
+
gem 'rspec', '~> 3.12'
|
20
|
+
gem 'timecop', '~> 0.9.8'
|
21
|
+
# To support postgresql adapter
|
22
|
+
gem 'pg', '~> 1.5', '>= 1.5.4'
|
23
|
+
# To support sqlite3 adapter
|
24
|
+
gem 'sqlite3', '~> 1.7', '>= 1.7.1'
|
25
|
+
# To support mysql2 adapter
|
26
|
+
gem 'mysql2', '~> 0.5.5'
|
27
|
+
# To support trilogy adapter
|
28
|
+
gem 'trilogy', '~> 2.8'
|
29
|
+
gem 'factory_bot_rails', '~> 6.4', '>= 6.4.3'
|
30
|
+
gem 'fivemat', '~> 1.3', '>= 1.3.7'
|
31
|
+
gem 'rspec-its', '~> 1.3'
|
32
|
+
gem "bootsnap", require: false
|
33
|
+
gem 'rspec-rails', '~> 6.0'
|
data/README.md
CHANGED
@@ -1,20 +1,22 @@
|
|
1
1
|
# TrxExt
|
2
2
|
|
3
|
-
Extends functionality of ActiveRecord's transaction to auto-retry failed SQL transaction in case of deadlock, serialization error or unique constraint error. It also allows you to define `on_complete` callback that is being executed after SQL transaction is finished(either COMMIT-ed or ROLLBACK-ed).
|
3
|
+
Extends functionality of ActiveRecord's transaction to auto-retry failed SQL transaction in case of deadlock, serialization error or unique constraint error. It also allows you to define `on_complete` callback that is being executed after SQL transaction is finished(either COMMIT-ed or ROLLBACK-ed). The implementation is not bound to any database, but relies on the rails connection adapters instead. Thus, if your database is supported by rails out of the box, then the gem's features will just work. Currently supported adapters:
|
4
4
|
|
5
|
-
|
5
|
+
- `postgresql`
|
6
|
+
- `mysql2`
|
7
|
+
- `sqlite3`
|
8
|
+
- `trilogy`
|
6
9
|
|
7
10
|
**WARNING!**
|
8
11
|
|
9
|
-
Because the implementation of this gem
|
12
|
+
Because the implementation of this gem patches ActiveRecord - carefully test its integration into your project. For example, if your application patches ActiveRecord or if some of your gems patches ActiveRecord - there might be conflicts in the implementation which could potentially lead to the data loss.
|
10
13
|
|
11
|
-
Currently, the implementation is tested for rails v6
|
14
|
+
Currently, the implementation is tested for rails v7.1+. **If you need the support of rails v6.0, v6.1, v7.0 - please use v1.x of this gem, but it works with PostgreSQL only.**
|
12
15
|
|
13
16
|
## Requirements
|
14
17
|
|
15
|
-
- ActiveRecord
|
18
|
+
- ActiveRecord 7.1+
|
16
19
|
- Ruby 3
|
17
|
-
- PostgreSQL 9.1+
|
18
20
|
|
19
21
|
## Installation
|
20
22
|
|
@@ -36,7 +38,6 @@ Or install it yourself as:
|
|
36
38
|
|
37
39
|
```ruby
|
38
40
|
require 'trx_ext'
|
39
|
-
require 'active_record'
|
40
41
|
|
41
42
|
# Object#trx is a shorthand of ActiveRecord::Base.transaction
|
42
43
|
trx do
|
@@ -66,6 +67,27 @@ class DummyRecord
|
|
66
67
|
end
|
67
68
|
```
|
68
69
|
|
70
|
+
If you are using non-primary connection for your model - you have to explicitly call `trx` method over that class:
|
71
|
+
|
72
|
+
```ruby
|
73
|
+
DummyRecord.trx do
|
74
|
+
DummyRecord.first || DummyRecord.create
|
75
|
+
end
|
76
|
+
```
|
77
|
+
In general, you should know about this if you are using multi-databases configuration.
|
78
|
+
|
79
|
+
If you want to wrap some method into a transaction using `wrap_in_trx` outside the ActiveRecord model context, you can pass a model name as a second argument explicitly:
|
80
|
+
|
81
|
+
```ruby
|
82
|
+
class MyAwesomeLib
|
83
|
+
# Wrap method in transaction
|
84
|
+
def some_method_with_quieries
|
85
|
+
DummyRecord.first || DummyRecord.create
|
86
|
+
end
|
87
|
+
wrap_in_trx :some_method_with_quieries, 'DummyRecord'
|
88
|
+
end
|
89
|
+
```
|
90
|
+
|
69
91
|
## Configuration
|
70
92
|
|
71
93
|
```ruby
|
@@ -77,15 +99,11 @@ end
|
|
77
99
|
|
78
100
|
## How it works?
|
79
101
|
|
80
|
-
|
102
|
+
When an ActiveRecord SQL query fails due to deadlock error, serialization error or unique constraint error - it is automatically retried. In case of ActiveRecord transaction - the block of code the AR transaction belongs to is re-executed, thus the transaction query is retried.
|
81
103
|
|
82
104
|
## Rules you have to stick when using this gem
|
83
105
|
|
84
|
-
|
85
|
-
>
|
86
|
-
> — [PostgreSQL documentation]
|
87
|
-
|
88
|
-
Since `ActiveRecord::ConnectionAdapters::PostgreSQLAdapter` is now patched with `TrxExt::Retry.with_retry_until_serialized`, there's no need to wrap every AR query in a `trx` block to ensure integrity. Wrap code in an explicit `trx` block if and only if it can or does produce two or more SQL queries *and* it is important to run those queries together atomically.
|
106
|
+
**Don't put into a single transaction more than needed for integrity purposes.**
|
89
107
|
|
90
108
|
There is "On complete" feature that allows you to define callbacks(blocks of code) that will be executed after transaction is complete. See `On complete callbacks` section bellow for the docs. See `On complete callbacks integrity` section bellow to be aware about different situations with them.
|
91
109
|
|
@@ -583,8 +601,14 @@ end
|
|
583
601
|
|
584
602
|
### Setup
|
585
603
|
|
586
|
-
|
587
|
-
|
604
|
+
- After checking out the repo, run `bundle install` to install dependencies.
|
605
|
+
- Run docker-compose using `docker-compose up` command - it starts necessary services
|
606
|
+
- Run next command to create dev and test databases:
|
607
|
+
|
608
|
+
```shell
|
609
|
+
bundle exec rails db:create db:migrate
|
610
|
+
RAILS_ENV=test bundle exec rails db:migrate
|
611
|
+
```
|
588
612
|
|
589
613
|
Now you can run `bin/console` for an interactive prompt that will allow you to experiment.
|
590
614
|
|
data/bin/console
CHANGED
@@ -13,14 +13,5 @@ require "trx_ext"
|
|
13
13
|
# Pry.start
|
14
14
|
|
15
15
|
require "irb"
|
16
|
-
require "logger"
|
17
|
-
require 'active_record'
|
18
|
-
require_relative '../spec/support/config'
|
19
|
-
require_relative '../spec/support/dummy_record'
|
20
|
-
|
21
|
-
ActiveRecord::Base.logger = ActiveSupport::Logger.new(STDOUT)
|
22
|
-
TrxExt.logger = ActiveSupport::Logger.new(STDOUT)
|
23
|
-
|
24
|
-
DummyRecord.setup
|
25
16
|
|
26
17
|
IRB.start(__FILE__)
|
data/bin/rails
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
Dir.chdir(File.expand_path("../dummy_app", __dir__))
|
4
|
+
ENV['BUNDLE_GEMFILE'] = "#{__dir__}/Gemfile"
|
5
|
+
|
6
|
+
APP_PATH = File.expand_path("../dummy_app/config/application", __dir__)
|
7
|
+
require_relative "../dummy_app/config/boot"
|
8
|
+
|
9
|
+
require "rails/commands"
|
data/bin/test_all_ar_versions
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
# frozen_string_literal: true
|
4
4
|
|
5
|
-
%w[
|
5
|
+
%w[7.1].each do |ar_version|
|
6
6
|
`rm Gemfile.lock`
|
7
7
|
Process.waitpid(Kernel.spawn({ 'AR_VERSION' => ar_version }, "bundle install --quiet", close_others: true))
|
8
8
|
Process.waitpid(Kernel.spawn({ 'AR_VERSION' => ar_version }, "rspec", close_others: true))
|
data/docker/my.cnf
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
[mysqld]
|
2
|
+
# Log General
|
3
|
+
general_log = 1
|
4
|
+
general_log_file = /var/log/mysql_general.log
|
5
|
+
|
6
|
+
# Log Error
|
7
|
+
log_error = /var/log/mysql_error.log
|
8
|
+
|
9
|
+
# Log Slow
|
10
|
+
slow_query_log = 1
|
11
|
+
slow_query_log_file = /var/log/mysql_slow_query.log
|
12
|
+
long_query_time = 0 # 0 has the effect of logging all queries
|
13
|
+
log_queries_not_using_indexes = 1
|
data/docker/mysqld.sh
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
#!/usr/bin/env bash
|
2
|
+
set -euo pipefail
|
3
|
+
|
4
|
+
##
|
5
|
+
# This script exists to work-around the fact that
|
6
|
+
# mysql does not support logging to stdout
|
7
|
+
#
|
8
|
+
# This will tail the file logs configured in ./my.cnf
|
9
|
+
##
|
10
|
+
|
11
|
+
LOG_PATHS=(
|
12
|
+
'/var/log/mysql_general.log'
|
13
|
+
'/var/log/mysql_error.log'
|
14
|
+
'/var/log/mysql_slow_query.log'
|
15
|
+
)
|
16
|
+
for LOG_PATH in "${LOG_PATHS[@]}"; do
|
17
|
+
# https://serverfault.com/a/599209
|
18
|
+
( umask 0 && truncate -s0 "$LOG_PATH" )
|
19
|
+
tail --pid $$ -n0 -F "$LOG_PATH" &
|
20
|
+
done
|
21
|
+
|
22
|
+
docker-entrypoint.sh mysqld
|
data/docker-compose.yml
CHANGED
@@ -2,9 +2,21 @@ version: "3.5"
|
|
2
2
|
|
3
3
|
services:
|
4
4
|
postgres:
|
5
|
-
image:
|
6
|
-
|
5
|
+
image: postgres:16
|
6
|
+
command: ["postgres", "-c", "log_statement=all", "-c", "default_transaction_isolation=serializable"]
|
7
7
|
ports:
|
8
8
|
- 5532:5432
|
9
9
|
environment:
|
10
10
|
- POSTGRES_PASSWORD=postgres
|
11
|
+
mysql:
|
12
|
+
image: mysql:8.3
|
13
|
+
command:
|
14
|
+
- /usr/local/bin/mysqld.sh
|
15
|
+
volumes:
|
16
|
+
- ./docker/my.cnf:/etc/mysql/conf.d/my.cnf
|
17
|
+
- ./docker/mysqld.sh:/usr/local/bin/mysqld.sh
|
18
|
+
ports:
|
19
|
+
- 3406:3306
|
20
|
+
- 34060:33060
|
21
|
+
environment:
|
22
|
+
- MYSQL_ALLOW_EMPTY_PASSWORD=true
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# See https://help.github.com/articles/ignoring-files for more about ignoring files.
|
2
|
+
#
|
3
|
+
# If you find yourself ignoring temporary files generated by your text editor
|
4
|
+
# or operating system, you probably want to add a global ignore instead:
|
5
|
+
# git config --global core.excludesfile '~/.gitignore_global'
|
6
|
+
|
7
|
+
# Ignore bundler config.
|
8
|
+
/.bundle
|
9
|
+
|
10
|
+
# Ignore the default SQLite database.
|
11
|
+
/db/*.sqlite3
|
12
|
+
/db/*.sqlite3-*
|
13
|
+
|
14
|
+
# Ignore all logfiles and tempfiles.
|
15
|
+
/log/*
|
16
|
+
/tmp/*
|
17
|
+
!/log/.keep
|
18
|
+
!/tmp/.keep
|
19
|
+
|
20
|
+
# Ignore pidfiles, but keep the directory.
|
21
|
+
/tmp/pids/*
|
22
|
+
!/tmp/pids/
|
23
|
+
!/tmp/pids/.keep
|
24
|
+
|
25
|
+
# Ignore uploaded files in development.
|
26
|
+
/storage/*
|
27
|
+
!/storage/.keep
|
28
|
+
/tmp/storage/*
|
29
|
+
!/tmp/storage/
|
30
|
+
!/tmp/storage/.keep
|
31
|
+
|
32
|
+
# Ignore master key for decrypting credentials and more.
|
33
|
+
/config/master.key
|
34
|
+
Gemfile.lock
|
35
|
+
db/schema.rb
|
36
|
+
db/primary_sqlite_schema.rb
|
37
|
+
db/primary_mysql_schema.rb
|
38
|
+
db/primary_trilogy_schema.rb
|
data/dummy_app/README.md
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# README
|
2
|
+
|
3
|
+
This README would normally document whatever steps are necessary to get the
|
4
|
+
application up and running.
|
5
|
+
|
6
|
+
Things you may want to cover:
|
7
|
+
|
8
|
+
* Ruby version
|
9
|
+
|
10
|
+
* System dependencies
|
11
|
+
|
12
|
+
* Configuration
|
13
|
+
|
14
|
+
* Database creation
|
15
|
+
|
16
|
+
* Database initialization
|
17
|
+
|
18
|
+
* How to run the test suite
|
19
|
+
|
20
|
+
* Services (job queues, cache servers, search engines, etc.)
|
21
|
+
|
22
|
+
* Deployment instructions
|
23
|
+
|
24
|
+
* ...
|
data/dummy_app/Rakefile
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Dummy record. It is used to test transaction integration.
|
4
|
+
class DummyMysqlRecord < ApplicationMysqlRecord
|
5
|
+
class << self
|
6
|
+
def find_or_create_by(attributes, &block)
|
7
|
+
find_by(attributes) || create(attributes, &block)
|
8
|
+
end
|
9
|
+
wrap_in_trx :find_or_create_by
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Dummy record. It is used to test transaction integration.
|
4
|
+
class DummyPgRecord < ApplicationPgRecord
|
5
|
+
class << self
|
6
|
+
def find_or_create_by(attributes, &block)
|
7
|
+
find_by(attributes) || create(attributes, &block)
|
8
|
+
end
|
9
|
+
wrap_in_trx :find_or_create_by
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Dummy record. It is used to test transaction integration.
|
4
|
+
class DummySqliteRecord < ApplicationSqliteRecord
|
5
|
+
class << self
|
6
|
+
def find_or_create_by(attributes, &block)
|
7
|
+
find_by(attributes) || create(attributes, &block)
|
8
|
+
end
|
9
|
+
wrap_in_trx :find_or_create_by
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Dummy record. It is used to test transaction integration.
|
4
|
+
class DummyTrilogyRecord < ApplicationTrilogyRecord
|
5
|
+
class << self
|
6
|
+
def find_or_create_by(attributes, &block)
|
7
|
+
find_by(attributes) || create(attributes, &block)
|
8
|
+
end
|
9
|
+
wrap_in_trx :find_or_create_by
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'bundle' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
require "rubygems"
|
12
|
+
|
13
|
+
m = Module.new do
|
14
|
+
module_function
|
15
|
+
|
16
|
+
def invoked_as_script?
|
17
|
+
File.expand_path($0) == File.expand_path(__FILE__)
|
18
|
+
end
|
19
|
+
|
20
|
+
def env_var_version
|
21
|
+
ENV["BUNDLER_VERSION"]
|
22
|
+
end
|
23
|
+
|
24
|
+
def cli_arg_version
|
25
|
+
return unless invoked_as_script? # don't want to hijack other binstubs
|
26
|
+
return unless "update".start_with?(ARGV.first || " ") # must be running `bundle update`
|
27
|
+
bundler_version = nil
|
28
|
+
update_index = nil
|
29
|
+
ARGV.each_with_index do |a, i|
|
30
|
+
if update_index && update_index.succ == i && a =~ Gem::Version::ANCHORED_VERSION_PATTERN
|
31
|
+
bundler_version = a
|
32
|
+
end
|
33
|
+
next unless a =~ /\A--bundler(?:[= ](#{Gem::Version::VERSION_PATTERN}))?\z/
|
34
|
+
bundler_version = $1
|
35
|
+
update_index = i
|
36
|
+
end
|
37
|
+
bundler_version
|
38
|
+
end
|
39
|
+
|
40
|
+
def gemfile
|
41
|
+
gemfile = ENV["BUNDLE_GEMFILE"]
|
42
|
+
return gemfile if gemfile && !gemfile.empty?
|
43
|
+
|
44
|
+
File.expand_path("../Gemfile", __dir__)
|
45
|
+
end
|
46
|
+
|
47
|
+
def lockfile
|
48
|
+
lockfile =
|
49
|
+
case File.basename(gemfile)
|
50
|
+
when "gems.rb" then gemfile.sub(/\.rb$/, ".locked")
|
51
|
+
else "#{gemfile}.lock"
|
52
|
+
end
|
53
|
+
File.expand_path(lockfile)
|
54
|
+
end
|
55
|
+
|
56
|
+
def lockfile_version
|
57
|
+
return unless File.file?(lockfile)
|
58
|
+
lockfile_contents = File.read(lockfile)
|
59
|
+
return unless lockfile_contents =~ /\n\nBUNDLED WITH\n\s{2,}(#{Gem::Version::VERSION_PATTERN})\n/
|
60
|
+
Regexp.last_match(1)
|
61
|
+
end
|
62
|
+
|
63
|
+
def bundler_requirement
|
64
|
+
@bundler_requirement ||=
|
65
|
+
env_var_version ||
|
66
|
+
cli_arg_version ||
|
67
|
+
bundler_requirement_for(lockfile_version)
|
68
|
+
end
|
69
|
+
|
70
|
+
def bundler_requirement_for(version)
|
71
|
+
return "#{Gem::Requirement.default}.a" unless version
|
72
|
+
|
73
|
+
bundler_gem_version = Gem::Version.new(version)
|
74
|
+
|
75
|
+
bundler_gem_version.approximate_recommendation
|
76
|
+
end
|
77
|
+
|
78
|
+
def load_bundler!
|
79
|
+
ENV["BUNDLE_GEMFILE"] ||= gemfile
|
80
|
+
|
81
|
+
activate_bundler
|
82
|
+
end
|
83
|
+
|
84
|
+
def activate_bundler
|
85
|
+
gem_error = activation_error_handling do
|
86
|
+
gem "bundler", bundler_requirement
|
87
|
+
end
|
88
|
+
return if gem_error.nil?
|
89
|
+
require_error = activation_error_handling do
|
90
|
+
require "bundler/version"
|
91
|
+
end
|
92
|
+
return if require_error.nil? && Gem::Requirement.new(bundler_requirement).satisfied_by?(Gem::Version.new(Bundler::VERSION))
|
93
|
+
warn "Activating bundler (#{bundler_requirement}) failed:\n#{gem_error.message}\n\nTo install the version of bundler this project requires, run `gem install bundler -v '#{bundler_requirement}'`"
|
94
|
+
exit 42
|
95
|
+
end
|
96
|
+
|
97
|
+
def activation_error_handling
|
98
|
+
yield
|
99
|
+
nil
|
100
|
+
rescue StandardError, LoadError => e
|
101
|
+
e
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
m.load_bundler!
|
106
|
+
|
107
|
+
if m.invoked_as_script?
|
108
|
+
load Gem.bin_path("bundler", "bundle")
|
109
|
+
end
|
data/dummy_app/bin/rails
ADDED
data/dummy_app/bin/rake
ADDED
data/dummy_app/bin/setup
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require "fileutils"
|
3
|
+
|
4
|
+
# path to your application root.
|
5
|
+
APP_ROOT = File.expand_path("..", __dir__)
|
6
|
+
|
7
|
+
def system!(*args)
|
8
|
+
system(*args) || abort("\n== Command #{args} failed ==")
|
9
|
+
end
|
10
|
+
|
11
|
+
FileUtils.chdir APP_ROOT do
|
12
|
+
# This script is a way to set up or update your development environment automatically.
|
13
|
+
# This script is idempotent, so that you can run it at any time and get an expectable outcome.
|
14
|
+
# Add necessary setup steps to this file.
|
15
|
+
|
16
|
+
puts "== Installing dependencies =="
|
17
|
+
system! "gem install bundler --conservative"
|
18
|
+
system("bundle check") || system!("bundle install")
|
19
|
+
|
20
|
+
# puts "\n== Copying sample files =="
|
21
|
+
# unless File.exist?("config/database.yml")
|
22
|
+
# FileUtils.cp "config/database.yml.sample", "config/database.yml"
|
23
|
+
# end
|
24
|
+
|
25
|
+
puts "\n== Preparing database =="
|
26
|
+
system! "bin/rails db:prepare"
|
27
|
+
|
28
|
+
puts "\n== Removing old logs and tempfiles =="
|
29
|
+
system! "bin/rails log:clear tmp:clear"
|
30
|
+
|
31
|
+
puts "\n== Restarting application server =="
|
32
|
+
system! "bin/rails restart"
|
33
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "boot"
|
4
|
+
|
5
|
+
require "rails"
|
6
|
+
|
7
|
+
%w(
|
8
|
+
active_record/railtie
|
9
|
+
action_controller/railtie
|
10
|
+
action_view/railtie
|
11
|
+
).each do |railtie|
|
12
|
+
begin
|
13
|
+
require railtie
|
14
|
+
rescue LoadError
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
# Require the gems listed in Gemfile, including any gems
|
20
|
+
# you've limited to :test, :development, or :production.
|
21
|
+
Bundler.require(*Rails.groups)
|
22
|
+
|
23
|
+
module DummyApp
|
24
|
+
class Application < Rails::Application
|
25
|
+
rails_version = Gem::Specification.find_by_name('rails').version
|
26
|
+
# Initialize configuration defaults for originally generated Rails version.
|
27
|
+
config.load_defaults rails_version.segments[0..1].join('.')
|
28
|
+
|
29
|
+
# Configuration for the application, engines, and railties goes here.
|
30
|
+
#
|
31
|
+
# These settings can be overridden in specific environments using the files
|
32
|
+
# in config/environments, which are processed later.
|
33
|
+
#
|
34
|
+
# config.time_zone = "Central Time (US & Canada)"
|
35
|
+
# config.eager_load_paths << Rails.root.join("extras")
|
36
|
+
|
37
|
+
# Only loads a smaller set of middleware suitable for API only apps.
|
38
|
+
# Middleware like session, flash, cookies can be added back manually.
|
39
|
+
# Skip views, helpers and assets when generating a new resource.
|
40
|
+
config.api_only = true
|
41
|
+
if rails_version < Gem::Version.new('7.0.0')
|
42
|
+
config.active_record.legacy_connection_handling = false
|
43
|
+
end
|
44
|
+
# config.active_job.queue_adapter = :async
|
45
|
+
|
46
|
+
|
47
|
+
if defined?(FactoryBotRails)
|
48
|
+
config.factory_bot.definition_file_paths += [File.expand_path('../../spec/factories', __dir__)]
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|