trx_ext 1.0.5 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +1 -1
  3. data/.ruby-version +1 -1
  4. data/CHANGELOG.md +10 -2
  5. data/Gemfile +24 -3
  6. data/README.md +40 -29
  7. data/bin/console +0 -12
  8. data/bin/rails +9 -0
  9. data/bin/test_all_ar_versions +1 -3
  10. data/docker/my.cnf +13 -0
  11. data/docker/mysqld.sh +22 -0
  12. data/docker-compose.yml +22 -0
  13. data/dummy_app/.gitattributes +7 -0
  14. data/dummy_app/.gitignore +38 -0
  15. data/dummy_app/README.md +24 -0
  16. data/dummy_app/Rakefile +6 -0
  17. data/dummy_app/app/controllers/application_controller.rb +2 -0
  18. data/dummy_app/app/models/application_mysql_record.rb +7 -0
  19. data/dummy_app/app/models/application_pg_record.rb +7 -0
  20. data/dummy_app/app/models/application_sqlite_record.rb +7 -0
  21. data/dummy_app/app/models/application_trilogy_record.rb +7 -0
  22. data/dummy_app/app/models/dummy_mysql_record.rb +11 -0
  23. data/dummy_app/app/models/dummy_pg_record.rb +11 -0
  24. data/dummy_app/app/models/dummy_sqlite_record.rb +11 -0
  25. data/dummy_app/app/models/dummy_trilogy_record.rb +11 -0
  26. data/dummy_app/bin/bundle +109 -0
  27. data/dummy_app/bin/rails +4 -0
  28. data/dummy_app/bin/rake +4 -0
  29. data/dummy_app/bin/setup +33 -0
  30. data/dummy_app/config/application.rb +51 -0
  31. data/dummy_app/config/boot.rb +4 -0
  32. data/dummy_app/config/credentials.yml +0 -0
  33. data/dummy_app/config/database.yml +70 -0
  34. data/dummy_app/config/environment.rb +5 -0
  35. data/dummy_app/config/environments/development.rb +66 -0
  36. data/dummy_app/config/environments/test.rb +61 -0
  37. data/dummy_app/config/initializers/.keep +0 -0
  38. data/dummy_app/config/locales/en.yml +2 -0
  39. data/dummy_app/config/locales/fr-CH.yml +2 -0
  40. data/dummy_app/config/puma.rb +43 -0
  41. data/dummy_app/config/routes.rb +5 -0
  42. data/dummy_app/config.ru +6 -0
  43. data/dummy_app/db/migrate/.keep +0 -0
  44. data/dummy_app/db/migrate/20240128111549_create_dummy_record.rb +10 -0
  45. data/dummy_app/db/primary_mysql/20240128111549_create_dummy_mysql_record.rb +10 -0
  46. data/dummy_app/db/primary_sqlite/20240128111549_create_dummy_sqlite_record.rb +10 -0
  47. data/dummy_app/db/primary_trilogy/20240128111549_create_dummy_trilogy_record.rb +10 -0
  48. data/dummy_app/db/seeds.rb +7 -0
  49. data/dummy_app/lib/tasks/.keep +0 -0
  50. data/dummy_app/log/.keep +0 -0
  51. data/dummy_app/public/robots.txt +1 -0
  52. data/dummy_app/storage/.keep +0 -0
  53. data/dummy_app/tmp/.keep +0 -0
  54. data/dummy_app/vendor/.keep +0 -0
  55. data/lib/trx_ext/object_ext.rb +12 -7
  56. data/lib/trx_ext/retry.rb +17 -27
  57. data/lib/trx_ext/transaction.rb +1 -1
  58. data/lib/trx_ext/version.rb +1 -2
  59. data/lib/trx_ext.rb +18 -21
  60. data/trx_ext.gemspec +1 -7
  61. metadata +53 -93
  62. data/bin/setup +0 -8
  63. data/lib/trx_ext/railtie.rb +0 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 489053db9c987c891db8ef10bc7ce8d513c49193c99b543a5d9610dc80cfe18b
4
- data.tar.gz: a964c8bbf189217897b61237ac6be0fb8c35ba669efae9b65a24f7a5323a7789
3
+ metadata.gz: d86c6295c4d141b3bcf938c95e8856cf390d5bd1a0454f81dfde3a135c35b9ff
4
+ data.tar.gz: d47c2e2425bf29d242824da94551acd8f44cb4489c811935ef5bd16169892544
5
5
  SHA512:
6
- metadata.gz: b09b5eb4644c73a3717d27808b6d9fc7c570b9447a0cfb038952ed862ee240ff880d3650e9688482ea9084c28d429b86663a3e39f55950a179c9b870b33cec00
7
- data.tar.gz: 74bcdd9e164756cfcdf97132a32d3c08d0cc19785261e4ae827a7f73732db504171494eb52bdea994848aaffa6b25675ba7a7395f76297ae9718e06f0b27cb24
6
+ metadata.gz: 1dd474ef6d21fe8443b14b7d3d12a3af00c030d14ff45924cf5130495cd12e5e37b8890d6af9303100e7acf269564fce405b9f00848661079c4e2627735ccfe7
7
+ data.tar.gz: 98ea0710b3c50b96741511c50ce627b06e8d8a7e8701c53935db1696c7aec2e61db9474bfa4239f11aa15e2243a7754a7de1590d3e2a157a885d8e6f9b4d1d93
data/.rspec CHANGED
@@ -1,3 +1,3 @@
1
1
  --format Fivemat
2
- --require spec_helper
2
+ --require rails_helper
3
3
  --require fivemat
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 3.2.2
1
+ 3.3.0
data/CHANGELOG.md CHANGED
@@ -1,8 +1,16 @@
1
1
  ## [Unreleased]
2
2
 
3
- Nothing new yet
3
+ ## [2.0.0] - 2024-04-14
4
4
 
5
- ## [1.0.5] - 2022-01-27
5
+ - `trx_ext` now supports any adapter(except `mysql`; `mysql2` is supported though), supported by rails
6
+ - **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
7
+ - Support multiple databases configurations
8
+
9
+ ## [1.0.6] - 2023-08-25
10
+
11
+ - Refactoring the retry implementation
12
+
13
+ ## [1.0.5] - 2023-05-11
6
14
 
7
15
  - Load `Object` extension earlier
8
16
 
data/Gemfile CHANGED
@@ -5,8 +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
- gem 'activerecord', ENV['AR_VERSION']
9
+ # Given ENV['AR_VERSION'] to equal "6.0" will produce
10
+ # ```ruby
11
+ # gem 'activerecord', "~> 6.0", "< 6.1"
12
+ # ```
13
+ gem 'rails', "~> #{ENV['AR_VERSION']}", "< #{ENV['AR_VERSION'].next}"
14
+ else
15
+ gem 'rails'
12
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
- Currently, the implementation only works for ActiveRecord PostgreSQL adapter. Feel free to improve it.
5
+ - `postgresql`
6
+ - `mysql2`
7
+ - `sqlite3`
8
+ - `trilogy`
6
9
 
7
10
  **WARNING!**
8
11
 
9
- Because the implementation of this gem is a patch for `ActiveRecord::ConnectionAdapters::PostgreSQLAdapter` - carefully test its integration into your project. For example, if your project 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.
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 `6.0.4.4`, `6.1.4.4` and `7.0.1` versions of ActiveRecord(see [TrxExt::SUPPORTED_AR_VERSIONS](lib/trx_ext/version.rb))
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 6+
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
- Your either every single AR SQL query or whole AR transaction is retried whenever it throws deadlock error, serialization error or unique constraint error. In case of AR transaction - the block of code that the AR transaction belongs to is re-executed, thus the transaction is retried.
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
- > "Don't put more into a single transaction than needed for integrity purposes."
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,23 +601,20 @@ end
583
601
 
584
602
  ### Setup
585
603
 
586
- - After checking out the repo, run `bin/setup` to install dependencies.
587
- - Setup postgresql server with `serializable` transaction isolation level - you have to set `default_transaction_isolation` config option to `serializable` in your `postgresql.conf` file
588
- - Create pg user and a database. This database will be used to run tests. When running console, this database will be used as a default database to connect to. Example:
589
- ```shell
590
- sudo -u postgres createuser postgres --superuser
591
- sudo -u postgres psql --command="CREATE DATABASE trx_ext_db OWNER postgres"
592
- ```
593
- - Setup db connection settings. Copy config sample and edit it to match your created pg user and database:
594
- ```shell
595
- cp spec/support/config/database.yml.sample spec/support/config/database.yml
596
- ```
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
+ ```
597
612
 
598
613
  Now you can run `bin/console` for an interactive prompt that will allow you to experiment.
599
614
 
600
615
  ### Tests
601
616
 
602
- You can run tests for currently installed AR using `rspec` command. There is `bin/test_all_ar_versions` executable that allows you to run tests within all supported AR versions(see [TrxExt::SUPPORTED_AR_VERSIONS](lib/trx_ext/version.rb)) as well.
617
+ You can run tests for currently installed AR using `rspec` command. There is `bin/test_all_ar_versions` executable that allows you to run tests within all supported AR versions.
603
618
 
604
619
  ### Other
605
620
 
@@ -616,7 +631,3 @@ The gem is available as open source under the terms of the [MIT License](https:/
616
631
  ## Code of Conduct
617
632
 
618
633
  Everyone interacting in the TrxExt project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/intale/trx_ext/blob/master/CODE_OF_CONDUCT.md).
619
-
620
- ## TODO
621
-
622
- - integrate GitHub Actions
data/bin/console CHANGED
@@ -13,17 +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
- if Config.db_config
25
- ActiveRecord::Base.establish_connection(Config.db_config)
26
- DummyRecord.setup
27
- end
28
16
 
29
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"
@@ -2,9 +2,7 @@
2
2
 
3
3
  # frozen_string_literal: true
4
4
 
5
- require_relative '../lib/trx_ext/version'
6
-
7
- TrxExt::SUPPORTED_AR_VERSIONS.each do |ar_version|
5
+ %w[7.1].each do |ar_version|
8
6
  `rm Gemfile.lock`
9
7
  Process.waitpid(Kernel.spawn({ 'AR_VERSION' => ar_version }, "bundle install --quiet", close_others: true))
10
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
@@ -0,0 +1,22 @@
1
+ version: "3.5"
2
+
3
+ services:
4
+ postgres:
5
+ image: postgres:16
6
+ command: ["postgres", "-c", "log_statement=all", "-c", "default_transaction_isolation=serializable"]
7
+ ports:
8
+ - 5532:5432
9
+ environment:
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,7 @@
1
+ # See https://git-scm.com/docs/gitattributes for more about git attribute files.
2
+
3
+ # Mark the database schema as having been generated.
4
+ db/schema.rb linguist-generated
5
+
6
+ # Mark any vendored files as having been vendored.
7
+ vendor/* linguist-vendored
@@ -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
@@ -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
+ * ...
@@ -0,0 +1,6 @@
1
+ # Add your own tasks in files placed in lib/tasks ending in .rake,
2
+ # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
3
+
4
+ require_relative "config/application"
5
+
6
+ Rails.application.load_tasks
@@ -0,0 +1,2 @@
1
+ class ApplicationController < ActionController::API
2
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ApplicationMysqlRecord < ActiveRecord::Base
4
+ self.abstract_class = true
5
+
6
+ connects_to database: { writing: :primary_mysql, reading: :primary_mysql }
7
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ApplicationPgRecord < ActiveRecord::Base
4
+ self.abstract_class = true
5
+
6
+ connects_to database: { writing: :primary_pg, reading: :primary_pg }
7
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ApplicationSqliteRecord < ActiveRecord::Base
4
+ self.abstract_class = true
5
+
6
+ connects_to database: { writing: :primary_sqlite, reading: :primary_sqlite }
7
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ApplicationTrilogyRecord < ActiveRecord::Base
4
+ self.abstract_class = true
5
+
6
+ connects_to database: { writing: :primary_trilogy, reading: :primary_trilogy }
7
+ end
@@ -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
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ APP_PATH = File.expand_path("../config/application", __dir__)
3
+ require_relative "../config/boot"
4
+ require "rails/commands"
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ require_relative "../config/boot"
3
+ require "rake"
4
+ Rake.application.run
@@ -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