apartment 0.24.3 → 0.25.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +3 -2
- data/Appraisals +7 -3
- data/HISTORY.md +8 -0
- data/README.md +76 -21
- data/TODO.md +2 -2
- data/apartment.gemspec +17 -1
- data/gemfiles/{rails3.2.gemfile → rails_3_2.gemfile} +5 -1
- data/gemfiles/{rails4.0.gemfile → rails_4_0.gemfile} +5 -1
- data/gemfiles/rails_4_1.gemfile +11 -0
- data/lib/apartment.rb +2 -2
- data/lib/apartment/adapters/abstract_adapter.rb +1 -1
- data/lib/apartment/adapters/jdbc_mysql_adapter.rb +2 -2
- data/lib/apartment/adapters/jdbc_postgresql_adapter.rb +1 -1
- data/lib/apartment/adapters/mysql2_adapter.rb +3 -7
- data/lib/apartment/adapters/postgis_adapter.rb +2 -4
- data/lib/apartment/adapters/postgresql_adapter.rb +93 -8
- data/lib/apartment/adapters/sqlite3_adapter.rb +1 -1
- data/lib/apartment/console.rb +2 -2
- data/lib/apartment/elevators/generic.rb +2 -2
- data/lib/apartment/migrator.rb +1 -1
- data/lib/apartment/railtie.rb +3 -3
- data/lib/apartment/{database.rb → tenant.rb} +10 -3
- data/lib/apartment/version.rb +1 -1
- data/lib/generators/apartment/install/templates/apartment.rb +3 -0
- data/lib/tasks/apartment.rake +3 -3
- data/spec/adapters/jdbc_mysql_adapter_spec.rb +1 -1
- data/spec/adapters/jdbc_postgresql_adapter_spec.rb +1 -1
- data/spec/adapters/mysql2_adapter_spec.rb +2 -2
- data/spec/adapters/postgresql_adapter_spec.rb +17 -2
- data/spec/adapters/sqlite3_adapter_spec.rb +1 -1
- data/spec/apartment_spec.rb +4 -0
- data/spec/database_spec.rb +2 -2
- data/spec/examples/connection_adapter_examples.rb +1 -1
- data/spec/examples/schema_adapter_examples.rb +4 -4
- data/spec/integration/apartment_rake_integration_spec.rb +4 -4
- data/spec/integration/query_caching_spec.rb +7 -7
- data/spec/support/contexts.rb +1 -1
- data/spec/support/setup.rb +2 -2
- data/spec/unit/elevators/domain_spec.rb +1 -1
- data/spec/unit/elevators/generic_spec.rb +2 -2
- data/spec/unit/elevators/host_hash_spec.rb +1 -1
- data/spec/unit/elevators/subdomain_spec.rb +2 -2
- data/spec/unit/migrator_spec.rb +4 -4
- data/spec/unit/reloader_spec.rb +1 -1
- metadata +26 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7511a4af17aae3dc546bb1c76342c5b8301829c6
|
4
|
+
data.tar.gz: 819a8d11d7cf74fea4d67d9d7c364c92f6bf8aeb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 67dbe1ad054395e0466e785b9c3d81d17b7ff97147a2e04f76b1af951a806045bd774e6a9cf4c372860389d9b63919cb22d742c6165b1d25bbe60505a1b41d9d
|
7
|
+
data.tar.gz: 4fd680bc07c8e12f5a88fc143a1a26c09c289b6ae9c3a96296b5d3b48137cfd680132a6aa2b1ac28e3316d9350dae1fe43c9c718b49088cdf1ff18366dfafee6
|
data/.travis.yml
CHANGED
@@ -5,8 +5,9 @@ rvm:
|
|
5
5
|
- 2.1.0
|
6
6
|
- jruby-19mode
|
7
7
|
gemfile:
|
8
|
-
- gemfiles/
|
9
|
-
- gemfiles/
|
8
|
+
- gemfiles/rails_3_2.gemfile
|
9
|
+
- gemfiles/rails_4_0.gemfile
|
10
|
+
- gemfiles/rails_4_1.gemfile
|
10
11
|
bundler_args: --without local --verbose
|
11
12
|
before_install:
|
12
13
|
- gem install bundler -v '> 1.5.0'
|
data/Appraisals
CHANGED
data/HISTORY.md
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
# 0.25.0
|
2
|
+
* July 3, 2014
|
3
|
+
|
4
|
+
- [BREAKING CHANGE] - `Apartment::Database` is not deprecated in favour of
|
5
|
+
`Apartment::Tenant`
|
6
|
+
- ActiveRecord (and Rails) 4.1 now supported
|
7
|
+
- A new sql based adapter that dumps the schema using sql
|
8
|
+
|
1
9
|
# 0.24.3
|
2
10
|
* March 5, 2014
|
3
11
|
|
data/README.md
CHANGED
@@ -43,7 +43,7 @@ Before you can switch to a new apartment tenant, you will need to create it. Whe
|
|
43
43
|
you need to create a new tenant, you can run the following command:
|
44
44
|
|
45
45
|
```ruby
|
46
|
-
Apartment::
|
46
|
+
Apartment::Tenant.create('tenant_name')
|
47
47
|
```
|
48
48
|
|
49
49
|
If you're using the [prepend environment](https://github.com/influitive/apartment#handling-environments) config option or you AREN'T using Postgresql Schemas, this will create a tenant in the following format: "#{environment}\_tenant_name".
|
@@ -67,7 +67,7 @@ One can optionally use the full database creation instead if they want, though t
|
|
67
67
|
To switch tenants using Apartment, use the following command:
|
68
68
|
|
69
69
|
```ruby
|
70
|
-
Apartment::
|
70
|
+
Apartment::Tenant.switch('tenant_name')
|
71
71
|
```
|
72
72
|
|
73
73
|
When switch is called, all requests coming to ActiveRecord will be routed to the tenant
|
@@ -179,58 +179,101 @@ Rails will always access the 'public' tenant when accessing these models, but n
|
|
179
179
|
|
180
180
|
### Postgresql Schemas
|
181
181
|
|
182
|
-
|
182
|
+
## Providing a Different default_schema
|
183
183
|
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:
|
184
184
|
|
185
185
|
```ruby
|
186
186
|
config.default_schema = "some_other_schema"
|
187
187
|
```
|
188
188
|
|
189
|
-
With that set, all excluded models will use this schema as the table name prefix instead of `public` and `reset` on `Apartment::
|
189
|
+
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 also
|
190
190
|
|
191
|
-
|
191
|
+
## Persistent Schemas
|
192
192
|
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:
|
193
193
|
|
194
194
|
```ruby
|
195
195
|
config.persistent_schemas = ['some', 'other', 'schemas']
|
196
196
|
```
|
197
197
|
|
198
|
-
|
198
|
+
### Installing Extensions into Persistent Schemas
|
199
|
+
Persistent Schemas have numerous useful applications. [Hstore](http://www.postgresql.org/docs/9.1/static/hstore.html), for instance, is a popular storage engine for Postgresql. In order to use extensions such as Hstore, you have to install it to a specific schema and have that always in the `schema_search_path`.
|
200
|
+
|
201
|
+
When using extensions, keep in mind:
|
202
|
+
* Extensions can only be installed into one schema per database, so we will want to install it into a schema that is always available in the `schema_search_path`
|
203
|
+
* The schema and extension need to be created in the database *before* they are referenced in migrations, database.yml or apartment.
|
204
|
+
* There does not seem to be a way to create the schema and extension using standard rails migrations.
|
205
|
+
* Rails db:test:prepare deletes and recreates the database, so it needs to be easy for the extension schema to be recreated here.
|
206
|
+
|
207
|
+
#### 1. Ensure the extensions schema is created when the database is created
|
199
208
|
|
200
209
|
```ruby
|
201
|
-
#
|
202
|
-
|
203
|
-
|
204
|
-
|
210
|
+
# lib/tasks/db_enhancements.rake
|
211
|
+
|
212
|
+
####### Important information ####################
|
213
|
+
# This file is used to setup a shared extensions #
|
214
|
+
# within a dedicated schema. This gives us the #
|
215
|
+
# advantage of only needing to enable extensions #
|
216
|
+
# in one place. #
|
217
|
+
# #
|
218
|
+
# This task should be run AFTER db:create but #
|
219
|
+
# BEFORE db:migrate. #
|
220
|
+
##################################################
|
221
|
+
|
222
|
+
|
223
|
+
namespace :db do
|
224
|
+
desc 'Also create shared_extensions Schema'
|
225
|
+
task :extensions => :environment do
|
226
|
+
# Create Schema
|
227
|
+
ActiveRecord::Base.connection.execute 'CREATE SCHEMA IF NOT EXISTS shared_extensions;'
|
228
|
+
# Enable Hstore
|
229
|
+
ActiveRecord::Base.connection.execute 'CREATE EXTENSION IF NOT EXISTS HSTORE SCHEMA shared_extensions;'
|
230
|
+
# Enable UUID-OSSP
|
231
|
+
ActiveRecord::Base.connection.execute 'CREATE EXTENSION IF NOT EXISTS "uuid-ossp" SCHEMA shared_extensions;'
|
232
|
+
end
|
233
|
+
end
|
205
234
|
|
206
|
-
|
207
|
-
|
208
|
-
|
235
|
+
Rake::Task["db:create"].enhance do
|
236
|
+
Rake::Task["db:extensions"].invoke
|
237
|
+
end
|
209
238
|
|
210
|
-
|
239
|
+
Rake::Task["db:test:purge"].enhance do
|
240
|
+
Rake::Task["db:extensions"].invoke
|
241
|
+
end
|
242
|
+
```
|
211
243
|
|
212
|
-
|
244
|
+
#### 2. Ensure the schema is in Rails' default connection
|
213
245
|
|
214
|
-
Next, your `database.yml` file must mimic what you've set for your default and persistent schemas in Apartment. When you run migrataions with Rails, it won't know about the
|
246
|
+
Next, your `database.yml` file must mimic what you've set for your default and persistent schemas in Apartment. When you run migrataions with Rails, it won't know about the extensions schema because Apartment isn't injected into the default connection, it's done on a per-request basis, therefore Rails doesn't know about `hstore` or `uuid-ossp` during migrations. To do so, add the following to your `database.yml` for all environments
|
215
247
|
|
216
248
|
```yaml
|
217
249
|
# database.yml
|
218
250
|
...
|
219
251
|
adapter: postgresql
|
220
|
-
schema_search_path: "public,
|
252
|
+
schema_search_path: "public,shared_extensions"
|
221
253
|
...
|
222
254
|
```
|
223
255
|
|
224
|
-
This would be for a config with `default_schema` set to `public` and `persistent_schemas` set to `['
|
256
|
+
This would be for a config with `default_schema` 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/427). For older Rails versions Heroku regenerates a completely different `database.yml` for each deploy and your predefined `schema_search_path` will be deleted. ActiveRecord's `schema_search_path` will be the default `\"$user\",public`.
|
257
|
+
|
258
|
+
#### 3. Ensure the schema is in the apartment config
|
259
|
+
```ruby
|
260
|
+
# config/initializers/apartment.rb
|
261
|
+
...
|
262
|
+
config.persistent_schemas = ['shared_extensions']
|
263
|
+
...
|
264
|
+
```
|
225
265
|
|
266
|
+
#### Alternative: Creating schema by default
|
226
267
|
Another way that we've successfully configured hstore for our applications is to add it into the
|
227
268
|
postgresql template1 database so that every tenant that gets created has it by default.
|
228
269
|
|
270
|
+
One caveat with this approach is that it can interfere with other projects in development using the same extensions and template, but not using apartment with this approach.
|
271
|
+
|
229
272
|
You can do so using a command like so
|
230
273
|
|
231
274
|
```bash
|
232
|
-
psql -U postgres -d template1 -c "CREATE SCHEMA
|
233
|
-
psql -U postgres -d template1 -c "CREATE EXTENSION IF NOT EXISTS hstore SCHEMA
|
275
|
+
psql -U postgres -d template1 -c "CREATE SCHEMA shared_extensions AUTHORIZATION some_username;"
|
276
|
+
psql -U postgres -d template1 -c "CREATE EXTENSION IF NOT EXISTS hstore SCHEMA shared_extensions;"
|
234
277
|
```
|
235
278
|
|
236
279
|
The *ideal* setup would actually be to install `hstore` into the `public` schema and leave the public
|
@@ -238,6 +281,18 @@ schema in the `search_path` at all times. We won't be able to do this though unt
|
|
238
281
|
also contain the tenanted tables, which is an open issue with no real milestone to be completed.
|
239
282
|
Happy to accept PR's on the matter.
|
240
283
|
|
284
|
+
#### Alternative: Creating new schemas by using raw SQL dumps
|
285
|
+
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 respresented in `schema.rb`, like materialized views etc.
|
286
|
+
|
287
|
+
This only applies while using postgres adapter and `config.use_schemas` is set to `true`.
|
288
|
+
(Note: this option doesn't use `db/structure.sql`, it creates SQL dump by executing `pg_dump`)
|
289
|
+
|
290
|
+
Enable this option with:
|
291
|
+
```ruby
|
292
|
+
config.use_sql = true
|
293
|
+
```
|
294
|
+
|
295
|
+
|
241
296
|
### Managing Migrations
|
242
297
|
|
243
298
|
In order to migrate all of your tenants (or posgresql schemas) you need to provide a list
|
@@ -258,7 +313,7 @@ You can then migrate your tenants using the normal rake task:
|
|
258
313
|
rake db:migrate
|
259
314
|
```
|
260
315
|
|
261
|
-
This just invokes `Apartment::
|
316
|
+
This just invokes `Apartment::Tenant.migrate(#{tenant_name})` for each tenant name supplied
|
262
317
|
from `Apartment.tenant_names`
|
263
318
|
|
264
319
|
Note that you can disable the default migrating of all tenants with `db:migrate` by setting
|
data/TODO.md
CHANGED
@@ -19,9 +19,9 @@
|
|
19
19
|
|
20
20
|
This should ensure that going forward nothing breaks, and we should *ideally* be able to randomize the test order
|
21
21
|
|
22
|
-
2.
|
22
|
+
2. <del>`Apartment::Database` is the wrong abstraction. When dealing with a multi-tenanted system, users shouldn't thing about 'Databases', they should
|
23
23
|
think about Tenants. I proprose that we deprecate the `Apartment::Database` constant in favour of `Apartment::Tenant` for a nicer abstraction. See
|
24
|
-
http://myronmars.to/n/dev-blog/2011/09/deprecating-constants-and-classes-in-ruby for ideas on how to achieve this
|
24
|
+
http://myronmars.to/n/dev-blog/2011/09/deprecating-constants-and-classes-in-ruby for ideas on how to achieve this.</del>
|
25
25
|
|
26
26
|
4. Apartment::Database.process should be deprecated in favour of just passing a block to `switch`
|
27
27
|
5. Apartment::Database.switch should be renamed to switch! to indicate that using it on its own has side effects
|
data/apartment.gemspec
CHANGED
@@ -18,7 +18,23 @@ Gem::Specification.new do |s|
|
|
18
18
|
s.homepage = %q{https://github.com/influitive/apartment}
|
19
19
|
s.licenses = ["MIT"]
|
20
20
|
|
21
|
-
s.
|
21
|
+
s.post_install_message = <<-MSG
|
22
|
+
********************************
|
23
|
+
|
24
|
+
Apartment Deprecation Warning
|
25
|
+
|
26
|
+
`Apartment::Database` has been deprecated in favour of `Apartment::Tenant`.
|
27
|
+
Please update your application to use the new constant as it is a more
|
28
|
+
appropriate abstraction.
|
29
|
+
|
30
|
+
To further this, DatabaseNotFound, SchemaNotFound, DatabaseExists and
|
31
|
+
SchemaExists exceptions will all be removed, you should instead use
|
32
|
+
TenantNotFound and TenantExists to catch any exceptions.
|
33
|
+
|
34
|
+
********************************
|
35
|
+
MSG
|
36
|
+
|
37
|
+
s.add_dependency 'activerecord', '>= 3.1.2', '< 4.2' # must be >= 3.1.2 due to bug in prepared_statements
|
22
38
|
s.add_dependency 'rack', '>= 1.3.6'
|
23
39
|
|
24
40
|
s.add_development_dependency 'appraisal'
|
data/lib/apartment.rb
CHANGED
@@ -2,7 +2,7 @@ require 'apartment/railtie' if defined?(Rails)
|
|
2
2
|
require 'active_support/core_ext/object/blank'
|
3
3
|
require 'forwardable'
|
4
4
|
require 'active_record'
|
5
|
-
require 'apartment/
|
5
|
+
require 'apartment/tenant'
|
6
6
|
|
7
7
|
module Apartment
|
8
8
|
|
@@ -10,7 +10,7 @@ module Apartment
|
|
10
10
|
|
11
11
|
extend Forwardable
|
12
12
|
|
13
|
-
ACCESSOR_METHODS = [:use_schemas, :seed_after_create, :prepend_environment, :append_environment]
|
13
|
+
ACCESSOR_METHODS = [:use_schemas, :use_sql, :seed_after_create, :prepend_environment, :append_environment]
|
14
14
|
WRITER_METHODS = [:tenant_names, :database_schema_file, :excluded_models, :default_schema, :persistent_schemas, :connection_class, :tld_length, :db_migrate_tenants]
|
15
15
|
|
16
16
|
attr_accessor(*ACCESSOR_METHODS)
|
@@ -182,7 +182,7 @@ module Apartment
|
|
182
182
|
# Exceptions to rescue from on db operations
|
183
183
|
#
|
184
184
|
def rescuable_exceptions
|
185
|
-
[ActiveRecord::
|
185
|
+
[ActiveRecord::ActiveRecordError] + [rescue_from].flatten
|
186
186
|
end
|
187
187
|
|
188
188
|
# Extra exceptions to rescue from
|
@@ -2,7 +2,7 @@ require "apartment/adapters/abstract_jdbc_adapter"
|
|
2
2
|
|
3
3
|
module Apartment
|
4
4
|
|
5
|
-
module
|
5
|
+
module Tenant
|
6
6
|
def self.jdbc_mysql_adapter(config)
|
7
7
|
Adapters::JDBCMysqlAdapter.new config
|
8
8
|
end
|
@@ -22,7 +22,7 @@ module Apartment
|
|
22
22
|
def connect_to_new(database)
|
23
23
|
super
|
24
24
|
rescue DatabaseNotFound
|
25
|
-
Apartment::
|
25
|
+
Apartment::Tenant.reset
|
26
26
|
raise DatabaseNotFound, "Cannot find database #{environmentify(database)}"
|
27
27
|
end
|
28
28
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'apartment/adapters/abstract_adapter'
|
2
2
|
|
3
3
|
module Apartment
|
4
|
-
module
|
4
|
+
module Tenant
|
5
5
|
|
6
6
|
def self.mysql2_adapter(config)
|
7
7
|
Apartment.use_schemas ?
|
@@ -24,7 +24,7 @@ module Apartment
|
|
24
24
|
def connect_to_new(tenant = nil)
|
25
25
|
super
|
26
26
|
rescue Mysql2::Error
|
27
|
-
Apartment::
|
27
|
+
Apartment::Tenant.reset
|
28
28
|
raise DatabaseNotFound, "Cannot find tenant #{environmentify(tenant)}"
|
29
29
|
end
|
30
30
|
end
|
@@ -61,16 +61,12 @@ module Apartment
|
|
61
61
|
Apartment.connection.execute "use #{environmentify(tenant)}"
|
62
62
|
|
63
63
|
rescue ActiveRecord::StatementInvalid
|
64
|
-
Apartment::
|
64
|
+
Apartment::Tenant.reset
|
65
65
|
raise DatabaseNotFound, "Cannot find tenant #{environmentify(tenant)}"
|
66
66
|
end
|
67
67
|
|
68
68
|
def process_excluded_model(model)
|
69
69
|
model.constantize.tap do |klass|
|
70
|
-
# some models (such as delayed_job) seem to load and cache their column names before this,
|
71
|
-
# so would never get the default prefix, so reset first
|
72
|
-
klass.reset_column_information
|
73
|
-
|
74
70
|
# Ensure that if a schema *was* set, we override
|
75
71
|
table_name = klass.table_name.split('.', 2).last
|
76
72
|
|
@@ -3,12 +3,10 @@
|
|
3
3
|
require "apartment/adapters/postgresql_adapter"
|
4
4
|
|
5
5
|
module Apartment
|
6
|
-
module
|
6
|
+
module Tenant
|
7
7
|
|
8
8
|
def self.postgis_adapter(config)
|
9
|
-
|
10
|
-
Adapters::PostgresqlSchemaAdapter.new(config) :
|
11
|
-
Adapters::PostgresqlAdapter.new(config)
|
9
|
+
postgresql_adapter(config)
|
12
10
|
end
|
13
11
|
end
|
14
12
|
end
|
@@ -1,12 +1,13 @@
|
|
1
1
|
require 'apartment/adapters/abstract_adapter'
|
2
2
|
|
3
3
|
module Apartment
|
4
|
-
module
|
4
|
+
module Tenant
|
5
5
|
|
6
6
|
def self.postgresql_adapter(config)
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
adapter = Adapters::PostgresqlAdapter
|
8
|
+
adapter = Adapters::PostgresqlSchemaAdapter if Apartment.use_schemas
|
9
|
+
adapter = Adapters::PostgresqlSchemaFromSqlAdapter if Apartment.use_sql && Apartment.use_schemas
|
10
|
+
adapter.new(config)
|
10
11
|
end
|
11
12
|
end
|
12
13
|
|
@@ -55,10 +56,6 @@ module Apartment
|
|
55
56
|
def process_excluded_models
|
56
57
|
Apartment.excluded_models.each do |excluded_model|
|
57
58
|
excluded_model.constantize.tap do |klass|
|
58
|
-
# some models (such as delayed_job) seem to load and cache their column names before this,
|
59
|
-
# so would never get the default prefix, so reset first
|
60
|
-
klass.reset_column_information
|
61
|
-
|
62
59
|
# Ensure that if a schema *was* set, we override
|
63
60
|
table_name = klass.table_name.split('.', 2).last
|
64
61
|
|
@@ -116,5 +113,93 @@ module Apartment
|
|
116
113
|
[@current_tenant, Apartment.persistent_schemas].flatten
|
117
114
|
end
|
118
115
|
end
|
116
|
+
|
117
|
+
# Another Adapter for Postgresql when using schemas and SQL
|
118
|
+
class PostgresqlSchemaFromSqlAdapter < PostgresqlSchemaAdapter
|
119
|
+
|
120
|
+
PSQL_DUMP_BLACKLISTED_STATEMENTS= [
|
121
|
+
/SET search_path/i, # overridden later
|
122
|
+
/SET lock_timeout/i # new in postgresql 9.3
|
123
|
+
]
|
124
|
+
|
125
|
+
def import_database_schema
|
126
|
+
clone_pg_schema
|
127
|
+
copy_schema_migrations
|
128
|
+
end
|
129
|
+
|
130
|
+
private
|
131
|
+
|
132
|
+
# Clone default schema into new schema named after current tenant
|
133
|
+
#
|
134
|
+
def clone_pg_schema
|
135
|
+
pg_schema_sql = patch_search_path(pg_dump_schema)
|
136
|
+
Apartment.connection.execute(pg_schema_sql)
|
137
|
+
end
|
138
|
+
|
139
|
+
# Copy data from schema_migrations into new schema
|
140
|
+
#
|
141
|
+
def copy_schema_migrations
|
142
|
+
pg_migrations_data = patch_search_path(pg_dump_schema_migrations_data)
|
143
|
+
Apartment.connection.execute(pg_migrations_data)
|
144
|
+
end
|
145
|
+
|
146
|
+
# Dump postgres default schema
|
147
|
+
#
|
148
|
+
# @return {String} raw SQL contaning only postgres schema dump
|
149
|
+
#
|
150
|
+
def pg_dump_schema
|
151
|
+
dbname = ActiveRecord::Base.connection_config[:database]
|
152
|
+
default_schema = Apartment.default_schema
|
153
|
+
|
154
|
+
# Skip excluded tables? :/
|
155
|
+
# excluded_tables =
|
156
|
+
# collect_table_names(Apartment.excluded_models)
|
157
|
+
# .map! {|t| "-T #{t}"}
|
158
|
+
# .join(' ')
|
159
|
+
|
160
|
+
# `pg_dump -s -x -O -n #{default_schema} #{excluded_tables} #{dbname}`
|
161
|
+
|
162
|
+
`pg_dump -s -x -O -n #{default_schema} #{dbname}`
|
163
|
+
end
|
164
|
+
|
165
|
+
# Dump data from schema_migrations table
|
166
|
+
#
|
167
|
+
# @return {String} raw SQL contaning inserts with data from schema_migrations
|
168
|
+
#
|
169
|
+
def pg_dump_schema_migrations_data
|
170
|
+
`pg_dump -a --inserts -t schema_migrations -n #{Apartment.default_schema} bithub_development`
|
171
|
+
end
|
172
|
+
|
173
|
+
# Remove "SET search_path ..." line from SQL dump and prepend search_path set to current tenant
|
174
|
+
#
|
175
|
+
# @return {String} patched raw SQL dump
|
176
|
+
#
|
177
|
+
def patch_search_path(sql)
|
178
|
+
search_path = "SET search_path = #{self.current_tenant}, #{Apartment.default_schema};"
|
179
|
+
|
180
|
+
sql
|
181
|
+
.split("\n")
|
182
|
+
.select {|line| check_input_against_regexps(line, PSQL_DUMP_BLACKLISTED_STATEMENTS).empty?}
|
183
|
+
.prepend(search_path)
|
184
|
+
.join("\n")
|
185
|
+
end
|
186
|
+
|
187
|
+
# Checks if any of regexps matches against input
|
188
|
+
#
|
189
|
+
def check_input_against_regexps(input, regexps)
|
190
|
+
regexps.select {|c| input.match c}
|
191
|
+
end
|
192
|
+
|
193
|
+
# Collect table names from AR Models
|
194
|
+
#
|
195
|
+
def collect_table_names(models)
|
196
|
+
models.map do |m|
|
197
|
+
m.constantize.table_name
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
end
|
202
|
+
|
203
|
+
|
119
204
|
end
|
120
205
|
end
|
data/lib/apartment/console.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# A workaraound to get `reload!` to also call Apartment::
|
1
|
+
# A workaraound to get `reload!` to also call Apartment::Tenant.init
|
2
2
|
# This is unfortunate, but I haven't figured out how to hook into the reload process *after* files are reloaded
|
3
3
|
|
4
4
|
# reloads the environment
|
@@ -7,6 +7,6 @@ def reload!(print=true)
|
|
7
7
|
# This triggers the to_prepare callbacks
|
8
8
|
ActionDispatch::Callbacks.new(Proc.new {}).call({})
|
9
9
|
# Manually init Apartment again once classes are reloaded
|
10
|
-
Apartment::
|
10
|
+
Apartment::Tenant.init
|
11
11
|
true
|
12
12
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
require 'rack/request'
|
2
|
-
require 'apartment/
|
2
|
+
require 'apartment/tenant'
|
3
3
|
|
4
4
|
module Apartment
|
5
5
|
module Elevators
|
@@ -17,7 +17,7 @@ module Apartment
|
|
17
17
|
|
18
18
|
database = @processor.call(request)
|
19
19
|
|
20
|
-
Apartment::
|
20
|
+
Apartment::Tenant.switch database if database
|
21
21
|
|
22
22
|
@app.call(env)
|
23
23
|
end
|
data/lib/apartment/migrator.rb
CHANGED
data/lib/apartment/railtie.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
require 'rails'
|
2
|
-
require 'apartment/
|
2
|
+
require 'apartment/tenant'
|
3
3
|
require 'apartment/reloader'
|
4
4
|
|
5
5
|
module Apartment
|
@@ -28,7 +28,7 @@ module Apartment
|
|
28
28
|
# See the middleware/console declarations below to help with this. Hope to fix that soon.
|
29
29
|
#
|
30
30
|
config.to_prepare do
|
31
|
-
Apartment::
|
31
|
+
Apartment::Tenant.init
|
32
32
|
end
|
33
33
|
|
34
34
|
#
|
@@ -50,7 +50,7 @@ module Apartment
|
|
50
50
|
app.config.middleware.use "Apartment::Reloader"
|
51
51
|
end
|
52
52
|
|
53
|
-
# Overrides reload! to also call Apartment::
|
53
|
+
# Overrides reload! to also call Apartment::Tenant.init as well so that the reloaded classes have the proper table_names
|
54
54
|
console do
|
55
55
|
require 'apartment/console'
|
56
56
|
end
|
@@ -3,7 +3,7 @@ require 'forwardable'
|
|
3
3
|
module Apartment
|
4
4
|
# The main entry point to Apartment functions
|
5
5
|
#
|
6
|
-
module
|
6
|
+
module Tenant
|
7
7
|
|
8
8
|
extend self
|
9
9
|
extend Forwardable
|
@@ -60,7 +60,14 @@ module Apartment
|
|
60
60
|
# Fetch the rails database configuration
|
61
61
|
#
|
62
62
|
def config
|
63
|
-
@config ||=
|
63
|
+
@config ||= (ActiveRecord::Base.configurations[Rails.env] ||
|
64
|
+
Rails.application.config.database_configuration[Rails.env]).symbolize_keys
|
64
65
|
end
|
65
66
|
end
|
66
|
-
|
67
|
+
|
68
|
+
def self.const_missing(const_name)
|
69
|
+
super unless const_name == :Database
|
70
|
+
warn "`Apartment::Database` has been deprecated. Use `Apartment::Tenant` instead."
|
71
|
+
Tenant
|
72
|
+
end
|
73
|
+
end
|
data/lib/apartment/version.rb
CHANGED
@@ -22,6 +22,9 @@ Apartment.configure do |config|
|
|
22
22
|
# use postgres schemas?
|
23
23
|
config.use_schemas = true
|
24
24
|
|
25
|
+
# use raw SQL dumps for creating postgres schemas? (only appies with use_schemas set to true)
|
26
|
+
#config.use_sql = true
|
27
|
+
|
25
28
|
# configure persistent schemas (E.g. hstore )
|
26
29
|
# config.persistent_schemas = %w{ hstore }
|
27
30
|
|
data/lib/tasks/apartment.rake
CHANGED
@@ -7,7 +7,7 @@ apartment_namespace = namespace :apartment do
|
|
7
7
|
tenants.each do |tenant|
|
8
8
|
begin
|
9
9
|
puts("Creating #{tenant} tenant")
|
10
|
-
quietly { Apartment::
|
10
|
+
quietly { Apartment::Tenant.create(tenant) }
|
11
11
|
rescue Apartment::TenantExists => e
|
12
12
|
puts e.message
|
13
13
|
end
|
@@ -35,8 +35,8 @@ apartment_namespace = namespace :apartment do
|
|
35
35
|
tenants.each do |tenant|
|
36
36
|
begin
|
37
37
|
puts("Seeding #{tenant} tenant")
|
38
|
-
Apartment::
|
39
|
-
Apartment::
|
38
|
+
Apartment::Tenant.process(tenant) do
|
39
|
+
Apartment::Tenant.seed
|
40
40
|
end
|
41
41
|
rescue Apartment::TenantNotFound => e
|
42
42
|
puts e.message
|
@@ -5,7 +5,7 @@ if defined?(JRUBY_VERSION)
|
|
5
5
|
|
6
6
|
describe Apartment::Adapters::JDBCMysqlAdapter, database: :mysql do
|
7
7
|
|
8
|
-
subject { Apartment::
|
8
|
+
subject { Apartment::Tenant.jdbc_mysql_adapter config.symbolize_keys }
|
9
9
|
|
10
10
|
def tenant_names
|
11
11
|
ActiveRecord::Base.connection.execute("SELECT schema_name FROM information_schema.schemata").collect { |row| row['schema_name'] }
|
@@ -5,7 +5,7 @@ if defined?(JRUBY_VERSION)
|
|
5
5
|
|
6
6
|
describe Apartment::Adapters::JDBCPostgresqlAdapter, database: :postgresql do
|
7
7
|
|
8
|
-
subject { Apartment::
|
8
|
+
subject { Apartment::Tenant.jdbc_postgresql_adapter config.symbolize_keys }
|
9
9
|
|
10
10
|
context "using schemas" do
|
11
11
|
|
@@ -4,7 +4,7 @@ require 'apartment/adapters/mysql2_adapter'
|
|
4
4
|
describe Apartment::Adapters::Mysql2Adapter, database: :mysql do
|
5
5
|
unless defined?(JRUBY_VERSION)
|
6
6
|
|
7
|
-
subject(:adapter){ Apartment::
|
7
|
+
subject(:adapter){ Apartment::Tenant.mysql2_adapter config }
|
8
8
|
|
9
9
|
def tenant_names
|
10
10
|
ActiveRecord::Base.connection.execute("SELECT schema_name FROM information_schema.schemata").collect { |row| row[0] }
|
@@ -31,7 +31,7 @@ describe Apartment::Adapters::Mysql2Adapter, database: :mysql do
|
|
31
31
|
end
|
32
32
|
|
33
33
|
it "should process model exclusions" do
|
34
|
-
Apartment::
|
34
|
+
Apartment::Tenant.init
|
35
35
|
|
36
36
|
Company.table_name.should == "#{default_tenant}.companies"
|
37
37
|
end
|
@@ -4,9 +4,9 @@ require 'apartment/adapters/postgresql_adapter'
|
|
4
4
|
describe Apartment::Adapters::PostgresqlAdapter, database: :postgresql do
|
5
5
|
unless defined?(JRUBY_VERSION)
|
6
6
|
|
7
|
-
subject{ Apartment::
|
7
|
+
subject{ Apartment::Tenant.postgresql_adapter config }
|
8
8
|
|
9
|
-
context "using schemas" do
|
9
|
+
context "using schemas with schema.rb" do
|
10
10
|
|
11
11
|
before{ Apartment.use_schemas = true }
|
12
12
|
|
@@ -21,6 +21,21 @@ describe Apartment::Adapters::PostgresqlAdapter, database: :postgresql do
|
|
21
21
|
it_should_behave_like "a schema based apartment adapter"
|
22
22
|
end
|
23
23
|
|
24
|
+
context "using schemas with SQL dump" do
|
25
|
+
|
26
|
+
before{ Apartment.use_schemas = true; Apartment.use_sql = true }
|
27
|
+
|
28
|
+
# Not sure why, but somehow using let(:tenant_names) memoizes for the whole example group, not just each test
|
29
|
+
def tenant_names
|
30
|
+
ActiveRecord::Base.connection.execute("SELECT nspname FROM pg_namespace;").collect { |row| row['nspname'] }
|
31
|
+
end
|
32
|
+
|
33
|
+
let(:default_tenant) { subject.process { ActiveRecord::Base.connection.schema_search_path.gsub('"', '') } }
|
34
|
+
|
35
|
+
it_should_behave_like "a generic apartment adapter"
|
36
|
+
it_should_behave_like "a schema based apartment adapter"
|
37
|
+
end
|
38
|
+
|
24
39
|
context "using connections" do
|
25
40
|
|
26
41
|
before{ Apartment.use_schemas = false }
|
@@ -4,7 +4,7 @@ require 'apartment/adapters/sqlite3_adapter'
|
|
4
4
|
describe Apartment::Adapters::Sqlite3Adapter, database: :sqlite do
|
5
5
|
unless defined?(JRUBY_VERSION)
|
6
6
|
|
7
|
-
subject{ Apartment::
|
7
|
+
subject{ Apartment::Tenant.sqlite3_adapter config }
|
8
8
|
|
9
9
|
context "using connections" do
|
10
10
|
def tenant_names
|
data/spec/apartment_spec.rb
CHANGED
data/spec/database_spec.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe Apartment::
|
3
|
+
describe Apartment::Tenant do
|
4
4
|
context "using mysql", database: :mysql do
|
5
5
|
|
6
6
|
before do
|
@@ -77,7 +77,7 @@ describe Apartment::Database do
|
|
77
77
|
subject.stub(:config).and_return config.merge(:adapter => 'unknown')
|
78
78
|
|
79
79
|
expect {
|
80
|
-
Apartment::
|
80
|
+
Apartment::Tenant.adapter
|
81
81
|
}.to raise_error
|
82
82
|
end
|
83
83
|
|
@@ -10,7 +10,7 @@ shared_examples_for "a connection based apartment adapter" do
|
|
10
10
|
Apartment.configure do |config|
|
11
11
|
config.excluded_models = ["Company"]
|
12
12
|
end
|
13
|
-
Apartment::
|
13
|
+
Apartment::Tenant.init
|
14
14
|
|
15
15
|
Company.connection.object_id.should_not == ActiveRecord::Base.connection.object_id
|
16
16
|
end
|
@@ -16,7 +16,7 @@ shared_examples_for "a schema based apartment adapter" do
|
|
16
16
|
end
|
17
17
|
|
18
18
|
it "should process model exclusions" do
|
19
|
-
Apartment::
|
19
|
+
Apartment::Tenant.init
|
20
20
|
|
21
21
|
Company.table_name.should == "public.companies"
|
22
22
|
end
|
@@ -24,13 +24,13 @@ shared_examples_for "a schema based apartment adapter" do
|
|
24
24
|
context "with a default_schema", :default_schema => true do
|
25
25
|
|
26
26
|
it "should set the proper table_name on excluded_models" do
|
27
|
-
Apartment::
|
27
|
+
Apartment::Tenant.init
|
28
28
|
|
29
29
|
Company.table_name.should == "#{default_schema}.companies"
|
30
30
|
end
|
31
31
|
|
32
32
|
it 'sets the search_path correctly' do
|
33
|
-
Apartment::
|
33
|
+
Apartment::Tenant.init
|
34
34
|
|
35
35
|
User.connection.schema_search_path.should =~ %r|#{default_schema}|
|
36
36
|
end
|
@@ -38,7 +38,7 @@ shared_examples_for "a schema based apartment adapter" do
|
|
38
38
|
|
39
39
|
context "persistent_schemas", :persistent_schemas => true do
|
40
40
|
it "sets the persistent schemas in the schema_search_path" do
|
41
|
-
Apartment::
|
41
|
+
Apartment::Tenant.init
|
42
42
|
connection.schema_search_path.should end_with persistent_schemas.map { |schema| %{"#{schema}"} }.join(', ')
|
43
43
|
end
|
44
44
|
end
|
@@ -21,7 +21,7 @@ describe "apartment rake tasks", database: :postgresql do
|
|
21
21
|
config.excluded_models = ["Company"]
|
22
22
|
config.tenant_names = lambda{ Company.pluck(:database) }
|
23
23
|
end
|
24
|
-
Apartment::
|
24
|
+
Apartment::Tenant.reload!(config)
|
25
25
|
|
26
26
|
# fix up table name of shared/excluded models
|
27
27
|
Company.table_name = 'public.companies'
|
@@ -37,13 +37,13 @@ describe "apartment rake tasks", database: :postgresql do
|
|
37
37
|
|
38
38
|
before do
|
39
39
|
db_names.collect do |db_name|
|
40
|
-
Apartment::
|
40
|
+
Apartment::Tenant.create(db_name)
|
41
41
|
Company.create :database => db_name
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
45
45
|
after do
|
46
|
-
db_names.each{ |db| Apartment::
|
46
|
+
db_names.each{ |db| Apartment::Tenant.drop(db) }
|
47
47
|
Company.delete_all
|
48
48
|
end
|
49
49
|
|
@@ -65,7 +65,7 @@ describe "apartment rake tasks", database: :postgresql do
|
|
65
65
|
|
66
66
|
describe "apartment:seed" do
|
67
67
|
it "should seed all databases" do
|
68
|
-
Apartment::
|
68
|
+
Apartment::Tenant.should_receive(:seed).exactly(company_count).times
|
69
69
|
|
70
70
|
@rake['apartment:seed'].invoke
|
71
71
|
end
|
@@ -10,32 +10,32 @@ describe 'query caching' do
|
|
10
10
|
config.use_schemas = true
|
11
11
|
end
|
12
12
|
|
13
|
-
Apartment::
|
13
|
+
Apartment::Tenant.reload!(config)
|
14
14
|
|
15
15
|
db_names.each do |db_name|
|
16
|
-
Apartment::
|
16
|
+
Apartment::Tenant.create(db_name)
|
17
17
|
Company.create database: db_name
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
21
|
after do
|
22
|
-
db_names.each{ |db| Apartment::
|
23
|
-
Apartment::
|
22
|
+
db_names.each{ |db| Apartment::Tenant.drop(db) }
|
23
|
+
Apartment::Tenant.reset
|
24
24
|
Company.delete_all
|
25
25
|
end
|
26
26
|
|
27
27
|
it 'clears the ActiveRecord::QueryCache after switching databases' do
|
28
28
|
db_names.each do |db_name|
|
29
|
-
Apartment::
|
29
|
+
Apartment::Tenant.switch db_name
|
30
30
|
User.create! name: db_name
|
31
31
|
end
|
32
32
|
|
33
33
|
ActiveRecord::Base.connection.enable_query_cache!
|
34
34
|
|
35
|
-
Apartment::
|
35
|
+
Apartment::Tenant.switch db_names.first
|
36
36
|
User.find_by_name(db_names.first).name.should == db_names.first
|
37
37
|
|
38
|
-
Apartment::
|
38
|
+
Apartment::Tenant.switch db_names.last
|
39
39
|
User.find_by_name(db_names.first).should be_nil
|
40
40
|
end
|
41
41
|
end
|
data/spec/support/contexts.rb
CHANGED
@@ -20,7 +20,7 @@ shared_context "elevators", elevator: true do
|
|
20
20
|
let(:company1) { mock_model(Company, database: db1).as_null_object }
|
21
21
|
let(:company2) { mock_model(Company, database: db2).as_null_object }
|
22
22
|
|
23
|
-
let(:api) { Apartment::
|
23
|
+
let(:api) { Apartment::Tenant }
|
24
24
|
|
25
25
|
before do
|
26
26
|
Apartment.reset # reset all config
|
data/spec/support/setup.rb
CHANGED
@@ -15,7 +15,7 @@ module Apartment
|
|
15
15
|
# Otherwise these actually get run after test defined hooks
|
16
16
|
around(:each) do |example|
|
17
17
|
# before
|
18
|
-
Apartment::
|
18
|
+
Apartment::Tenant.reload!(config)
|
19
19
|
ActiveRecord::Base.establish_connection config
|
20
20
|
|
21
21
|
example.run
|
@@ -33,7 +33,7 @@ module Apartment
|
|
33
33
|
end
|
34
34
|
|
35
35
|
Apartment.reset
|
36
|
-
Apartment::
|
36
|
+
Apartment::Tenant.reload!
|
37
37
|
end
|
38
38
|
end
|
39
39
|
end
|
@@ -24,7 +24,7 @@ describe Apartment::Elevators::Domain do
|
|
24
24
|
|
25
25
|
describe "#call" do
|
26
26
|
it "switches to the proper tenant" do
|
27
|
-
Apartment::
|
27
|
+
Apartment::Tenant.should_receive(:switch).with('example')
|
28
28
|
|
29
29
|
elevator.call('HTTP_HOST' => 'www.example.com')
|
30
30
|
end
|
@@ -15,7 +15,7 @@ describe Apartment::Elevators::Generic do
|
|
15
15
|
it "calls the processor if given" do
|
16
16
|
elevator = described_class.new(Proc.new{}, Proc.new{'tenant1'})
|
17
17
|
|
18
|
-
Apartment::
|
18
|
+
Apartment::Tenant.should_receive(:switch).with('tenant1')
|
19
19
|
|
20
20
|
elevator.call('HTTP_HOST' => 'foo.bar.com')
|
21
21
|
end
|
@@ -29,7 +29,7 @@ describe Apartment::Elevators::Generic do
|
|
29
29
|
it "switches to the parsed db_name" do
|
30
30
|
elevator = MyElevator.new(Proc.new{})
|
31
31
|
|
32
|
-
Apartment::
|
32
|
+
Apartment::Tenant.should_receive(:switch).with('tenant2')
|
33
33
|
|
34
34
|
elevator.call('HTTP_HOST' => 'foo.bar.com')
|
35
35
|
end
|
@@ -24,7 +24,7 @@ describe Apartment::Elevators::HostHash do
|
|
24
24
|
|
25
25
|
describe "#call" do
|
26
26
|
it "switches to the proper tenant" do
|
27
|
-
Apartment::
|
27
|
+
Apartment::Tenant.should_receive(:switch).with('example_tenant')
|
28
28
|
|
29
29
|
elevator.call('HTTP_HOST' => 'example.com')
|
30
30
|
end
|
@@ -39,14 +39,14 @@ describe Apartment::Elevators::Subdomain do
|
|
39
39
|
|
40
40
|
describe "#call" do
|
41
41
|
it "switches to the proper tenant" do
|
42
|
-
Apartment::
|
42
|
+
Apartment::Tenant.should_receive(:switch).with('tenant1')
|
43
43
|
elevator.call('HTTP_HOST' => 'tenant1.example.com')
|
44
44
|
end
|
45
45
|
|
46
46
|
it "ignores excluded subdomains" do
|
47
47
|
described_class.excluded_subdomains = %w{foo}
|
48
48
|
|
49
|
-
Apartment::
|
49
|
+
Apartment::Tenant.should_not_receive(:switch)
|
50
50
|
|
51
51
|
elevator.call('HTTP_HOST' => 'foo.bar.com')
|
52
52
|
|
data/spec/unit/migrator_spec.rb
CHANGED
@@ -6,11 +6,11 @@ describe Apartment::Migrator do
|
|
6
6
|
let(:tenant){ Apartment::Test.next_db }
|
7
7
|
|
8
8
|
# Don't need a real switch here, just testing behaviour
|
9
|
-
before { Apartment::
|
9
|
+
before { Apartment::Tenant.adapter.stub(:connect_to_new) }
|
10
10
|
|
11
11
|
describe "::migrate" do
|
12
12
|
it "processes and migrates" do
|
13
|
-
expect(Apartment::
|
13
|
+
expect(Apartment::Tenant).to receive(:process).with(tenant).and_call_original
|
14
14
|
expect(ActiveRecord::Migrator).to receive(:migrate)
|
15
15
|
|
16
16
|
Apartment::Migrator.migrate(tenant)
|
@@ -19,7 +19,7 @@ describe Apartment::Migrator do
|
|
19
19
|
|
20
20
|
describe "::run" do
|
21
21
|
it "processes and runs" do
|
22
|
-
expect(Apartment::
|
22
|
+
expect(Apartment::Tenant).to receive(:process).with(tenant).and_call_original
|
23
23
|
expect(ActiveRecord::Migrator).to receive(:run).with(:up, anything, 1234)
|
24
24
|
|
25
25
|
Apartment::Migrator.run(:up, tenant, 1234)
|
@@ -28,7 +28,7 @@ describe Apartment::Migrator do
|
|
28
28
|
|
29
29
|
describe "::rollback" do
|
30
30
|
it "processes and rolls back" do
|
31
|
-
expect(Apartment::
|
31
|
+
expect(Apartment::Tenant).to receive(:process).with(tenant).and_call_original
|
32
32
|
expect(ActiveRecord::Migrator).to receive(:rollback).with(anything, 2)
|
33
33
|
|
34
34
|
Apartment::Migrator.rollback(tenant, 2)
|
data/spec/unit/reloader_spec.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: apartment
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.25.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryan Brunner
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-03
|
12
|
+
date: 2014-07-03 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activerecord
|
@@ -18,6 +18,9 @@ dependencies:
|
|
18
18
|
- - '>='
|
19
19
|
- !ruby/object:Gem::Version
|
20
20
|
version: 3.1.2
|
21
|
+
- - <
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: '4.2'
|
21
24
|
type: :runtime
|
22
25
|
prerelease: false
|
23
26
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -25,6 +28,9 @@ dependencies:
|
|
25
28
|
- - '>='
|
26
29
|
- !ruby/object:Gem::Version
|
27
30
|
version: 3.1.2
|
31
|
+
- - <
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '4.2'
|
28
34
|
- !ruby/object:Gem::Dependency
|
29
35
|
name: rack
|
30
36
|
requirement: !ruby/object:Gem::Requirement
|
@@ -174,8 +180,9 @@ files:
|
|
174
180
|
- Rakefile
|
175
181
|
- TODO.md
|
176
182
|
- apartment.gemspec
|
177
|
-
- gemfiles/
|
178
|
-
- gemfiles/
|
183
|
+
- gemfiles/rails_3_2.gemfile
|
184
|
+
- gemfiles/rails_4_0.gemfile
|
185
|
+
- gemfiles/rails_4_1.gemfile
|
179
186
|
- lib/apartment.rb
|
180
187
|
- lib/apartment/adapters/abstract_adapter.rb
|
181
188
|
- lib/apartment/adapters/abstract_jdbc_adapter.rb
|
@@ -186,7 +193,6 @@ files:
|
|
186
193
|
- lib/apartment/adapters/postgresql_adapter.rb
|
187
194
|
- lib/apartment/adapters/sqlite3_adapter.rb
|
188
195
|
- lib/apartment/console.rb
|
189
|
-
- lib/apartment/database.rb
|
190
196
|
- lib/apartment/elevators/domain.rb
|
191
197
|
- lib/apartment/elevators/first_subdomain.rb
|
192
198
|
- lib/apartment/elevators/generic.rb
|
@@ -196,6 +202,7 @@ files:
|
|
196
202
|
- lib/apartment/railtie.rb
|
197
203
|
- lib/apartment/reloader.rb
|
198
204
|
- lib/apartment/tasks/enhancements.rb
|
205
|
+
- lib/apartment/tenant.rb
|
199
206
|
- lib/apartment/version.rb
|
200
207
|
- lib/generators/apartment/install/USAGE
|
201
208
|
- lib/generators/apartment/install/install_generator.rb
|
@@ -271,7 +278,20 @@ homepage: https://github.com/influitive/apartment
|
|
271
278
|
licenses:
|
272
279
|
- MIT
|
273
280
|
metadata: {}
|
274
|
-
post_install_message:
|
281
|
+
post_install_message: |2
|
282
|
+
********************************
|
283
|
+
|
284
|
+
Apartment Deprecation Warning
|
285
|
+
|
286
|
+
`Apartment::Database` has been deprecated in favour of `Apartment::Tenant`.
|
287
|
+
Please update your application to use the new constant as it is a more
|
288
|
+
appropriate abstraction.
|
289
|
+
|
290
|
+
To further this, DatabaseNotFound, SchemaNotFound, DatabaseExists and
|
291
|
+
SchemaExists exceptions will all be removed, you should instead use
|
292
|
+
TenantNotFound and TenantExists to catch any exceptions.
|
293
|
+
|
294
|
+
********************************
|
275
295
|
rdoc_options: []
|
276
296
|
require_paths:
|
277
297
|
- lib
|