ros-apartment 2.7.2 → 2.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.circleci/config.yml +78 -0
- data/.github/workflows/changelog.yml +26 -4
- data/.rubocop.yml +5 -0
- data/Appraisals +15 -3
- data/CHANGELOG.md +50 -4
- data/README.md +27 -0
- data/Rakefile +3 -2
- data/gemfiles/rails_6_1.gemfile +23 -0
- data/lib/apartment.rb +17 -2
- data/lib/apartment/adapters/abstract_adapter.rb +2 -0
- data/lib/apartment/adapters/postgresql_adapter.rb +17 -1
- data/lib/apartment/console.rb +3 -1
- data/lib/apartment/log_subscriber.rb +33 -0
- data/lib/apartment/railtie.rb +26 -21
- data/lib/apartment/tasks/task_helper.rb +19 -0
- data/lib/apartment/tenant.rb +4 -19
- data/lib/apartment/version.rb +1 -1
- data/lib/tasks/apartment.rake +4 -13
- data/ros-apartment.gemspec +2 -2
- metadata +7 -6
- data/.travis.yml +0 -49
- data/lib/apartment/active_record/log_subscriber.rb +0 -44
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f31fef7b2332c76bce3bff4823754c145b7a049bbf845ce29bb22b65b29585e4
|
4
|
+
data.tar.gz: 657b9a8bf128f912894e03bd2331b2e2201bf9f43f38515117e434ef65694341
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d35580a7ed02ea8423251e0e7ed555d002fe34f4d2705cb16b982e5211a5f79fd8f078b97c7ac633f8b1bb605c9ada8176a6c082c0d1ad00591ba4b079acb7b4
|
7
|
+
data.tar.gz: fa77558d5731e0a99c8ff1f8611c5353e633a5bbcd37fe94c64fe310414f8f724177d6fa7121ca88031315638990087546892a7411fd7477e37362de52682e31
|
@@ -0,0 +1,78 @@
|
|
1
|
+
version: 2.1
|
2
|
+
|
3
|
+
orbs:
|
4
|
+
rubocop: hanachin/rubocop@0.0.6
|
5
|
+
|
6
|
+
jobs:
|
7
|
+
build:
|
8
|
+
docker:
|
9
|
+
- image: circleci/<< parameters.ruby_version >>
|
10
|
+
- image: circleci/postgres:9.6.2-alpine
|
11
|
+
- image: circleci/mysql:5.7
|
12
|
+
environment:
|
13
|
+
MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
|
14
|
+
parameters:
|
15
|
+
ruby_version:
|
16
|
+
type: string
|
17
|
+
gemfile:
|
18
|
+
type: string
|
19
|
+
environment:
|
20
|
+
BUNDLE_GEMFILE: << parameters.gemfile >>
|
21
|
+
steps:
|
22
|
+
- checkout
|
23
|
+
# Restore Cached Dependencies
|
24
|
+
# - restore_cache:
|
25
|
+
# keys:
|
26
|
+
# - gem-cache-v1-{{ arch }}-{{ .Branch }}-{{ checksum "<< parameters.gemfile >>.lock" }}
|
27
|
+
# - gem-cache-v1-{{ arch }}-{{ .Branch }}
|
28
|
+
# - gem-cache-v1
|
29
|
+
|
30
|
+
- run: bundle install --path vendor/bundle
|
31
|
+
|
32
|
+
# - save_cache:
|
33
|
+
# key: gem-cache-v1-{{ arch }}-{{ .Branch }}-{{ checksum "<< parameters.gemfile >>.lock" }}
|
34
|
+
# paths:
|
35
|
+
# - vendor/bundle
|
36
|
+
|
37
|
+
- run:
|
38
|
+
name: Install postgres client
|
39
|
+
command: sudo apt install -y postgresql-client
|
40
|
+
|
41
|
+
- run:
|
42
|
+
name: Install mysql client
|
43
|
+
command: sudo apt install -y default-mysql-client
|
44
|
+
|
45
|
+
- run:
|
46
|
+
name: Configure config database.yml
|
47
|
+
command: bundle exec rake db:copy_credentials
|
48
|
+
|
49
|
+
- run:
|
50
|
+
name: wait for postgresql
|
51
|
+
command: dockerize -wait tcp://localhost:5432 -timeout 1m
|
52
|
+
|
53
|
+
- run:
|
54
|
+
name: wait for mysql
|
55
|
+
command: dockerize -wait tcp://localhost:3306 -timeout 1m
|
56
|
+
|
57
|
+
- run:
|
58
|
+
name: Database Setup
|
59
|
+
command: |
|
60
|
+
bundle exec rake db:test:prepare
|
61
|
+
|
62
|
+
- run:
|
63
|
+
name: Run tests
|
64
|
+
command: bundle exec rspec
|
65
|
+
|
66
|
+
workflows:
|
67
|
+
tests:
|
68
|
+
jobs:
|
69
|
+
- build:
|
70
|
+
matrix:
|
71
|
+
parameters:
|
72
|
+
ruby_version: ["ruby:2.6-buster", "ruby:2.7-buster"]
|
73
|
+
gemfile: ["gemfiles/rails_5_2.gemfile", "gemfiles/rails_6_0.gemfile", "gemfiles/rails_6_1.gemfile"]
|
74
|
+
|
75
|
+
rubocop:
|
76
|
+
jobs:
|
77
|
+
- rubocop/rubocop:
|
78
|
+
version: 0.88.0
|
@@ -35,7 +35,29 @@ jobs:
|
|
35
35
|
|
36
36
|
- name: Push changes
|
37
37
|
if: env.push == 1
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
38
|
+
env:
|
39
|
+
# CI_USER: ${{ secrets.YOUR_GITHUB_USER }}
|
40
|
+
CI_TOKEN: ${{ secrets.CHANGELOG_GITHUB_TOKEN }}
|
41
|
+
run: |
|
42
|
+
git push "https://$GITHUB_ACTOR:$CI_TOKEN@github.com/$GITHUB_REPOSITORY.git" HEAD:master
|
43
|
+
|
44
|
+
# - name: Push changelog to master
|
45
|
+
# if: env.push == 1
|
46
|
+
# uses: ad-m/github-push-action@master
|
47
|
+
# with:
|
48
|
+
# github_token: ${{ secrets.CHANGELOG_GITHUB_TOKEN }}
|
49
|
+
# branch: master
|
50
|
+
|
51
|
+
# - name: Cherry-pick changelog to development
|
52
|
+
# if: env.push == 1
|
53
|
+
# env:
|
54
|
+
# ACTION_EMAIL: action@github.com
|
55
|
+
# ACTION_USERNAME: GitHub Action
|
56
|
+
# run: |
|
57
|
+
# git config --local user.email "$ACTION_EMAIL"
|
58
|
+
# git config --local user.name "$ACTION_USERNAME"
|
59
|
+
# commit_hash=`git show HEAD | egrep commit\ .+$ | cut -d' ' -f2`
|
60
|
+
# git checkout development
|
61
|
+
# git pull
|
62
|
+
# git cherry-pick $commit_hash
|
63
|
+
# git push
|
data/.rubocop.yml
CHANGED
data/Appraisals
CHANGED
@@ -45,14 +45,26 @@ appraise 'rails-6-0' do
|
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
48
|
+
appraise 'rails-6-1' do
|
49
|
+
gem 'rails', '~> 6.1.0'
|
50
|
+
platforms :ruby do
|
51
|
+
gem 'sqlite3', '~> 1.4'
|
52
|
+
end
|
53
|
+
platforms :jruby do
|
54
|
+
gem 'activerecord-jdbc-adapter', '~> 61.0'
|
55
|
+
gem 'activerecord-jdbcpostgresql-adapter', '~> 61.0'
|
56
|
+
gem 'activerecord-jdbcmysql-adapter', '~> 61.0'
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
48
60
|
appraise 'rails-master' do
|
49
61
|
gem 'rails', git: 'https://github.com/rails/rails.git'
|
50
62
|
platforms :ruby do
|
51
63
|
gem 'sqlite3', '~> 1.4'
|
52
64
|
end
|
53
65
|
platforms :jruby do
|
54
|
-
gem 'activerecord-jdbc-adapter', '~>
|
55
|
-
gem 'activerecord-jdbcpostgresql-adapter', '~>
|
56
|
-
gem 'activerecord-jdbcmysql-adapter', '~>
|
66
|
+
gem 'activerecord-jdbc-adapter', '~> 61.0'
|
67
|
+
gem 'activerecord-jdbcpostgresql-adapter', '~> 61.0'
|
68
|
+
gem 'activerecord-jdbcmysql-adapter', '~> 61.0'
|
57
69
|
end
|
58
70
|
end
|
data/CHANGELOG.md
CHANGED
@@ -2,7 +2,45 @@
|
|
2
2
|
|
3
3
|
## [Unreleased](https://github.com/rails-on-services/apartment/tree/HEAD)
|
4
4
|
|
5
|
-
[Full Changelog](https://github.com/rails-on-services/apartment/compare/v2.
|
5
|
+
[Full Changelog](https://github.com/rails-on-services/apartment/compare/v2.8.0...HEAD)
|
6
|
+
|
7
|
+
**Implemented enhancements:**
|
8
|
+
|
9
|
+
**Fixed bugs:**
|
10
|
+
|
11
|
+
- New version raises an error with ActiveSupport::LogSubscriber [#128](https://github.com/rails-on-services/apartment/issues/128)
|
12
|
+
- Weird logs when tenant fails to create [#127](<https://github.com/rails-on-services/apartment/issues/127>)
|
13
|
+
|
14
|
+
**Closed issues:**
|
15
|
+
|
16
|
+
## [v2.8.0](https://github.com/rails-on-services/apartment/tree/v2.8.0) (2020-12-16)
|
17
|
+
|
18
|
+
[Full Changelog](https://github.com/rails-on-services/apartment/compare/v2.7.2...v2.8.0)
|
19
|
+
|
20
|
+
**Implemented enhancements:**
|
21
|
+
|
22
|
+
- Uses a transaction to create a tenant [#66](https://github.com/rails-on-services/apartment/issues/66)
|
23
|
+
|
24
|
+
**Fixed bugs:**
|
25
|
+
|
26
|
+
- Fix seeding errors [#86](https://github.com/rails-on-services/apartment/issues/86)
|
27
|
+
- When tests run in a transaction, new tenants in tests fail to create [#123](https://github.com/rails-on-services/apartment/issues/123)
|
28
|
+
- Reverted unsafe initializer - introduces the possibility of disabling the initial connection to the database via
|
29
|
+
environment variable. Relates to the following tickets/PRs:
|
30
|
+
- [#113](https://github.com/rails-on-services/apartment/issues/113)
|
31
|
+
- [#39](https://github.com/rails-on-services/apartment/pull/39)
|
32
|
+
- [#53](https://github.com/rails-on-services/apartment/pull/53)
|
33
|
+
- [#118](https://github.com/rails-on-services/apartment/pull/118)
|
34
|
+
|
35
|
+
**Closed issues:**
|
36
|
+
|
37
|
+
- Improve changelog automatic generation [#98](https://github.com/rails-on-services/apartment/issues/98)
|
38
|
+
- Relaxes dependencies to allow rails 6.1 [#121](https://github.com/rails-on-services/apartment/issues/121)
|
39
|
+
|
40
|
+
|
41
|
+
## [v2.7.2](https://github.com/rails-on-services/apartment/tree/v2.7.2) (2020-07-17)
|
42
|
+
|
43
|
+
[Full Changelog](https://github.com/rails-on-services/apartment/compare/v2.7.1...v2.7.2)
|
6
44
|
|
7
45
|
**Implemented enhancements:**
|
8
46
|
|
@@ -19,13 +57,21 @@
|
|
19
57
|
- enhanced db:create task breaks plugins compatibility [\#82](https://github.com/rails-on-services/apartment/issues/82)
|
20
58
|
- Support disabling of full\_migration\_on\_create [\#30](https://github.com/rails-on-services/apartment/issues/30)
|
21
59
|
|
60
|
+
**Merged pull requests:**
|
61
|
+
|
62
|
+
- \[Chore\] Fix Changelog github action [\#97](https://github.com/rails-on-services/apartment/pull/97) ([rpbaltazar](https://github.com/rpbaltazar))
|
63
|
+
- Prepare release - 2.7.2 [\#96](https://github.com/rails-on-services/apartment/pull/96) ([rpbaltazar](https://github.com/rpbaltazar))
|
64
|
+
- \[Resolves \#92\] tenant switch raises exception on first call [\#95](https://github.com/rails-on-services/apartment/pull/95) ([rpbaltazar](https://github.com/rpbaltazar))
|
65
|
+
- Dont use custom rubocop [\#94](https://github.com/rails-on-services/apartment/pull/94) ([rpbaltazar](https://github.com/rpbaltazar))
|
66
|
+
- \[Resolves \#80\] added changelog action [\#90](https://github.com/rails-on-services/apartment/pull/90) ([rpbaltazar](https://github.com/rpbaltazar))
|
67
|
+
- \[Resolves \#81\] check for var existence before [\#89](https://github.com/rails-on-services/apartment/pull/89) ([rpbaltazar](https://github.com/rpbaltazar))
|
68
|
+
|
22
69
|
## [v2.7.1](https://github.com/rails-on-services/apartment/tree/v2.7.1) (2020-06-27)
|
23
70
|
|
24
71
|
[Full Changelog](https://github.com/rails-on-services/apartment/compare/v2.7.0...v2.7.1)
|
25
72
|
|
26
73
|
**Merged pull requests:**
|
27
74
|
|
28
|
-
- \[Resolves \#80\] added changelog action [\#90](https://github.com/rails-on-services/apartment/pull/90) ([rpbaltazar](https://github.com/rpbaltazar))
|
29
75
|
- Prepare Release 2.7.1 [\#84](https://github.com/rails-on-services/apartment/pull/84) ([rpbaltazar](https://github.com/rpbaltazar))
|
30
76
|
- \[Resolves \#82\] Enhanced db create task breaks plugins compatibility [\#83](https://github.com/rails-on-services/apartment/pull/83) ([rpbaltazar](https://github.com/rpbaltazar))
|
31
77
|
- \[ci\] update rake [\#79](https://github.com/rails-on-services/apartment/pull/79) ([ahorek](https://github.com/ahorek))
|
@@ -67,6 +113,7 @@
|
|
67
113
|
|
68
114
|
- db:rollback uses second latest migration for tenants [\#56](https://github.com/rails-on-services/apartment/issues/56)
|
69
115
|
- rake db:setup tries to seed non existing tenant [\#52](https://github.com/rails-on-services/apartment/issues/52)
|
116
|
+
- Custom Console deprecation warning [\#37](https://github.com/rails-on-services/apartment/issues/37)
|
70
117
|
|
71
118
|
**Merged pull requests:**
|
72
119
|
|
@@ -76,7 +123,6 @@
|
|
76
123
|
- \[\#52\] enhance after db create [\#54](https://github.com/rails-on-services/apartment/pull/54) ([rpbaltazar](https://github.com/rpbaltazar))
|
77
124
|
- fix init after reload on development [\#53](https://github.com/rails-on-services/apartment/pull/53) ([fsateler](https://github.com/fsateler))
|
78
125
|
- fix: reset sequence\_name after tenant switch [\#51](https://github.com/rails-on-services/apartment/pull/51) ([fsateler](https://github.com/fsateler))
|
79
|
-
- Add console welcome message [\#47](https://github.com/rails-on-services/apartment/pull/47) ([JeremiahChurch](https://github.com/JeremiahChurch))
|
80
126
|
- Avoid early connection [\#39](https://github.com/rails-on-services/apartment/pull/39) ([fsateler](https://github.com/fsateler))
|
81
127
|
|
82
128
|
## [v2.6.0](https://github.com/rails-on-services/apartment/tree/v2.6.0) (2020-05-14)
|
@@ -88,13 +134,13 @@
|
|
88
134
|
- Error Dropping Tenant [\#46](https://github.com/rails-on-services/apartment/issues/46)
|
89
135
|
- After switch callback not working with nil argument [\#42](https://github.com/rails-on-services/apartment/issues/42)
|
90
136
|
- Add tenant info to console boot? [\#41](https://github.com/rails-on-services/apartment/issues/41)
|
91
|
-
- Custom Console deprecation warning [\#37](https://github.com/rails-on-services/apartment/issues/37)
|
92
137
|
- Support configuration for skip checking of schema existence before switching [\#26](https://github.com/rails-on-services/apartment/issues/26)
|
93
138
|
|
94
139
|
**Merged pull requests:**
|
95
140
|
|
96
141
|
- \[Resolves \#37\] Custom console deprecation warning [\#49](https://github.com/rails-on-services/apartment/pull/49) ([rpbaltazar](https://github.com/rpbaltazar))
|
97
142
|
- Prepare Release 2.6.0 [\#48](https://github.com/rails-on-services/apartment/pull/48) ([rpbaltazar](https://github.com/rpbaltazar))
|
143
|
+
- Add console welcome message [\#47](https://github.com/rails-on-services/apartment/pull/47) ([JeremiahChurch](https://github.com/JeremiahChurch))
|
98
144
|
- \[Resolves \#26\] Support configuration for skip checking of schema existence before switching [\#45](https://github.com/rails-on-services/apartment/pull/45) ([rpbaltazar](https://github.com/rpbaltazar))
|
99
145
|
- \[Resolves \#42\] After switch callback not working with nil argument [\#43](https://github.com/rails-on-services/apartment/pull/43) ([rpbaltazar](https://github.com/rpbaltazar))
|
100
146
|
|
data/README.md
CHANGED
@@ -338,6 +338,23 @@ Apartment.configure do |config|
|
|
338
338
|
end
|
339
339
|
```
|
340
340
|
|
341
|
+
### Additional logging information
|
342
|
+
|
343
|
+
Enabling this configuration will output the database that the process is currently connected to as well as which
|
344
|
+
schemas are in the search path. This can be enabled by setting to true the `active_record_log` configuration.
|
345
|
+
|
346
|
+
Please note that our custom logger inherits from `ActiveRecord::LogSubscriber` so this will be required for the configuration to work.
|
347
|
+
|
348
|
+
**Example log output:**
|
349
|
+
|
350
|
+
<img src="documentation/images/log_example.png">
|
351
|
+
|
352
|
+
```ruby
|
353
|
+
Apartment.configure do |config|
|
354
|
+
config.active_record_log = true
|
355
|
+
end
|
356
|
+
```
|
357
|
+
|
341
358
|
### Excluding models
|
342
359
|
|
343
360
|
If you have some models that should always access the 'public' tenant, you can specify this by configuring Apartment using `Apartment.configure`. This will yield a config object for you. You can set excluded models like so:
|
@@ -594,6 +611,16 @@ module Apartment
|
|
594
611
|
end
|
595
612
|
```
|
596
613
|
|
614
|
+
## Running rails console without a connection to the database
|
615
|
+
|
616
|
+
By default, once apartment starts, it establishes a connection to the database. It is possible to
|
617
|
+
disable this initial connection, by running with `APARTMENT_DISABLE_INIT` set to something:
|
618
|
+
|
619
|
+
```shell
|
620
|
+
$ APARTMENT_DISABLE_INIT=true DATABASE_URL=postgresql://localhost:1234/buk_development bin/rails runner 'puts 1'
|
621
|
+
# 1
|
622
|
+
```
|
623
|
+
|
597
624
|
## Contributing
|
598
625
|
|
599
626
|
* In both `spec/dummy/config` and `spec/config`, you will see `database.yml.sample` files
|
data/Rakefile
CHANGED
@@ -47,9 +47,9 @@ namespace :db do
|
|
47
47
|
rails_db_file = 'spec/dummy/config/database.yml'
|
48
48
|
|
49
49
|
unless File.exist?(apartment_db_file)
|
50
|
-
FileUtils.copy(apartment_db_file
|
50
|
+
FileUtils.copy("#{apartment_db_file}.sample", apartment_db_file, verbose: true)
|
51
51
|
end
|
52
|
-
FileUtils.copy(rails_db_file
|
52
|
+
FileUtils.copy("#{rails_db_file}.sample", rails_db_file, verbose: true) unless File.exist?(rails_db_file)
|
53
53
|
end
|
54
54
|
end
|
55
55
|
|
@@ -65,6 +65,7 @@ namespace :postgres do
|
|
65
65
|
params << "-U#{pg_config['username']}"
|
66
66
|
params << "-h#{pg_config['host']}" if pg_config['host']
|
67
67
|
params << "-p#{pg_config['port']}" if pg_config['port']
|
68
|
+
|
68
69
|
begin
|
69
70
|
`createdb #{params.join(' ')}`
|
70
71
|
rescue StandardError
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# This file was generated by Appraisal
|
2
|
+
|
3
|
+
source "http://rubygems.org"
|
4
|
+
|
5
|
+
gem "rails", "~> 6.1.0"
|
6
|
+
gem "rubocop"
|
7
|
+
|
8
|
+
group :local do
|
9
|
+
gem "guard-rspec", "~> 4.2"
|
10
|
+
gem "pry"
|
11
|
+
end
|
12
|
+
|
13
|
+
platforms :ruby do
|
14
|
+
gem "sqlite3", "~> 1.4"
|
15
|
+
end
|
16
|
+
|
17
|
+
platforms :jruby do
|
18
|
+
gem "activerecord-jdbc-adapter", "~> 61.0"
|
19
|
+
gem "activerecord-jdbcpostgresql-adapter", "~> 61.0"
|
20
|
+
gem "activerecord-jdbcmysql-adapter", "~> 61.0"
|
21
|
+
end
|
22
|
+
|
23
|
+
gemspec path: "../"
|
data/lib/apartment.rb
CHANGED
@@ -6,7 +6,7 @@ require 'forwardable'
|
|
6
6
|
require 'active_record'
|
7
7
|
require 'apartment/tenant'
|
8
8
|
|
9
|
-
require_relative 'apartment/
|
9
|
+
require_relative 'apartment/log_subscriber'
|
10
10
|
|
11
11
|
if ActiveRecord.version.release >= Gem::Version.new('6.0')
|
12
12
|
require_relative 'apartment/active_record/connection_handling'
|
@@ -27,7 +27,7 @@ module Apartment
|
|
27
27
|
|
28
28
|
WRITER_METHODS = %i[tenant_names database_schema_file excluded_models
|
29
29
|
persistent_schemas connection_class
|
30
|
-
db_migrate_tenants seed_data_file
|
30
|
+
db_migrate_tenants db_migrate_tenant_missing_strategy seed_data_file
|
31
31
|
parallel_migration_threads pg_excluded_names].freeze
|
32
32
|
|
33
33
|
attr_accessor(*ACCESSOR_METHODS)
|
@@ -72,6 +72,21 @@ module Apartment
|
|
72
72
|
@db_migrate_tenants = true
|
73
73
|
end
|
74
74
|
|
75
|
+
# How to handle tenant missing on db:migrate
|
76
|
+
# defaults to :rescue_exception
|
77
|
+
# available options: rescue_exception, raise_exception, create_tenant
|
78
|
+
def db_migrate_tenant_missing_strategy
|
79
|
+
valid = %i[rescue_exception raise_exception create_tenant]
|
80
|
+
value = @db_migrate_tenant_missing_strategy || :rescue_exception
|
81
|
+
|
82
|
+
return value if valid.include?(value)
|
83
|
+
|
84
|
+
key_name = 'config.db_migrate_tenant_missing_strategy'
|
85
|
+
opt_names = valid.join(', ')
|
86
|
+
|
87
|
+
raise ApartmentError, "Option #{value} not valid for `#{key_name}`. Use one of #{opt_names}"
|
88
|
+
end
|
89
|
+
|
75
90
|
# Default to empty array
|
76
91
|
def excluded_models
|
77
92
|
@excluded_models || []
|
@@ -201,11 +201,13 @@ module Apartment
|
|
201
201
|
# @param {String} tenant: Database name
|
202
202
|
# @param {Boolean} with_database: if true, use the actual tenant's db name
|
203
203
|
# if false, use the default db name from the db
|
204
|
+
# rubocop:disable Style/OptionalBooleanParameter
|
204
205
|
def multi_tenantify(tenant, with_database = true)
|
205
206
|
db_connection_config(tenant).tap do |config|
|
206
207
|
multi_tenantify_with_tenant_db_name(config, tenant) if with_database
|
207
208
|
end
|
208
209
|
end
|
210
|
+
# rubocop:enable Style/OptionalBooleanParameter
|
209
211
|
|
210
212
|
def multi_tenantify_with_tenant_db_name(config, tenant)
|
211
213
|
config[:database] = environmentify(tenant)
|
@@ -97,7 +97,23 @@ module Apartment
|
|
97
97
|
end
|
98
98
|
|
99
99
|
def create_tenant_command(conn, tenant)
|
100
|
-
|
100
|
+
# NOTE: This was causing some tests to fail because of the database strategy for rspec
|
101
|
+
if ActiveRecord::Base.connection.open_transactions.positive?
|
102
|
+
conn.execute(%(CREATE SCHEMA "#{tenant}"))
|
103
|
+
else
|
104
|
+
schema = %(BEGIN;
|
105
|
+
CREATE SCHEMA "#{tenant}";
|
106
|
+
COMMIT;)
|
107
|
+
|
108
|
+
conn.execute(schema)
|
109
|
+
end
|
110
|
+
rescue *rescuable_exceptions => e
|
111
|
+
rollback_transaction(conn)
|
112
|
+
raise e
|
113
|
+
end
|
114
|
+
|
115
|
+
def rollback_transaction(conn)
|
116
|
+
conn.execute('ROLLBACK;')
|
101
117
|
end
|
102
118
|
|
103
119
|
# Generate the final search path to set including persistent_schemas
|
data/lib/apartment/console.rb
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# A
|
3
|
+
# A workaround to get `reload!` to also call Apartment::Tenant.init
|
4
4
|
# This is unfortunate, but I haven't figured out how to hook into the reload process *after* files are reloaded
|
5
5
|
|
6
6
|
# reloads the environment
|
7
|
+
# rubocop:disable Style/OptionalBooleanParameter
|
7
8
|
def reload!(print = true)
|
8
9
|
puts 'Reloading...' if print
|
9
10
|
|
@@ -13,6 +14,7 @@ def reload!(print = true)
|
|
13
14
|
Apartment::Tenant.init
|
14
15
|
true
|
15
16
|
end
|
17
|
+
# rubocop:enable Style/OptionalBooleanParameter
|
16
18
|
|
17
19
|
def st(schema_name = nil)
|
18
20
|
if schema_name.nil?
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_record/log_subscriber'
|
4
|
+
|
5
|
+
module Apartment
|
6
|
+
# Custom Log subscriber to include database name and schema name in sql logs
|
7
|
+
class LogSubscriber < ActiveRecord::LogSubscriber
|
8
|
+
# NOTE: for some reason, if the method definition is not here, then the custom debug method is not called
|
9
|
+
# rubocop:disable Lint/UselessMethodDefinition
|
10
|
+
def sql(event)
|
11
|
+
super(event)
|
12
|
+
end
|
13
|
+
# rubocop:enable Lint/UselessMethodDefinition
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def debug(progname = nil, &block)
|
18
|
+
progname = " #{apartment_log}#{progname}" unless progname.nil?
|
19
|
+
|
20
|
+
super(progname, &block)
|
21
|
+
end
|
22
|
+
|
23
|
+
def apartment_log
|
24
|
+
database = color("[#{Apartment.connection.raw_connection.db}] ", ActiveSupport::LogSubscriber::MAGENTA, true)
|
25
|
+
schema = nil
|
26
|
+
unless Apartment.connection.schema_search_path.nil?
|
27
|
+
schema = color("[#{Apartment.connection.schema_search_path.tr('"', '')}] ",
|
28
|
+
ActiveSupport::LogSubscriber::YELLOW, true)
|
29
|
+
end
|
30
|
+
"#{database}#{schema}"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/lib/apartment/railtie.rb
CHANGED
@@ -25,28 +25,33 @@ module Apartment
|
|
25
25
|
ActiveRecord::Migrator.migrations_paths = Rails.application.paths['db/migrate'].to_a
|
26
26
|
end
|
27
27
|
|
28
|
-
#
|
28
|
+
# Hook into ActionDispatch::Reloader to ensure Apartment is properly initialized
|
29
|
+
# Note that this doesn't entirely work as expected in Development,
|
30
|
+
# because this is called before classes are reloaded
|
31
|
+
# See the middleware/console declarations below to help with this. Hope to fix that soon.
|
32
|
+
#
|
29
33
|
config.to_prepare do
|
30
|
-
|
31
|
-
|
34
|
+
next if ARGV.any? { |arg| arg =~ /\Aassets:(?:precompile|clean)\z/ }
|
35
|
+
next if ARGV.any? { |arg| arg == 'webpacker:compile' }
|
36
|
+
next if ENV['APARTMENT_DISABLE_INIT']
|
32
37
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
#
|
37
|
-
module ApartmentInitializer
|
38
|
-
def connection
|
39
|
-
super.tap do
|
40
|
-
Apartment::Tenant.init_once
|
38
|
+
begin
|
39
|
+
Apartment.connection_class.connection_pool.with_connection do
|
40
|
+
Apartment::Tenant.init
|
41
41
|
end
|
42
|
+
rescue ::ActiveRecord::NoDatabaseError
|
43
|
+
# Since `db:create` and other tasks invoke this block from Rails 5.2.0,
|
44
|
+
# we need to swallow the error to execute `db:create` properly.
|
42
45
|
end
|
46
|
+
end
|
43
47
|
|
44
|
-
|
45
|
-
|
46
|
-
|
48
|
+
config.after_initialize do
|
49
|
+
# NOTE: Load the custom log subscriber if enabled
|
50
|
+
if Apartment.active_record_log
|
51
|
+
ActiveSupport::Notifications.unsubscribe 'sql.active_record'
|
52
|
+
Apartment::LogSubscriber.attach_to :active_record
|
47
53
|
end
|
48
54
|
end
|
49
|
-
ActiveRecord::Base.singleton_class.prepend ApartmentInitializer
|
50
55
|
|
51
56
|
#
|
52
57
|
# Ensure rake tasks are loaded
|
@@ -57,10 +62,8 @@ module Apartment
|
|
57
62
|
end
|
58
63
|
|
59
64
|
#
|
60
|
-
# The following initializers are a workaround to the fact that I can't
|
61
|
-
#
|
62
|
-
# Note this is technically valid for any environment where cache_classes
|
63
|
-
# is false, for us, it's just development
|
65
|
+
# The following initializers are a workaround to the fact that I can't properly hook into the rails reloader
|
66
|
+
# Note this is technically valid for any environment where cache_classes is false, for us, it's just development
|
64
67
|
#
|
65
68
|
if Rails.env.development?
|
66
69
|
|
@@ -69,11 +72,13 @@ module Apartment
|
|
69
72
|
app.config.middleware.use Apartment::Reloader
|
70
73
|
end
|
71
74
|
|
72
|
-
# Overrides reload! to also call Apartment::Tenant.init as well
|
73
|
-
# reloaded classes have the proper table_names
|
75
|
+
# Overrides reload! to also call Apartment::Tenant.init as well
|
76
|
+
# so that the reloaded classes have the proper table_names
|
77
|
+
# rubocop:disable Lint/Debugger
|
74
78
|
console do
|
75
79
|
require 'apartment/console'
|
76
80
|
end
|
81
|
+
# rubocop:enable Lint/Debugger
|
77
82
|
end
|
78
83
|
end
|
79
84
|
end
|
@@ -29,5 +29,24 @@ module Apartment
|
|
29
29
|
Note that your tenants currently haven't been migrated. You'll need to run `db:migrate` to rectify this.
|
30
30
|
WARNING
|
31
31
|
end
|
32
|
+
|
33
|
+
def self.create_tenant(tenant_name)
|
34
|
+
puts("Creating #{tenant_name} tenant")
|
35
|
+
Apartment::Tenant.create(tenant_name)
|
36
|
+
rescue Apartment::TenantExists => e
|
37
|
+
puts "Tried to create already existing tenant: #{e}"
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.migrate_tenant(tenant_name)
|
41
|
+
strategy = Apartment.db_migrate_tenant_missing_strategy
|
42
|
+
create_tenant(tenant_name) if strategy == :create_tenant
|
43
|
+
|
44
|
+
puts("Migrating #{tenant_name} tenant")
|
45
|
+
Apartment::Migrator.migrate tenant_name
|
46
|
+
rescue Apartment::TenantNotFound => e
|
47
|
+
raise e if strategy == :raise_exception
|
48
|
+
|
49
|
+
puts e.message
|
50
|
+
end
|
32
51
|
end
|
33
52
|
end
|
data/lib/apartment/tenant.rb
CHANGED
@@ -10,25 +10,10 @@ module Apartment
|
|
10
10
|
extend Forwardable
|
11
11
|
|
12
12
|
def_delegators :adapter, :create, :drop, :switch, :switch!, :current, :each,
|
13
|
-
:reset, :init, :set_callback, :seed, :
|
14
|
-
:default_tenant, :environmentify
|
13
|
+
:reset, :init, :set_callback, :seed, :default_tenant, :environmentify
|
15
14
|
|
16
15
|
attr_writer :config
|
17
16
|
|
18
|
-
def init_once
|
19
|
-
return if @already_initialized
|
20
|
-
|
21
|
-
# To avoid infinite loops in work init is doing,
|
22
|
-
# we need to set @already_initialized to true
|
23
|
-
# before init is called
|
24
|
-
@already_initialized = true
|
25
|
-
init
|
26
|
-
end
|
27
|
-
|
28
|
-
def reinitialize
|
29
|
-
@already_initialized = false
|
30
|
-
end
|
31
|
-
|
32
17
|
# Fetch the proper multi-tenant adapter based on Rails config
|
33
18
|
#
|
34
19
|
# @return {subclass of Apartment::AbstractAdapter}
|
@@ -38,9 +23,10 @@ module Apartment
|
|
38
23
|
adapter_method = "#{config[:adapter]}_adapter"
|
39
24
|
|
40
25
|
if defined?(JRUBY_VERSION)
|
41
|
-
|
26
|
+
case config[:adapter]
|
27
|
+
when /mysql/
|
42
28
|
adapter_method = 'jdbc_mysql_adapter'
|
43
|
-
|
29
|
+
when /postgresql/
|
44
30
|
adapter_method = 'jdbc_postgresql_adapter'
|
45
31
|
end
|
46
32
|
end
|
@@ -63,7 +49,6 @@ module Apartment
|
|
63
49
|
#
|
64
50
|
def reload!(config = nil)
|
65
51
|
Thread.current[:apartment_adapter] = nil
|
66
|
-
reinitialize
|
67
52
|
@config = config
|
68
53
|
end
|
69
54
|
|
data/lib/apartment/version.rb
CHANGED
data/lib/tasks/apartment.rake
CHANGED
@@ -10,12 +10,7 @@ apartment_namespace = namespace :apartment do
|
|
10
10
|
Apartment::TaskHelper.warn_if_tenants_empty
|
11
11
|
|
12
12
|
Apartment::TaskHelper.tenants.each do |tenant|
|
13
|
-
|
14
|
-
puts("Creating #{tenant} tenant")
|
15
|
-
Apartment::Tenant.create(tenant)
|
16
|
-
rescue Apartment::TenantExists => e
|
17
|
-
puts e.message
|
18
|
-
end
|
13
|
+
Apartment::TaskHelper.create_tenant(tenant)
|
19
14
|
end
|
20
15
|
end
|
21
16
|
|
@@ -35,21 +30,17 @@ apartment_namespace = namespace :apartment do
|
|
35
30
|
task :migrate do
|
36
31
|
Apartment::TaskHelper.warn_if_tenants_empty
|
37
32
|
Apartment::TaskHelper.each_tenant do |tenant|
|
38
|
-
|
39
|
-
puts("Migrating #{tenant} tenant")
|
40
|
-
Apartment::Migrator.migrate tenant
|
41
|
-
rescue Apartment::TenantNotFound => e
|
42
|
-
puts e.message
|
43
|
-
end
|
33
|
+
Apartment::TaskHelper.migrate_tenant(tenant)
|
44
34
|
end
|
45
35
|
end
|
46
36
|
|
47
37
|
desc 'Seed all tenants'
|
48
|
-
task seed
|
38
|
+
task :seed do
|
49
39
|
Apartment::TaskHelper.warn_if_tenants_empty
|
50
40
|
|
51
41
|
Apartment::TaskHelper.each_tenant do |tenant|
|
52
42
|
begin
|
43
|
+
Apartment::TaskHelper.create_tenant(tenant)
|
53
44
|
puts("Seeding #{tenant} tenant")
|
54
45
|
Apartment::Tenant.switch(tenant) do
|
55
46
|
Apartment::Tenant.seed
|
data/ros-apartment.gemspec
CHANGED
@@ -17,7 +17,7 @@ Gem::Specification.new do |s|
|
|
17
17
|
s.files = Dir.chdir(File.expand_path(__dir__)) do
|
18
18
|
`git ls-files -z`.split("\x0").reject do |f|
|
19
19
|
# NOTE: ignore all test related
|
20
|
-
f.match(%r{^(test|spec|features)/})
|
20
|
+
f.match(%r{^(test|spec|features|documentation)/})
|
21
21
|
end
|
22
22
|
end
|
23
23
|
s.executables = s.files.grep(%r{^bin/}).map { |f| File.basename(f) }
|
@@ -27,7 +27,7 @@ Gem::Specification.new do |s|
|
|
27
27
|
s.homepage = 'https://github.com/rails-on-services/apartment'
|
28
28
|
s.licenses = ['MIT']
|
29
29
|
|
30
|
-
s.add_dependency 'activerecord', '>= 5.0.0', '< 6.
|
30
|
+
s.add_dependency 'activerecord', '>= 5.0.0', '< 6.2'
|
31
31
|
s.add_dependency 'parallel', '< 2.0'
|
32
32
|
s.add_dependency 'public_suffix', '>= 2.0.5', '< 5.0'
|
33
33
|
s.add_dependency 'rack', '>= 1.3.6', '< 3.0'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ros-apartment
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryan Brunner
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2021-01-21 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activerecord
|
@@ -21,7 +21,7 @@ dependencies:
|
|
21
21
|
version: 5.0.0
|
22
22
|
- - "<"
|
23
23
|
- !ruby/object:Gem::Version
|
24
|
-
version: '6.
|
24
|
+
version: '6.2'
|
25
25
|
type: :runtime
|
26
26
|
prerelease: false
|
27
27
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -31,7 +31,7 @@ dependencies:
|
|
31
31
|
version: 5.0.0
|
32
32
|
- - "<"
|
33
33
|
- !ruby/object:Gem::Version
|
34
|
-
version: '6.
|
34
|
+
version: '6.2'
|
35
35
|
- !ruby/object:Gem::Dependency
|
36
36
|
name: parallel
|
37
37
|
requirement: !ruby/object:Gem::Requirement
|
@@ -228,6 +228,7 @@ executables: []
|
|
228
228
|
extensions: []
|
229
229
|
extra_rdoc_files: []
|
230
230
|
files:
|
231
|
+
- ".circleci/config.yml"
|
231
232
|
- ".github/ISSUE_TEMPLATE.md"
|
232
233
|
- ".github/workflows/changelog.yml"
|
233
234
|
- ".gitignore"
|
@@ -236,7 +237,6 @@ files:
|
|
236
237
|
- ".rubocop.yml"
|
237
238
|
- ".rubocop_todo.yml"
|
238
239
|
- ".story_branch.yml"
|
239
|
-
- ".travis.yml"
|
240
240
|
- Appraisals
|
241
241
|
- CHANGELOG.md
|
242
242
|
- Gemfile
|
@@ -251,11 +251,11 @@ files:
|
|
251
251
|
- gemfiles/rails_5_1.gemfile
|
252
252
|
- gemfiles/rails_5_2.gemfile
|
253
253
|
- gemfiles/rails_6_0.gemfile
|
254
|
+
- gemfiles/rails_6_1.gemfile
|
254
255
|
- gemfiles/rails_master.gemfile
|
255
256
|
- lib/apartment.rb
|
256
257
|
- lib/apartment/active_record/connection_handling.rb
|
257
258
|
- lib/apartment/active_record/internal_metadata.rb
|
258
|
-
- lib/apartment/active_record/log_subscriber.rb
|
259
259
|
- lib/apartment/active_record/schema_migration.rb
|
260
260
|
- lib/apartment/adapters/abstract_adapter.rb
|
261
261
|
- lib/apartment/adapters/abstract_jdbc_adapter.rb
|
@@ -274,6 +274,7 @@ files:
|
|
274
274
|
- lib/apartment/elevators/host.rb
|
275
275
|
- lib/apartment/elevators/host_hash.rb
|
276
276
|
- lib/apartment/elevators/subdomain.rb
|
277
|
+
- lib/apartment/log_subscriber.rb
|
277
278
|
- lib/apartment/migrator.rb
|
278
279
|
- lib/apartment/model.rb
|
279
280
|
- lib/apartment/railtie.rb
|
data/.travis.yml
DELETED
@@ -1,49 +0,0 @@
|
|
1
|
-
os: linux
|
2
|
-
|
3
|
-
language: ruby
|
4
|
-
services:
|
5
|
-
- docker
|
6
|
-
rvm:
|
7
|
-
- jruby-9.2.11.0
|
8
|
-
- 2.4.10
|
9
|
-
- 2.5.8
|
10
|
-
- 2.6.6
|
11
|
-
- 2.7.1
|
12
|
-
- jruby-head
|
13
|
-
- ruby-head
|
14
|
-
|
15
|
-
branches:
|
16
|
-
only:
|
17
|
-
- master
|
18
|
-
- development
|
19
|
-
|
20
|
-
gemfile:
|
21
|
-
- gemfiles/rails_5_0.gemfile
|
22
|
-
- gemfiles/rails_5_1.gemfile
|
23
|
-
- gemfiles/rails_5_2.gemfile
|
24
|
-
- gemfiles/rails_6_0.gemfile
|
25
|
-
- gemfiles/rails_master.gemfile
|
26
|
-
|
27
|
-
bundler_args: --without local
|
28
|
-
before_install:
|
29
|
-
- sudo /etc/init.d/mysql stop
|
30
|
-
- sudo /etc/init.d/postgresql stop
|
31
|
-
- docker-compose up -d
|
32
|
-
|
33
|
-
env:
|
34
|
-
RUBY_GC_MALLOC_LIMIT: 90000000
|
35
|
-
RUBY_GC_HEAP_FREE_SLOTS: 200000
|
36
|
-
jobs:
|
37
|
-
include:
|
38
|
-
- name: Rubocop Lint
|
39
|
-
script: gem install rubocop
|
40
|
-
|
41
|
-
allow_failures:
|
42
|
-
- rvm: ruby-head
|
43
|
-
- rvm: jruby-head
|
44
|
-
- gemfile: gemfiles/rails_master.gemfile
|
45
|
-
exclude:
|
46
|
-
- rvm: 2.4.10
|
47
|
-
gemfile: gemfiles/rails_6_0.gemfile
|
48
|
-
fast_finish: true
|
49
|
-
cache: bundler
|
@@ -1,44 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module ActiveRecord
|
4
|
-
# Supports the logging configuration to prepend the database and schema in the ActiveRecord log
|
5
|
-
class LogSubscriber
|
6
|
-
def apartment_log
|
7
|
-
return unless Apartment.active_record_log
|
8
|
-
|
9
|
-
database = color("[#{Apartment.connection.current_database}] ", ActiveSupport::LogSubscriber::MAGENTA, true)
|
10
|
-
schema = nil
|
11
|
-
unless Apartment.connection.schema_search_path.nil?
|
12
|
-
schema = color("[#{Apartment.connection.schema_search_path.tr('"', '')}] ",
|
13
|
-
ActiveSupport::LogSubscriber::YELLOW, true)
|
14
|
-
end
|
15
|
-
"#{database}#{schema}"
|
16
|
-
end
|
17
|
-
|
18
|
-
def payload_binds(binds, type_casted_binds)
|
19
|
-
return unless (binds || []).empty?
|
20
|
-
|
21
|
-
casted_params = type_casted_binds(type_casted_binds)
|
22
|
-
' ' + binds.zip(casted_params).map { |attr, value| render_bind(attr, value) }.inspect
|
23
|
-
end
|
24
|
-
|
25
|
-
def sql(event)
|
26
|
-
self.class.runtime += event.duration
|
27
|
-
return unless logger.debug?
|
28
|
-
|
29
|
-
payload = event.payload
|
30
|
-
|
31
|
-
return if IGNORE_PAYLOAD_NAMES.include?(payload[:name])
|
32
|
-
|
33
|
-
name = "#{payload[:name]} (#{event.duration.round(1)}ms)"
|
34
|
-
name = "CACHE #{name}" if payload[:cached]
|
35
|
-
sql = payload[:sql]
|
36
|
-
binds = payload_binds(payload[:binds], payload[:type_casted_binds])
|
37
|
-
|
38
|
-
name = colorize_payload_name(name, payload[:name])
|
39
|
-
sql = color(sql, sql_color(sql), true) if colorize_logging
|
40
|
-
|
41
|
-
debug " #{apartment_log}#{name} #{sql}#{binds}"
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|