ros-apartment 2.3.0 → 2.11.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 +63 -0
- data/.github/workflows/reviewdog.yml +22 -0
- data/.pryrc +5 -3
- data/.rubocop.yml +32 -0
- data/.rubocop_todo.yml +233 -0
- data/.ruby-version +1 -0
- data/.story_branch.yml +5 -0
- data/Appraisals +29 -42
- data/CHANGELOG.md +963 -0
- data/Gemfile +2 -7
- data/Guardfile +3 -16
- data/HISTORY.md +159 -68
- data/README.md +101 -21
- data/Rakefile +39 -22
- data/TODO.md +0 -1
- data/gemfiles/rails_5_2.gemfile +0 -5
- data/gemfiles/rails_6_0.gemfile +4 -9
- data/gemfiles/rails_6_1.gemfile +17 -0
- data/gemfiles/rails_7_0.gemfile +17 -0
- data/gemfiles/rails_master.gemfile +3 -8
- data/lib/apartment/active_record/connection_handling.rb +20 -0
- data/lib/apartment/active_record/internal_metadata.rb +9 -0
- data/lib/apartment/active_record/postgresql_adapter.rb +39 -0
- data/lib/apartment/active_record/schema_migration.rb +11 -0
- data/lib/apartment/adapters/abstract_adapter.rb +52 -46
- data/lib/apartment/adapters/abstract_jdbc_adapter.rb +5 -3
- data/lib/apartment/adapters/jdbc_mysql_adapter.rb +3 -3
- data/lib/apartment/adapters/jdbc_postgresql_adapter.rb +19 -13
- data/lib/apartment/adapters/mysql2_adapter.rb +15 -9
- data/lib/apartment/adapters/postgis_adapter.rb +3 -2
- data/lib/apartment/adapters/postgresql_adapter.rb +79 -31
- data/lib/apartment/adapters/sqlite3_adapter.rb +18 -8
- data/lib/apartment/console.rb +23 -11
- data/lib/apartment/custom_console.rb +42 -0
- data/lib/apartment/deprecation.rb +2 -1
- data/lib/apartment/elevators/domain.rb +4 -3
- data/lib/apartment/elevators/first_subdomain.rb +3 -2
- data/lib/apartment/elevators/generic.rb +4 -3
- data/lib/apartment/elevators/host.rb +6 -1
- data/lib/apartment/elevators/host_hash.rb +6 -2
- data/lib/apartment/elevators/subdomain.rb +9 -5
- data/lib/apartment/log_subscriber.rb +33 -0
- data/lib/apartment/migrator.rb +4 -3
- data/lib/apartment/model.rb +29 -0
- data/lib/apartment/railtie.rb +16 -20
- data/lib/apartment/tasks/enhancements.rb +4 -6
- data/lib/apartment/tasks/task_helper.rb +52 -0
- data/lib/apartment/tenant.rb +7 -10
- data/lib/apartment/version.rb +3 -1
- data/lib/apartment.rb +56 -15
- data/lib/generators/apartment/install/install_generator.rb +4 -3
- data/lib/generators/apartment/install/templates/apartment.rb +10 -3
- data/lib/tasks/apartment.rake +48 -87
- data/ros-apartment.gemspec +59 -0
- metadata +148 -240
- data/.travis.yml +0 -65
- data/apartment.gemspec +0 -47
- data/gemfiles/rails_4_2.gemfile +0 -23
- data/gemfiles/rails_5_0.gemfile +0 -22
- data/gemfiles/rails_5_1.gemfile +0 -22
- data/lib/apartment/reloader.rb +0 -21
- data/spec/adapters/jdbc_mysql_adapter_spec.rb +0 -19
- data/spec/adapters/jdbc_postgresql_adapter_spec.rb +0 -41
- data/spec/adapters/mysql2_adapter_spec.rb +0 -59
- data/spec/adapters/postgresql_adapter_spec.rb +0 -61
- data/spec/adapters/sqlite3_adapter_spec.rb +0 -83
- data/spec/apartment_spec.rb +0 -11
- data/spec/config/database.yml.sample +0 -49
- data/spec/dummy/Rakefile +0 -7
- data/spec/dummy/app/controllers/application_controller.rb +0 -6
- data/spec/dummy/app/helpers/application_helper.rb +0 -2
- data/spec/dummy/app/models/company.rb +0 -3
- data/spec/dummy/app/models/user.rb +0 -3
- data/spec/dummy/app/views/application/index.html.erb +0 -1
- data/spec/dummy/app/views/layouts/application.html.erb +0 -14
- data/spec/dummy/config/application.rb +0 -49
- data/spec/dummy/config/boot.rb +0 -11
- data/spec/dummy/config/database.yml.sample +0 -44
- data/spec/dummy/config/environment.rb +0 -5
- data/spec/dummy/config/environments/development.rb +0 -28
- data/spec/dummy/config/environments/production.rb +0 -51
- data/spec/dummy/config/environments/test.rb +0 -34
- data/spec/dummy/config/initializers/apartment.rb +0 -4
- data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -7
- data/spec/dummy/config/initializers/inflections.rb +0 -10
- data/spec/dummy/config/initializers/mime_types.rb +0 -5
- data/spec/dummy/config/initializers/secret_token.rb +0 -7
- data/spec/dummy/config/initializers/session_store.rb +0 -8
- data/spec/dummy/config/locales/en.yml +0 -5
- data/spec/dummy/config/routes.rb +0 -3
- data/spec/dummy/config.ru +0 -4
- data/spec/dummy/db/migrate/20110613152810_create_dummy_models.rb +0 -39
- data/spec/dummy/db/migrate/20111202022214_create_table_books.rb +0 -14
- data/spec/dummy/db/migrate/20180415260934_create_public_tokens.rb +0 -13
- data/spec/dummy/db/schema.rb +0 -55
- data/spec/dummy/db/seeds/import.rb +0 -5
- data/spec/dummy/db/seeds.rb +0 -5
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/dummy/public/404.html +0 -26
- data/spec/dummy/public/422.html +0 -26
- data/spec/dummy/public/500.html +0 -26
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/public/stylesheets/.gitkeep +0 -0
- data/spec/dummy/script/rails +0 -6
- data/spec/dummy_engine/.gitignore +0 -8
- data/spec/dummy_engine/Gemfile +0 -15
- data/spec/dummy_engine/Rakefile +0 -34
- data/spec/dummy_engine/bin/rails +0 -12
- data/spec/dummy_engine/config/initializers/apartment.rb +0 -51
- data/spec/dummy_engine/dummy_engine.gemspec +0 -24
- data/spec/dummy_engine/lib/dummy_engine/engine.rb +0 -4
- data/spec/dummy_engine/lib/dummy_engine/version.rb +0 -3
- data/spec/dummy_engine/lib/dummy_engine.rb +0 -4
- data/spec/dummy_engine/test/dummy/Rakefile +0 -6
- data/spec/dummy_engine/test/dummy/config/application.rb +0 -22
- data/spec/dummy_engine/test/dummy/config/boot.rb +0 -5
- data/spec/dummy_engine/test/dummy/config/database.yml +0 -25
- data/spec/dummy_engine/test/dummy/config/environment.rb +0 -5
- data/spec/dummy_engine/test/dummy/config/environments/development.rb +0 -37
- data/spec/dummy_engine/test/dummy/config/environments/production.rb +0 -78
- data/spec/dummy_engine/test/dummy/config/environments/test.rb +0 -39
- data/spec/dummy_engine/test/dummy/config/initializers/assets.rb +0 -8
- data/spec/dummy_engine/test/dummy/config/initializers/backtrace_silencers.rb +0 -7
- data/spec/dummy_engine/test/dummy/config/initializers/cookies_serializer.rb +0 -3
- data/spec/dummy_engine/test/dummy/config/initializers/filter_parameter_logging.rb +0 -4
- data/spec/dummy_engine/test/dummy/config/initializers/inflections.rb +0 -16
- data/spec/dummy_engine/test/dummy/config/initializers/mime_types.rb +0 -4
- data/spec/dummy_engine/test/dummy/config/initializers/session_store.rb +0 -3
- data/spec/dummy_engine/test/dummy/config/initializers/wrap_parameters.rb +0 -14
- data/spec/dummy_engine/test/dummy/config/locales/en.yml +0 -23
- data/spec/dummy_engine/test/dummy/config/routes.rb +0 -56
- data/spec/dummy_engine/test/dummy/config/secrets.yml +0 -22
- data/spec/dummy_engine/test/dummy/config.ru +0 -4
- data/spec/examples/connection_adapter_examples.rb +0 -42
- data/spec/examples/generic_adapter_custom_configuration_example.rb +0 -95
- data/spec/examples/generic_adapter_examples.rb +0 -163
- data/spec/examples/schema_adapter_examples.rb +0 -234
- data/spec/integration/apartment_rake_integration_spec.rb +0 -107
- data/spec/integration/query_caching_spec.rb +0 -81
- data/spec/integration/use_within_an_engine_spec.rb +0 -28
- data/spec/schemas/v1.rb +0 -16
- data/spec/schemas/v2.rb +0 -43
- data/spec/schemas/v3.rb +0 -49
- data/spec/spec_helper.rb +0 -61
- data/spec/support/apartment_helpers.rb +0 -43
- data/spec/support/capybara_sessions.rb +0 -15
- data/spec/support/config.rb +0 -10
- data/spec/support/contexts.rb +0 -52
- data/spec/support/requirements.rb +0 -35
- data/spec/support/setup.rb +0 -46
- data/spec/tasks/apartment_rake_spec.rb +0 -129
- data/spec/tenant_spec.rb +0 -190
- data/spec/unit/config_spec.rb +0 -112
- data/spec/unit/elevators/domain_spec.rb +0 -32
- data/spec/unit/elevators/first_subdomain_spec.rb +0 -24
- data/spec/unit/elevators/generic_spec.rb +0 -54
- data/spec/unit/elevators/host_hash_spec.rb +0 -32
- data/spec/unit/elevators/host_spec.rb +0 -89
- data/spec/unit/elevators/subdomain_spec.rb +0 -76
- data/spec/unit/migrator_spec.rb +0 -77
- data/spec/unit/reloader_spec.rb +0 -24
data/README.md
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
# Apartment
|
2
2
|
|
3
|
-
[![Gem Version](https://badge.fury.io/rb/apartment.svg)](https://badge.fury.io/rb/apartment)
|
4
|
-
[![Code Climate](https://codeclimate.com/
|
5
|
-
[![Build Status](https://travis-ci.org/
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/ros-apartment.svg)](https://badge.fury.io/rb/apartment)
|
4
|
+
[![Code Climate](https://api.codeclimate.com/v1/badges/b0dc327380bb8438f991/maintainability)](https://codeclimate.com/github/rails-on-services/apartment/maintainability)
|
5
|
+
[![Build Status](https://travis-ci.org/rails-on-services/apartment.svg?branch=development)](https://travis-ci.org/rails-on-services/apartment)
|
6
6
|
|
7
7
|
*Multitenancy for Rails and ActiveRecord*
|
8
8
|
|
@@ -33,7 +33,7 @@ may find or proposing improvements to the gem itself. Feel free to reach out.
|
|
33
33
|
Add the following to your Gemfile:
|
34
34
|
|
35
35
|
```ruby
|
36
|
-
gem 'ros-apartment'
|
36
|
+
gem 'ros-apartment', require: 'apartment'
|
37
37
|
```
|
38
38
|
|
39
39
|
Then generate your `Apartment` config file using
|
@@ -101,6 +101,16 @@ switched back at the end of the block to what it was before.
|
|
101
101
|
There is also `switch!` which doesn't take a block, but it's recommended to use `switch`.
|
102
102
|
To return to the default tenant, you can call `switch` with no arguments.
|
103
103
|
|
104
|
+
#### Multiple Tenants
|
105
|
+
|
106
|
+
When using schemas, you can also pass in a list of schemas if desired. Any tables defined in a schema earlier in the chain will be referenced first, so this is only useful if you have a schema with only some of the tables defined:
|
107
|
+
|
108
|
+
```ruby
|
109
|
+
Apartment::Tenant.switch(['tenant_1', 'tenant_2']) do
|
110
|
+
# ...
|
111
|
+
end
|
112
|
+
```
|
113
|
+
|
104
114
|
### Switching Tenants per request
|
105
115
|
|
106
116
|
You can have Apartment route to the appropriate tenant by adding some Rack middleware.
|
@@ -229,7 +239,7 @@ A Generic Elevator exists that allows you to pass a `Proc` (or anything that res
|
|
229
239
|
module MyApplication
|
230
240
|
class Application < Rails::Application
|
231
241
|
# Obviously not a contrived example
|
232
|
-
config.middleware.use Apartment::Elevators::Generic,
|
242
|
+
config.middleware.use Apartment::Elevators::Generic, proc { |request| request.host.reverse }
|
233
243
|
end
|
234
244
|
end
|
235
245
|
```
|
@@ -289,6 +299,27 @@ Apartment::Tenant.drop('tenant_name')
|
|
289
299
|
|
290
300
|
When method is called, the schema is dropped and all data from itself will be lost. Be careful with this method.
|
291
301
|
|
302
|
+
### Custom Prompt
|
303
|
+
|
304
|
+
#### Console methods
|
305
|
+
|
306
|
+
`ros-apartment` console configures two helper methods:
|
307
|
+
1. `tenant_list` - list available tenants while using the console
|
308
|
+
2. `st(tenant_name:String)` - Switches the context to the tenant name passed, if
|
309
|
+
it exists.
|
310
|
+
|
311
|
+
#### Custom printed prompt
|
312
|
+
|
313
|
+
`ros-apartment` also has a custom prompt that gives a bit more information about
|
314
|
+
the context in which you're running. It shows the environment as well as the tenant
|
315
|
+
that is currently switched to. In order for you to enable this, you need to require
|
316
|
+
the custom console in your application.
|
317
|
+
|
318
|
+
In `application.rb` add `require 'apartment/custom_console'`.
|
319
|
+
Please note that we rely on `pry-rails` to edit the prompt, thus your project needs
|
320
|
+
to install it as well. In order to do so, you need to add `gem 'pry-rails'` to your
|
321
|
+
project's gemfile.
|
322
|
+
|
292
323
|
## Config
|
293
324
|
|
294
325
|
The following config options should be set up in a Rails initializer such as:
|
@@ -303,6 +334,37 @@ Apartment.configure do |config|
|
|
303
334
|
end
|
304
335
|
```
|
305
336
|
|
337
|
+
### Skip tenant schema check
|
338
|
+
|
339
|
+
This is configurable by setting: `tenant_presence_check`. It defaults to true
|
340
|
+
in order to maintain the original gem behavior. This is only checked when using one of the PostgreSQL adapters.
|
341
|
+
The original gem behavior, when running `switch` would look for the existence of the schema before switching. This adds an extra query on every context switch. While in the default simple scenarios this is a valid check, in high volume platforms this adds some unnecessary overhead which can be detected in some other ways on the application level.
|
342
|
+
|
343
|
+
Setting this configuration value to `false` will disable the schema presence check before trying to switch the context.
|
344
|
+
|
345
|
+
```ruby
|
346
|
+
Apartment.configure do |config|
|
347
|
+
config.tenant_presence_check = false
|
348
|
+
end
|
349
|
+
```
|
350
|
+
|
351
|
+
### Additional logging information
|
352
|
+
|
353
|
+
Enabling this configuration will output the database that the process is currently connected to as well as which
|
354
|
+
schemas are in the search path. This can be enabled by setting to true the `active_record_log` configuration.
|
355
|
+
|
356
|
+
Please note that our custom logger inherits from `ActiveRecord::LogSubscriber` so this will be required for the configuration to work.
|
357
|
+
|
358
|
+
**Example log output:**
|
359
|
+
|
360
|
+
<img src="documentation/images/log_example.png">
|
361
|
+
|
362
|
+
```ruby
|
363
|
+
Apartment.configure do |config|
|
364
|
+
config.active_record_log = true
|
365
|
+
end
|
366
|
+
```
|
367
|
+
|
306
368
|
### Excluding models
|
307
369
|
|
308
370
|
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:
|
@@ -320,17 +382,30 @@ Rails will always access the 'public' tenant when accessing these models, but no
|
|
320
382
|
|
321
383
|
### Postgresql Schemas
|
322
384
|
|
323
|
-
|
385
|
+
#### Alternative: Creating new schemas by using raw SQL dumps
|
386
|
+
|
387
|
+
Apartment can be forced to use raw SQL dumps insted of `schema.rb` for creating new schemas. Use this when you are using some extra features in postgres that can't be represented in `schema.rb`, like materialized views etc.
|
388
|
+
|
389
|
+
This only applies while using postgres adapter and `config.use_schemas` is set to `true`.
|
390
|
+
(Note: this option doesn't use `db/structure.sql`, it creates SQL dump by executing `pg_dump`)
|
391
|
+
|
392
|
+
Enable this option with:
|
393
|
+
|
394
|
+
```ruby
|
395
|
+
config.use_sql = true
|
396
|
+
```
|
397
|
+
|
398
|
+
### Providing a Different default_tenant
|
324
399
|
|
325
400
|
By default, ActiveRecord will use `"$user", public` as the default `schema_search_path`. This can be modified if you wish to use a different default schema be setting:
|
326
401
|
|
327
402
|
```ruby
|
328
|
-
config.
|
403
|
+
config.default_tenant = "some_other_schema"
|
329
404
|
```
|
330
405
|
|
331
406
|
With that set, all excluded models will use this schema as the table name prefix instead of `public` and `reset` on `Apartment::Tenant` will return to this schema as well.
|
332
407
|
|
333
|
-
|
408
|
+
### Persistent Schemas
|
334
409
|
|
335
410
|
Apartment will normally just switch the `schema_search_path` whole hog to the one passed in. This can lead to problems if you want other schemas to always be searched as well. Enter `persistent_schemas`. You can configure a list of other schemas that will always remain in the search path, while the default gets swapped out:
|
336
411
|
|
@@ -398,7 +473,7 @@ schema_search_path: "public,shared_extensions"
|
|
398
473
|
...
|
399
474
|
```
|
400
475
|
|
401
|
-
This would be for a config with `
|
476
|
+
This would be for a config with `default_tenant` set to `public` and `persistent_schemas` set to `['shared_extensions']`. **Note**: This only works on Heroku with [Rails 4.1+](https://devcenter.heroku.com/changelog-items/426). For apps that use older Rails versions hosted on Heroku, the only way to properly setup is to start with a fresh PostgreSQL instance:
|
402
477
|
|
403
478
|
1. Append `?schema_search_path=public,hstore` to your `DATABASE_URL` environment variable, by this you don't have to revise the `database.yml` file (which is impossible since Heroku regenerates a completely different and immutable `database.yml` of its own on each deploy)
|
404
479
|
2. Run `heroku pg:psql` from your command line
|
@@ -436,18 +511,6 @@ schema in the `search_path` at all times. We won't be able to do this though unt
|
|
436
511
|
also contain the tenanted tables, which is an open issue with no real milestone to be completed.
|
437
512
|
Happy to accept PR's on the matter.
|
438
513
|
|
439
|
-
#### Alternative: Creating new schemas by using raw SQL dumps
|
440
|
-
|
441
|
-
Apartment can be forced to use raw SQL dumps insted of `schema.rb` for creating new schemas. Use this when you are using some extra features in postgres that can't be represented in `schema.rb`, like materialized views etc.
|
442
|
-
|
443
|
-
This only applies while using postgres adapter and `config.use_schemas` is set to `true`.
|
444
|
-
(Note: this option doesn't use `db/structure.sql`, it creates SQL dump by executing `pg_dump`)
|
445
|
-
|
446
|
-
Enable this option with:
|
447
|
-
```ruby
|
448
|
-
config.use_sql = true
|
449
|
-
```
|
450
|
-
|
451
514
|
### Managing Migrations
|
452
515
|
|
453
516
|
In order to migrate all of your tenants (or postgresql schemas) you need to provide a list
|
@@ -558,6 +621,16 @@ module Apartment
|
|
558
621
|
end
|
559
622
|
```
|
560
623
|
|
624
|
+
## Running rails console without a connection to the database
|
625
|
+
|
626
|
+
By default, once apartment starts, it establishes a connection to the database. It is possible to
|
627
|
+
disable this initial connection, by running with `APARTMENT_DISABLE_INIT` set to something:
|
628
|
+
|
629
|
+
```shell
|
630
|
+
$ APARTMENT_DISABLE_INIT=true DATABASE_URL=postgresql://localhost:1234/buk_development bin/rails runner 'puts 1'
|
631
|
+
# 1
|
632
|
+
```
|
633
|
+
|
561
634
|
## Contributing
|
562
635
|
|
563
636
|
* In both `spec/dummy/config` and `spec/config`, you will see `database.yml.sample` files
|
@@ -569,6 +642,13 @@ end
|
|
569
642
|
|
570
643
|
* If you're looking to help, check out the TODO file for some upcoming changes I'd like to implement in Apartment.
|
571
644
|
|
645
|
+
### Running bundle install
|
646
|
+
|
647
|
+
mysql2 gem in some cases fails to install.
|
648
|
+
If you face problems running bundle install in OSX, try installing the gem running:
|
649
|
+
|
650
|
+
`gem install mysql2 -v '0.5.3' -- --with-ldflags=-L/usr/local/opt/openssl/lib --with-cppflags=-I/usr/local/opt/openssl/include`
|
651
|
+
|
572
652
|
## License
|
573
653
|
|
574
654
|
Apartment is released under the [MIT License](http://www.opensource.org/licenses/MIT).
|
data/Rakefile
CHANGED
@@ -1,19 +1,25 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'bundler'
|
5
|
+
rescue StandardError
|
6
|
+
'You must `gem install bundler` and `bundle install` to run rake tasks'
|
7
|
+
end
|
2
8
|
Bundler.setup
|
3
9
|
Bundler::GemHelper.install_tasks
|
4
10
|
|
5
11
|
require 'appraisal'
|
6
12
|
|
7
|
-
require
|
8
|
-
require
|
13
|
+
require 'rspec'
|
14
|
+
require 'rspec/core/rake_task'
|
9
15
|
|
10
|
-
RSpec::Core::RakeTask.new(:
|
11
|
-
spec.pattern =
|
16
|
+
RSpec::Core::RakeTask.new(spec: %w[db:copy_credentials db:test:prepare]) do |spec|
|
17
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
12
18
|
# spec.rspec_opts = '--order rand:47078'
|
13
19
|
end
|
14
20
|
|
15
21
|
namespace :spec do
|
16
|
-
[
|
22
|
+
%i[tasks unit adapters integration].each do |type|
|
17
23
|
RSpec::Core::RakeTask.new(type => :spec) do |spec|
|
18
24
|
spec.pattern = "spec/#{type}/**/*_spec.rb"
|
19
25
|
end
|
@@ -27,11 +33,11 @@ task :console do
|
|
27
33
|
Pry.start
|
28
34
|
end
|
29
35
|
|
30
|
-
task :
|
36
|
+
task default: :spec
|
31
37
|
|
32
38
|
namespace :db do
|
33
39
|
namespace :test do
|
34
|
-
task :
|
40
|
+
task prepare: %w[postgres:drop_db postgres:build_db mysql:drop_db mysql:build_db]
|
35
41
|
end
|
36
42
|
|
37
43
|
desc "copy sample database credential files over if real files don't exist"
|
@@ -40,29 +46,36 @@ namespace :db do
|
|
40
46
|
apartment_db_file = 'spec/config/database.yml'
|
41
47
|
rails_db_file = 'spec/dummy/config/database.yml'
|
42
48
|
|
43
|
-
|
44
|
-
|
49
|
+
unless File.exist?(apartment_db_file)
|
50
|
+
FileUtils.copy("#{apartment_db_file}.sample", apartment_db_file, verbose: true)
|
51
|
+
end
|
52
|
+
FileUtils.copy("#{rails_db_file}.sample", rails_db_file, verbose: true) unless File.exist?(rails_db_file)
|
45
53
|
end
|
46
54
|
end
|
47
55
|
|
48
56
|
namespace :postgres do
|
49
57
|
require 'active_record'
|
50
|
-
require
|
58
|
+
require File.join(File.dirname(__FILE__), 'spec', 'support', 'config').to_s
|
51
59
|
|
52
60
|
desc 'Build the PostgreSQL test databases'
|
53
61
|
task :build_db do
|
54
62
|
params = []
|
55
|
-
params <<
|
63
|
+
params << '-E UTF8'
|
56
64
|
params << pg_config['database']
|
57
65
|
params << "-U#{pg_config['username']}"
|
58
66
|
params << "-h#{pg_config['host']}" if pg_config['host']
|
59
67
|
params << "-p#{pg_config['port']}" if pg_config['port']
|
60
|
-
|
68
|
+
|
69
|
+
begin
|
70
|
+
`createdb #{params.join(' ')}`
|
71
|
+
rescue StandardError
|
72
|
+
'test db already exists'
|
73
|
+
end
|
61
74
|
ActiveRecord::Base.establish_connection pg_config
|
62
75
|
migrate
|
63
76
|
end
|
64
77
|
|
65
|
-
desc
|
78
|
+
desc 'drop the PostgreSQL test database'
|
66
79
|
task :drop_db do
|
67
80
|
puts "dropping database #{pg_config['database']}"
|
68
81
|
params = []
|
@@ -70,14 +83,13 @@ namespace :postgres do
|
|
70
83
|
params << "-U#{pg_config['username']}"
|
71
84
|
params << "-h#{pg_config['host']}" if pg_config['host']
|
72
85
|
params << "-p#{pg_config['port']}" if pg_config['port']
|
73
|
-
|
86
|
+
`dropdb #{params.join(' ')}`
|
74
87
|
end
|
75
|
-
|
76
88
|
end
|
77
89
|
|
78
90
|
namespace :mysql do
|
79
91
|
require 'active_record'
|
80
|
-
require
|
92
|
+
require File.join(File.dirname(__FILE__), 'spec', 'support', 'config').to_s
|
81
93
|
|
82
94
|
desc 'Build the MySQL test databases'
|
83
95
|
task :build_db do
|
@@ -85,24 +97,29 @@ namespace :mysql do
|
|
85
97
|
params << "-h #{my_config['host']}" if my_config['host']
|
86
98
|
params << "-u #{my_config['username']}" if my_config['username']
|
87
99
|
params << "-p#{my_config['password']}" if my_config['password']
|
88
|
-
|
100
|
+
params << "--port #{my_config['port']}" if my_config['port']
|
101
|
+
begin
|
102
|
+
`mysqladmin #{params.join(' ')} create #{my_config['database']}`
|
103
|
+
rescue StandardError
|
104
|
+
'test db already exists'
|
105
|
+
end
|
89
106
|
ActiveRecord::Base.establish_connection my_config
|
90
107
|
migrate
|
91
108
|
end
|
92
109
|
|
93
|
-
desc
|
110
|
+
desc 'drop the MySQL test database'
|
94
111
|
task :drop_db do
|
95
112
|
puts "dropping database #{my_config['database']}"
|
96
113
|
params = []
|
97
114
|
params << "-h #{my_config['host']}" if my_config['host']
|
98
115
|
params << "-u #{my_config['username']}" if my_config['username']
|
99
116
|
params << "-p#{my_config['password']}" if my_config['password']
|
100
|
-
|
117
|
+
params << "--port #{my_config['port']}" if my_config['port']
|
118
|
+
`mysqladmin #{params.join(' ')} drop #{my_config['database']} --force`
|
101
119
|
end
|
102
|
-
|
103
120
|
end
|
104
121
|
|
105
|
-
# TODO clean this up
|
122
|
+
# TODO: clean this up
|
106
123
|
def config
|
107
124
|
Apartment::Test.config['connections']
|
108
125
|
end
|
data/TODO.md
CHANGED
data/gemfiles/rails_5_2.gemfile
CHANGED
data/gemfiles/rails_6_0.gemfile
CHANGED
@@ -2,21 +2,16 @@
|
|
2
2
|
|
3
3
|
source "http://rubygems.org"
|
4
4
|
|
5
|
-
gem "rails", "~> 6.0.0
|
6
|
-
|
7
|
-
group :local do
|
8
|
-
gem "pry"
|
9
|
-
gem "guard-rspec", "~> 4.2"
|
10
|
-
end
|
5
|
+
gem "rails", "~> 6.0.0"
|
11
6
|
|
12
7
|
platforms :ruby do
|
13
8
|
gem "sqlite3", "~> 1.4"
|
14
9
|
end
|
15
10
|
|
16
11
|
platforms :jruby do
|
17
|
-
gem "activerecord-jdbc-adapter", "~> 60.0
|
18
|
-
gem "activerecord-jdbcpostgresql-adapter", "~> 60.0
|
19
|
-
gem "activerecord-jdbcmysql-adapter", "~> 60.0
|
12
|
+
gem "activerecord-jdbc-adapter", "~> 60.0"
|
13
|
+
gem "activerecord-jdbcpostgresql-adapter", "~> 60.0"
|
14
|
+
gem "activerecord-jdbcmysql-adapter", "~> 60.0"
|
20
15
|
end
|
21
16
|
|
22
17
|
gemspec path: "../"
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# This file was generated by Appraisal
|
2
|
+
|
3
|
+
source "http://rubygems.org"
|
4
|
+
|
5
|
+
gem "rails", "~> 6.1.0"
|
6
|
+
|
7
|
+
platforms :ruby do
|
8
|
+
gem "sqlite3", "~> 1.4"
|
9
|
+
end
|
10
|
+
|
11
|
+
platforms :jruby do
|
12
|
+
gem "activerecord-jdbc-adapter", "~> 61.0"
|
13
|
+
gem "activerecord-jdbcpostgresql-adapter", "~> 61.0"
|
14
|
+
gem "activerecord-jdbcmysql-adapter", "~> 61.0"
|
15
|
+
end
|
16
|
+
|
17
|
+
gemspec path: "../"
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# This file was generated by Appraisal
|
2
|
+
|
3
|
+
source "http://rubygems.org"
|
4
|
+
|
5
|
+
gem "rails", "~> 7.0.0"
|
6
|
+
|
7
|
+
platforms :ruby do
|
8
|
+
gem "sqlite3", "~> 1.4"
|
9
|
+
end
|
10
|
+
|
11
|
+
platforms :jruby do
|
12
|
+
gem "activerecord-jdbc-adapter", "~> 61.0"
|
13
|
+
gem "activerecord-jdbcpostgresql-adapter", "~> 61.0"
|
14
|
+
gem "activerecord-jdbcmysql-adapter", "~> 61.0"
|
15
|
+
end
|
16
|
+
|
17
|
+
gemspec path: "../"
|
@@ -4,19 +4,14 @@ source "http://rubygems.org"
|
|
4
4
|
|
5
5
|
gem "rails", git: "https://github.com/rails/rails.git"
|
6
6
|
|
7
|
-
group :local do
|
8
|
-
gem "pry"
|
9
|
-
gem "guard-rspec", "~> 4.2"
|
10
|
-
end
|
11
|
-
|
12
7
|
platforms :ruby do
|
13
8
|
gem "sqlite3", "~> 1.4"
|
14
9
|
end
|
15
10
|
|
16
11
|
platforms :jruby do
|
17
|
-
gem "activerecord-jdbc-adapter", "~>
|
18
|
-
gem "activerecord-jdbcpostgresql-adapter", "~>
|
19
|
-
gem "activerecord-jdbcmysql-adapter", "~>
|
12
|
+
gem "activerecord-jdbc-adapter", "~> 61.0"
|
13
|
+
gem "activerecord-jdbcpostgresql-adapter", "~> 61.0"
|
14
|
+
gem "activerecord-jdbcmysql-adapter", "~> 61.0"
|
20
15
|
end
|
21
16
|
|
22
17
|
gemspec path: "../"
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
# This is monkeypatching activerecord to ensure that whenever a new connection is established it
|
5
|
+
# switches to the same tenant as before the connection switching. This problem is more evident when
|
6
|
+
# using read replica in Rails 6
|
7
|
+
module ConnectionHandling
|
8
|
+
def connected_to_with_tenant(database: nil, role: nil, prevent_writes: false, &blk)
|
9
|
+
current_tenant = Apartment::Tenant.current
|
10
|
+
|
11
|
+
connected_to_without_tenant(database: database, role: role, prevent_writes: prevent_writes) do
|
12
|
+
Apartment::Tenant.switch!(current_tenant)
|
13
|
+
yield(blk)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
alias connected_to_without_tenant connected_to
|
18
|
+
alias connected_to connected_to_with_tenant
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# rubocop:disable Style/ClassAndModuleChildren
|
4
|
+
|
5
|
+
# NOTE: This patch is meant to remove any schema_prefix appart from the ones for
|
6
|
+
# excluded models. The schema_prefix would be resolved by apartment's setting
|
7
|
+
# of search path
|
8
|
+
module Apartment::PostgreSqlAdapterPatch
|
9
|
+
def default_sequence_name(table, _column)
|
10
|
+
res = super
|
11
|
+
schema_prefix = "#{Apartment::Tenant.current}."
|
12
|
+
default_tenant_prefix = "#{Apartment::Tenant.default_tenant}."
|
13
|
+
|
14
|
+
# NOTE: Excluded models should always access the sequence from the default
|
15
|
+
# tenant schema
|
16
|
+
if excluded_model?(table)
|
17
|
+
res.sub!(schema_prefix, default_tenant_prefix) if schema_prefix != default_tenant_prefix
|
18
|
+
return res
|
19
|
+
end
|
20
|
+
|
21
|
+
res.delete_prefix!(schema_prefix) if res&.starts_with?(schema_prefix)
|
22
|
+
|
23
|
+
res
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def excluded_model?(table)
|
29
|
+
Apartment.excluded_models.any? { |m| m.constantize.table_name == table }
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
require 'active_record/connection_adapters/postgresql_adapter'
|
34
|
+
|
35
|
+
# NOTE: inject this into postgresql adapters
|
36
|
+
class ActiveRecord::ConnectionAdapters::PostgreSQLAdapter
|
37
|
+
include Apartment::PostgreSqlAdapterPatch
|
38
|
+
end
|
39
|
+
# rubocop:enable Style/ClassAndModuleChildren
|