ros-apartment 2.3.0.alpha2 → 2.6.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/.github/workflows/.rubocop-linter.yml +22 -0
- data/.pryrc +5 -3
- data/.rubocop.yml +21 -0
- data/.rubocop_todo.yml +29 -0
- data/.story_branch.yml +4 -0
- data/.travis.yml +15 -36
- data/Appraisals +16 -29
- data/Gemfile +4 -1
- data/Guardfile +3 -1
- data/HISTORY.md +7 -0
- data/README.md +80 -39
- data/Rakefile +45 -23
- data/apartment.gemspec +33 -25
- data/gemfiles/rails_4_2.gemfile +12 -10
- data/gemfiles/rails_5_0.gemfile +2 -1
- data/gemfiles/rails_5_1.gemfile +2 -1
- data/gemfiles/rails_5_2.gemfile +2 -1
- data/gemfiles/rails_6_0.gemfile +6 -5
- data/gemfiles/rails_master.gemfile +2 -1
- data/lib/apartment.rb +36 -11
- data/lib/apartment/active_record/connection_handling.rb +17 -0
- data/lib/apartment/active_record/internal_metadata.rb +11 -0
- data/lib/apartment/active_record/schema_migration.rb +13 -0
- data/lib/apartment/adapters/abstract_adapter.rb +50 -45
- data/lib/apartment/adapters/abstract_jdbc_adapter.rb +4 -3
- data/lib/apartment/adapters/jdbc_mysql_adapter.rb +3 -3
- data/lib/apartment/adapters/jdbc_postgresql_adapter.rb +20 -13
- data/lib/apartment/adapters/mysql2_adapter.rb +10 -9
- data/lib/apartment/adapters/postgis_adapter.rb +3 -2
- data/lib/apartment/adapters/postgresql_adapter.rb +55 -27
- data/lib/apartment/adapters/sqlite3_adapter.rb +18 -8
- data/lib/apartment/console.rb +35 -3
- 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/migrator.rb +4 -3
- data/lib/apartment/model.rb +27 -0
- data/lib/apartment/railtie.rb +26 -15
- data/lib/apartment/reloader.rb +2 -1
- data/lib/apartment/tasks/enhancements.rb +4 -6
- data/lib/apartment/tenant.rb +19 -9
- data/lib/apartment/version.rb +3 -1
- data/lib/generators/apartment/install/install_generator.rb +4 -3
- data/lib/generators/apartment/install/templates/apartment.rb +3 -2
- data/lib/tasks/apartment.rake +24 -19
- metadata +79 -256
- 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.ru +0 -4
- 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/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.rb +0 -5
- data/spec/dummy/db/seeds/import.rb +0 -5
- 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.rb +0 -4
- 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/test/dummy/Rakefile +0 -6
- data/spec/dummy_engine/test/dummy/config.ru +0 -4
- 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/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
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'apartment/adapters/abstract_adapter'
|
|
2
4
|
|
|
3
5
|
module Apartment
|
|
4
6
|
module Tenant
|
|
5
|
-
|
|
6
7
|
def self.postgresql_adapter(config)
|
|
7
8
|
adapter = Adapters::PostgresqlAdapter
|
|
8
9
|
adapter = Adapters::PostgresqlSchemaAdapter if Apartment.use_schemas
|
|
@@ -14,8 +15,7 @@ module Apartment
|
|
|
14
15
|
module Adapters
|
|
15
16
|
# Default adapter when not using Postgresql Schemas
|
|
16
17
|
class PostgresqlAdapter < AbstractAdapter
|
|
17
|
-
|
|
18
|
-
private
|
|
18
|
+
private
|
|
19
19
|
|
|
20
20
|
def rescue_from
|
|
21
21
|
PG::Error
|
|
@@ -24,7 +24,6 @@ module Apartment
|
|
|
24
24
|
|
|
25
25
|
# Separate Adapter for Postgresql when using schemas
|
|
26
26
|
class PostgresqlSchemaAdapter < AbstractAdapter
|
|
27
|
-
|
|
28
27
|
def initialize(config)
|
|
29
28
|
super
|
|
30
29
|
|
|
@@ -38,13 +37,19 @@ module Apartment
|
|
|
38
37
|
def reset
|
|
39
38
|
@current = default_tenant
|
|
40
39
|
Apartment.connection.schema_search_path = full_search_path
|
|
40
|
+
reset_sequence_names
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def init
|
|
44
|
+
super
|
|
45
|
+
Apartment.connection.schema_search_path = full_search_path
|
|
41
46
|
end
|
|
42
47
|
|
|
43
48
|
def current
|
|
44
49
|
@current || default_tenant
|
|
45
50
|
end
|
|
46
51
|
|
|
47
|
-
|
|
52
|
+
protected
|
|
48
53
|
|
|
49
54
|
def process_excluded_model(excluded_model)
|
|
50
55
|
excluded_model.constantize.tap do |klass|
|
|
@@ -56,39 +61,45 @@ module Apartment
|
|
|
56
61
|
end
|
|
57
62
|
|
|
58
63
|
def drop_command(conn, tenant)
|
|
59
|
-
conn.execute(%
|
|
64
|
+
conn.execute(%(DROP SCHEMA "#{tenant}" CASCADE))
|
|
60
65
|
end
|
|
61
66
|
|
|
62
67
|
# Set schema search path to new schema
|
|
63
68
|
#
|
|
64
69
|
def connect_to_new(tenant = nil)
|
|
65
70
|
return reset if tenant.nil?
|
|
66
|
-
raise ActiveRecord::StatementInvalid.new("Could not find schema #{tenant}") unless Apartment.connection.schema_exists?(tenant.to_s)
|
|
67
71
|
|
|
68
|
-
|
|
72
|
+
tenant = tenant.to_s
|
|
73
|
+
raise ActiveRecord::StatementInvalid, "Could not find schema #{tenant}" unless tenant_exists?(tenant)
|
|
74
|
+
|
|
75
|
+
@current = tenant
|
|
69
76
|
Apartment.connection.schema_search_path = full_search_path
|
|
70
77
|
|
|
71
78
|
# When the PostgreSQL version is < 9.3,
|
|
72
79
|
# there is a issue for prepared statement with changing search_path.
|
|
73
80
|
# https://www.postgresql.org/docs/9.3/static/sql-prepare.html
|
|
74
|
-
if postgresql_version <
|
|
75
|
-
|
|
76
|
-
end
|
|
77
|
-
|
|
81
|
+
Apartment.connection.clear_cache! if postgresql_version < 90_300
|
|
82
|
+
reset_sequence_names
|
|
78
83
|
rescue *rescuable_exceptions
|
|
79
84
|
raise TenantNotFound, "One of the following schema(s) is invalid: \"#{tenant}\" #{full_search_path}"
|
|
80
85
|
end
|
|
81
86
|
|
|
82
|
-
|
|
87
|
+
private
|
|
88
|
+
|
|
89
|
+
def tenant_exists?(tenant)
|
|
90
|
+
return true unless Apartment.tenant_presence_check
|
|
91
|
+
|
|
92
|
+
Apartment.connection.schema_exists?(tenant)
|
|
93
|
+
end
|
|
83
94
|
|
|
84
95
|
def create_tenant_command(conn, tenant)
|
|
85
|
-
conn.execute(%
|
|
96
|
+
conn.execute(%(CREATE SCHEMA "#{tenant}"))
|
|
86
97
|
end
|
|
87
98
|
|
|
88
99
|
# Generate the final search path to set including persistent_schemas
|
|
89
100
|
#
|
|
90
101
|
def full_search_path
|
|
91
|
-
persistent_schemas.map(&:inspect).join(
|
|
102
|
+
persistent_schemas.map(&:inspect).join(', ')
|
|
92
103
|
end
|
|
93
104
|
|
|
94
105
|
def persistent_schemas
|
|
@@ -100,20 +111,32 @@ module Apartment
|
|
|
100
111
|
# public from Rails 5.0.
|
|
101
112
|
Apartment.connection.send(:postgresql_version)
|
|
102
113
|
end
|
|
114
|
+
|
|
115
|
+
def reset_sequence_names
|
|
116
|
+
# sequence_name contains the schema, so it must be reset after switch
|
|
117
|
+
# There is `reset_sequence_name`, but that method actually goes to the database
|
|
118
|
+
# to find out the new name. Therefore, we do this hack to only unset the name,
|
|
119
|
+
# and it will be dynamically found the next time it is needed
|
|
120
|
+
ActiveRecord::Base.descendants
|
|
121
|
+
.select { |c| c.instance_variable_defined?(:@sequence_name) }
|
|
122
|
+
.reject { |c| c.instance_variable_defined?(:@explicit_sequence_name) && c.instance_variable_get(:@explicit_sequence_name) }
|
|
123
|
+
.each do |c|
|
|
124
|
+
c.remove_instance_variable :@sequence_name
|
|
125
|
+
end
|
|
126
|
+
end
|
|
103
127
|
end
|
|
104
128
|
|
|
105
129
|
# Another Adapter for Postgresql when using schemas and SQL
|
|
106
130
|
class PostgresqlSchemaFromSqlAdapter < PostgresqlSchemaAdapter
|
|
107
|
-
|
|
108
|
-
PSQL_DUMP_BLACKLISTED_STATEMENTS= [
|
|
131
|
+
PSQL_DUMP_BLACKLISTED_STATEMENTS = [
|
|
109
132
|
/SET search_path/i, # overridden later
|
|
110
133
|
/SET lock_timeout/i, # new in postgresql 9.3
|
|
111
134
|
/SET row_security/i, # new in postgresql 9.5
|
|
112
135
|
/SET idle_in_transaction_session_timeout/i, # new in postgresql 9.6
|
|
113
136
|
/CREATE SCHEMA public/i,
|
|
114
|
-
/COMMENT ON SCHEMA public/i
|
|
137
|
+
/COMMENT ON SCHEMA public/i
|
|
115
138
|
|
|
116
|
-
]
|
|
139
|
+
].freeze
|
|
117
140
|
|
|
118
141
|
def import_database_schema
|
|
119
142
|
preserving_search_path do
|
|
@@ -122,14 +145,14 @@ module Apartment
|
|
|
122
145
|
end
|
|
123
146
|
end
|
|
124
147
|
|
|
125
|
-
|
|
148
|
+
private
|
|
126
149
|
|
|
127
150
|
# Re-set search path after the schema is imported.
|
|
128
151
|
# Postgres now sets search path to empty before dumping the schema
|
|
129
152
|
# and it mut be reset
|
|
130
153
|
#
|
|
131
154
|
def preserving_search_path
|
|
132
|
-
search_path = Apartment.connection.execute(
|
|
155
|
+
search_path = Apartment.connection.execute('show search_path').first['search_path']
|
|
133
156
|
yield
|
|
134
157
|
Apartment.connection.execute("set search_path = #{search_path}")
|
|
135
158
|
end
|
|
@@ -153,7 +176,6 @@ module Apartment
|
|
|
153
176
|
# @return {String} raw SQL contaning only postgres schema dump
|
|
154
177
|
#
|
|
155
178
|
def pg_dump_schema
|
|
156
|
-
|
|
157
179
|
# Skip excluded tables? :/
|
|
158
180
|
# excluded_tables =
|
|
159
181
|
# collect_table_names(Apartment.excluded_models)
|
|
@@ -176,7 +198,10 @@ module Apartment
|
|
|
176
198
|
# Temporary set Postgresql related environment variables if there are in @config
|
|
177
199
|
#
|
|
178
200
|
def with_pg_env(&block)
|
|
179
|
-
pghost
|
|
201
|
+
pghost = ENV['PGHOST']
|
|
202
|
+
pgport = ENV['PGPORT']
|
|
203
|
+
pguser = ENV['PGUSER']
|
|
204
|
+
pgpassword = ENV['PGPASSWORD']
|
|
180
205
|
|
|
181
206
|
ENV['PGHOST'] = @config[:host] if @config[:host]
|
|
182
207
|
ENV['PGPORT'] = @config[:port].to_s if @config[:port]
|
|
@@ -185,7 +210,10 @@ module Apartment
|
|
|
185
210
|
|
|
186
211
|
block.call
|
|
187
212
|
ensure
|
|
188
|
-
ENV['PGHOST']
|
|
213
|
+
ENV['PGHOST'] = pghost
|
|
214
|
+
ENV['PGPORT'] = pgport
|
|
215
|
+
ENV['PGUSER'] = pguser
|
|
216
|
+
ENV['PGPASSWORD'] = pgpassword
|
|
189
217
|
end
|
|
190
218
|
|
|
191
219
|
# Remove "SET search_path ..." line from SQL dump and prepend search_path set to current tenant
|
|
@@ -197,7 +225,7 @@ module Apartment
|
|
|
197
225
|
|
|
198
226
|
swap_schema_qualifier(sql)
|
|
199
227
|
.split("\n")
|
|
200
|
-
.select {|line| check_input_against_regexps(line, PSQL_DUMP_BLACKLISTED_STATEMENTS).empty?}
|
|
228
|
+
.select { |line| check_input_against_regexps(line, PSQL_DUMP_BLACKLISTED_STATEMENTS).empty? }
|
|
201
229
|
.prepend(search_path)
|
|
202
230
|
.join("\n")
|
|
203
231
|
end
|
|
@@ -207,7 +235,7 @@ module Apartment
|
|
|
207
235
|
if Apartment.pg_excluded_names.any? { |name| match.include? name }
|
|
208
236
|
match
|
|
209
237
|
else
|
|
210
|
-
match.gsub("#{default_tenant}.", %
|
|
238
|
+
match.gsub("#{default_tenant}.", %("#{current}".))
|
|
211
239
|
end
|
|
212
240
|
end
|
|
213
241
|
end
|
|
@@ -215,7 +243,7 @@ module Apartment
|
|
|
215
243
|
# Checks if any of regexps matches against input
|
|
216
244
|
#
|
|
217
245
|
def check_input_against_regexps(input, regexps)
|
|
218
|
-
regexps.select {|c| input.match c}
|
|
246
|
+
regexps.select { |c| input.match c }
|
|
219
247
|
end
|
|
220
248
|
|
|
221
249
|
# Collect table names from AR Models
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'apartment/adapters/abstract_adapter'
|
|
2
4
|
|
|
3
5
|
module Apartment
|
|
@@ -16,8 +18,10 @@ module Apartment
|
|
|
16
18
|
end
|
|
17
19
|
|
|
18
20
|
def drop(tenant)
|
|
19
|
-
|
|
20
|
-
|
|
21
|
+
unless File.exist?(database_file(tenant))
|
|
22
|
+
raise TenantNotFound,
|
|
23
|
+
"The tenant #{environmentify(tenant)} cannot be found."
|
|
24
|
+
end
|
|
21
25
|
|
|
22
26
|
File.delete(database_file(tenant))
|
|
23
27
|
end
|
|
@@ -26,18 +30,24 @@ module Apartment
|
|
|
26
30
|
File.basename(Apartment.connection.instance_variable_get(:@config)[:database], '.sqlite3')
|
|
27
31
|
end
|
|
28
32
|
|
|
29
|
-
|
|
33
|
+
protected
|
|
30
34
|
|
|
31
35
|
def connect_to_new(tenant)
|
|
32
|
-
|
|
33
|
-
|
|
36
|
+
return reset if tenant.nil?
|
|
37
|
+
|
|
38
|
+
unless File.exist?(database_file(tenant))
|
|
39
|
+
raise TenantNotFound,
|
|
40
|
+
"The tenant #{environmentify(tenant)} cannot be found."
|
|
41
|
+
end
|
|
34
42
|
|
|
35
43
|
super database_file(tenant)
|
|
36
44
|
end
|
|
37
45
|
|
|
38
46
|
def create_tenant(tenant)
|
|
39
|
-
|
|
40
|
-
|
|
47
|
+
if File.exist?(database_file(tenant))
|
|
48
|
+
raise TenantExists,
|
|
49
|
+
"The tenant #{environmentify(tenant)} already exists."
|
|
50
|
+
end
|
|
41
51
|
|
|
42
52
|
begin
|
|
43
53
|
f = File.new(database_file(tenant), File::CREAT)
|
|
@@ -46,7 +56,7 @@ module Apartment
|
|
|
46
56
|
end
|
|
47
57
|
end
|
|
48
58
|
|
|
49
|
-
|
|
59
|
+
private
|
|
50
60
|
|
|
51
61
|
def database_file(tenant)
|
|
52
62
|
"#{@default_dir}/#{environmentify(tenant)}.sqlite3"
|
data/lib/apartment/console.rb
CHANGED
|
@@ -1,12 +1,44 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
# A workaraound to get `reload!` to also call Apartment::Tenant.init
|
|
2
4
|
# This is unfortunate, but I haven't figured out how to hook into the reload process *after* files are reloaded
|
|
3
5
|
|
|
4
6
|
# reloads the environment
|
|
5
|
-
def reload!(print=true)
|
|
6
|
-
|
|
7
|
+
def reload!(print = true)
|
|
8
|
+
# rubocop:disable Rails/Output
|
|
9
|
+
puts 'Reloading...' if print
|
|
10
|
+
# rubocop:enable Rails/Output
|
|
11
|
+
|
|
7
12
|
# This triggers the to_prepare callbacks
|
|
8
|
-
ActionDispatch::Callbacks.new(
|
|
13
|
+
ActionDispatch::Callbacks.new(proc {}).call({})
|
|
9
14
|
# Manually init Apartment again once classes are reloaded
|
|
10
15
|
Apartment::Tenant.init
|
|
11
16
|
true
|
|
12
17
|
end
|
|
18
|
+
|
|
19
|
+
def st(schema_name = nil)
|
|
20
|
+
if schema_name.nil?
|
|
21
|
+
# rubocop:disable Rails/Output
|
|
22
|
+
tenant_list.each { |t| puts t }
|
|
23
|
+
# rubocop:enable Rails/Output
|
|
24
|
+
elsif tenant_list.include? schema_name
|
|
25
|
+
Apartment::Tenant.switch!(schema_name)
|
|
26
|
+
else
|
|
27
|
+
# rubocop:disable Rails/Output
|
|
28
|
+
puts "Tenant #{schema_name} is not part of the tenant list"
|
|
29
|
+
# rubocop:enable Rails/Output
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def tenant_list
|
|
34
|
+
tenant_list = [Apartment.default_tenant]
|
|
35
|
+
tenant_list += Apartment.tenant_names
|
|
36
|
+
tenant_list.uniq
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def tenant_info_msg
|
|
40
|
+
# rubocop:disable Rails/Output
|
|
41
|
+
puts "Available Tenants: #{tenant_list}\n"
|
|
42
|
+
puts "Use `st 'tenant'` to switch tenants & `tenant_list` to see list\n"
|
|
43
|
+
# rubocop:enable Rails/Output
|
|
44
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'console'
|
|
4
|
+
|
|
5
|
+
module Apartment
|
|
6
|
+
module CustomConsole
|
|
7
|
+
begin
|
|
8
|
+
require 'pry-rails'
|
|
9
|
+
rescue LoadError
|
|
10
|
+
# rubocop:disable Rails/Output
|
|
11
|
+
puts '[Failed to load pry-rails] If you want to use Apartment custom prompt you need to add pry-rails to your gemfile'
|
|
12
|
+
# rubocop:enable Rails/Output
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
desc = "Includes the current Rails environment and project folder name.\n" \
|
|
16
|
+
'[1] [project_name][Rails.env][Apartment::Tenant.current] pry(main)>'
|
|
17
|
+
|
|
18
|
+
prompt_procs = [
|
|
19
|
+
proc { |target_self, nest_level, pry| prompt_contents(pry, target_self, nest_level, '>') },
|
|
20
|
+
proc { |target_self, nest_level, pry| prompt_contents(pry, target_self, nest_level, '*') }
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
if Gem::Version.new(Pry::VERSION) >= Gem::Version.new('0.13')
|
|
24
|
+
Pry.config.prompt = Pry::Prompt.new 'ros', desc, prompt_procs
|
|
25
|
+
else
|
|
26
|
+
Pry::Prompt.add 'ros', desc, %w[> *] do |target_self, nest_level, pry, sep|
|
|
27
|
+
prompt_contents(pry, target_self, nest_level, sep)
|
|
28
|
+
end
|
|
29
|
+
Pry.config.prompt = Pry::Prompt[:ros][:value]
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
Pry.config.hooks.add_hook(:when_started, 'startup message') do
|
|
33
|
+
tenant_info_msg
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def self.prompt_contents(pry, target_self, nest_level, sep)
|
|
37
|
+
"[#{pry.input_ring.size}] [#{PryRails::Prompt.formatted_env}][#{Apartment::Tenant.current}] " \
|
|
38
|
+
"#{pry.config.prompt_name}(#{Pry.view_clip(target_self)})" \
|
|
39
|
+
"#{":#{nest_level}" unless nest_level.zero?}#{sep} "
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'apartment/elevators/generic'
|
|
2
4
|
|
|
3
5
|
module Apartment
|
|
@@ -8,14 +10,13 @@ module Apartment
|
|
|
8
10
|
# eg. example.com => example
|
|
9
11
|
# www.example.bc.ca => example
|
|
10
12
|
# a.example.bc.ca => a
|
|
11
|
-
#
|
|
13
|
+
#
|
|
12
14
|
#
|
|
13
15
|
class Domain < Generic
|
|
14
|
-
|
|
15
16
|
def parse_tenant_name(request)
|
|
16
17
|
return nil if request.host.blank?
|
|
17
18
|
|
|
18
|
-
request.host.match(/(www\.)?(?<sld>[^.]*)/)[
|
|
19
|
+
request.host.match(/(www\.)?(?<sld>[^.]*)/)['sld']
|
|
19
20
|
end
|
|
20
21
|
end
|
|
21
22
|
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'apartment/elevators/subdomain'
|
|
2
4
|
|
|
3
5
|
module Apartment
|
|
@@ -8,10 +10,9 @@ module Apartment
|
|
|
8
10
|
# - example1.domain.com => example1
|
|
9
11
|
# - example2.something.domain.com => example2
|
|
10
12
|
class FirstSubdomain < Subdomain
|
|
11
|
-
|
|
12
13
|
def parse_tenant_name(request)
|
|
13
14
|
super.split('.')[0] unless super.nil?
|
|
14
15
|
end
|
|
15
16
|
end
|
|
16
17
|
end
|
|
17
|
-
end
|
|
18
|
+
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'rack/request'
|
|
2
4
|
require 'apartment/tenant'
|
|
3
5
|
|
|
@@ -6,7 +8,6 @@ module Apartment
|
|
|
6
8
|
# Provides a rack based tenant switching solution based on request
|
|
7
9
|
#
|
|
8
10
|
class Generic
|
|
9
|
-
|
|
10
11
|
def initialize(app, processor = nil)
|
|
11
12
|
@app = app
|
|
12
13
|
@processor = processor || method(:parse_tenant_name)
|
|
@@ -24,8 +25,8 @@ module Apartment
|
|
|
24
25
|
end
|
|
25
26
|
end
|
|
26
27
|
|
|
27
|
-
def parse_tenant_name(
|
|
28
|
-
raise
|
|
28
|
+
def parse_tenant_name(_request)
|
|
29
|
+
raise 'Override'
|
|
29
30
|
end
|
|
30
31
|
end
|
|
31
32
|
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'apartment/elevators/generic'
|
|
2
4
|
|
|
3
5
|
module Apartment
|
|
@@ -16,15 +18,18 @@ module Apartment
|
|
|
16
18
|
@ignored_first_subdomains ||= []
|
|
17
19
|
end
|
|
18
20
|
|
|
21
|
+
# rubocop:disable Style/TrivialAccessors
|
|
19
22
|
def self.ignored_first_subdomains=(arg)
|
|
20
23
|
@ignored_first_subdomains = arg
|
|
21
24
|
end
|
|
25
|
+
# rubocop:enable Style/TrivialAccessors
|
|
22
26
|
|
|
23
27
|
def parse_tenant_name(request)
|
|
24
28
|
return nil if request.host.blank?
|
|
29
|
+
|
|
25
30
|
parts = request.host.split('.')
|
|
26
31
|
self.class.ignored_first_subdomains.include?(parts[0]) ? parts.drop(1).join('.') : request.host
|
|
27
32
|
end
|
|
28
33
|
end
|
|
29
34
|
end
|
|
30
|
-
end
|
|
35
|
+
end
|