apartment 0.24.0 → 0.24.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/HISTORY.md +6 -0
- data/README.md +38 -32
- data/lib/apartment.rb +9 -1
- data/lib/apartment/railtie.rb +2 -1
- data/lib/apartment/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cb625bf45d3f3ca29dd49ac3f05831ad27670cea
|
4
|
+
data.tar.gz: 9ce79d1937a2873416fc766c65dcdc676976c0d0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 89328d8209fd287e8c3a60a927a6e9a6c2795127ae67e5bf6035810e584e22484c12a5d8c92eb9e24bec895655e7a6fab4f7009d48c2805228367cff5246e854
|
7
|
+
data.tar.gz: 3c4a316a8d26c42c00b7baf3513015e6e154a92fcb7ae359aba750a75ad887a6c6420595cc41921f60f4822ae32a9ae43de5ce7ac4d1bb3a998a45bd9436f098
|
data/HISTORY.md
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
# 0.24.1
|
2
|
+
* February 21, 2014
|
3
|
+
|
4
|
+
- requiring `apartment/tasks/enhancements` in an initializer doesn't work
|
5
|
+
- One can disable tenant migrations using `Apartment.db_migrate_tenants = false` in the Rakefile
|
6
|
+
|
1
7
|
# 0.24
|
2
8
|
* February 21, 2014 (In honour of the Women's Gold Medal in Hockey at Sochi)
|
3
9
|
|
data/README.md
CHANGED
@@ -4,9 +4,9 @@
|
|
4
4
|
|
5
5
|
*Multitenancy for Rails and ActiveRecord*
|
6
6
|
|
7
|
-
Apartment provides tools to help you deal with multiple
|
7
|
+
Apartment provides tools to help you deal with multiple tenants in your Rails
|
8
8
|
application. If you need to have certain data sequestered based on account or company,
|
9
|
-
but still allow some data to exist in a common
|
9
|
+
but still allow some data to exist in a common tenant, Apartment can help.
|
10
10
|
|
11
11
|
|
12
12
|
## Installation
|
@@ -28,8 +28,8 @@ bundle exec rails generate apartment:install
|
|
28
28
|
This will create a `config/initializers/apartment.rb` initializer file.
|
29
29
|
Configure as needed using the docs below.
|
30
30
|
|
31
|
-
That's all you need to set up the Apartment libraries. If you want to switch
|
32
|
-
on a per-user basis, look under "Usage - Switching
|
31
|
+
That's all you need to set up the Apartment libraries. If you want to switch tenants
|
32
|
+
on a per-user basis, look under "Usage - Switching tenants per request", below.
|
33
33
|
|
34
34
|
> NOTE: If using [postgresl schemas](http://www.postgresql.org/docs/9.0/static/ddl-schemas.html) you must use:
|
35
35
|
>
|
@@ -37,46 +37,46 @@ on a per-user basis, look under "Usage - Switching databases per request", below
|
|
37
37
|
|
38
38
|
## Usage
|
39
39
|
|
40
|
-
### Creating new
|
40
|
+
### Creating new Tenants
|
41
41
|
|
42
|
-
Before you can switch to a new apartment
|
43
|
-
you need to create a new
|
42
|
+
Before you can switch to a new apartment tenant, you will need to create it. Whenever
|
43
|
+
you need to create a new tenant, you can run the following command:
|
44
44
|
|
45
45
|
```ruby
|
46
|
-
Apartment::Database.create('
|
46
|
+
Apartment::Database.create('tenant_name')
|
47
47
|
```
|
48
48
|
|
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
|
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".
|
50
50
|
In the case of a sqlite database, this will be created in your 'db/' folder. With
|
51
|
-
other databases, the
|
51
|
+
other databases, the tenant will be created as a new DB within the system.
|
52
52
|
|
53
|
-
When you create a new
|
53
|
+
When you create a new tenant, all migrations will be run against that tenant, so it will be
|
54
54
|
up to date when create returns.
|
55
55
|
|
56
56
|
#### Notes on PostgreSQL
|
57
57
|
|
58
|
-
PostgreSQL works slightly differently than other databases when creating a new
|
59
|
-
are using PostgreSQL, Apartment by default will set up a new
|
60
|
-
provides better performance, and allows Apartment to work on systems like Heroku, which
|
58
|
+
PostgreSQL works slightly differently than other databases when creating a new tenant. If you
|
59
|
+
are using PostgreSQL, Apartment by default will set up a new [schema](http://www.postgresql.org/docs/9.3/static/ddl-schemas.html)
|
60
|
+
and migrate into there. This provides better performance, and allows Apartment to work on systems like Heroku, which
|
61
61
|
would not allow a full new database to be created.
|
62
62
|
|
63
63
|
One can optionally use the full database creation instead if they want, though this is not recommended
|
64
64
|
|
65
|
-
### Switching
|
65
|
+
### Switching Tenants
|
66
66
|
|
67
|
-
To switch
|
67
|
+
To switch tenants using Apartment, use the following command:
|
68
68
|
|
69
69
|
```ruby
|
70
|
-
Apartment::Database.switch('
|
70
|
+
Apartment::Database.switch('tenant_name')
|
71
71
|
```
|
72
72
|
|
73
|
-
When switch is called, all requests coming to ActiveRecord will be routed to the
|
73
|
+
When switch is called, all requests coming to ActiveRecord will be routed to the tenant
|
74
74
|
you specify (with the exception of excluded models, see below). To return to the 'root'
|
75
|
-
|
75
|
+
tenant, call switch with no arguments.
|
76
76
|
|
77
|
-
### Switching
|
77
|
+
### Switching Tenants per request
|
78
78
|
|
79
|
-
You can have Apartment route to the appropriate
|
79
|
+
You can have Apartment route to the appropriate tenant by adding some Rack middleware.
|
80
80
|
Apartment can support many different "Elevators" that can take care of this routing to your data.
|
81
81
|
|
82
82
|
The initializer above will generate the appropriate code for the Subdomain elevator
|
@@ -91,7 +91,7 @@ require 'apartment/elevators/subdomain' # or 'domain' or 'generic'
|
|
91
91
|
```
|
92
92
|
|
93
93
|
**Switch on subdomain**
|
94
|
-
In house, we use the subdomain elevator, which analyzes the subdomain of the request and switches to a
|
94
|
+
In house, we use the subdomain elevator, which analyzes the subdomain of the request and switches to a tenant schema of the same name. It can be used like so:
|
95
95
|
|
96
96
|
```ruby
|
97
97
|
# application.rb
|
@@ -109,7 +109,7 @@ If you want to exclude a domain, for example if you don't want your application
|
|
109
109
|
Apartment::Elevators::Subdomain.excluded_subdomains = ['www']
|
110
110
|
```
|
111
111
|
|
112
|
-
This functions much in the same way as Apartment.excluded_models. This example will prevent switching your
|
112
|
+
This functions much in the same way as Apartment.excluded_models. This example will prevent switching your tenant when the subdomain is www. Handy for subdomains like: "public", "www", and "admin" :)
|
113
113
|
|
114
114
|
**Switch on domain**
|
115
115
|
To switch based on full domain (excluding subdomains *ie 'www'* and top level domains *ie '.com'* ) use the following:
|
@@ -124,19 +124,19 @@ end
|
|
124
124
|
```
|
125
125
|
|
126
126
|
**Switch on full host using a hash**
|
127
|
-
To switch based on full host with a hash to find corresponding
|
127
|
+
To switch based on full host with a hash to find corresponding tenant name use the following:
|
128
128
|
|
129
129
|
```ruby
|
130
130
|
# application.rb
|
131
131
|
module MyApplication
|
132
132
|
class Application < Rails::Application
|
133
|
-
config.middleware.use 'Apartment::Elevators::HostHash', {'example.com' => '
|
133
|
+
config.middleware.use 'Apartment::Elevators::HostHash', {'example.com' => 'example_tenant'}
|
134
134
|
end
|
135
135
|
end
|
136
136
|
```
|
137
137
|
|
138
138
|
**Custom Elevator**
|
139
|
-
A Generic Elevator exists that allows you to pass a `Proc` (or anything that responds to `call`) to the middleware. This Object will be passed in an `ActionDispatch::Request` object when called for you to do your magic. Apartment will use the return value of this proc to switch to the appropriate
|
139
|
+
A Generic Elevator exists that allows you to pass a `Proc` (or anything that responds to `call`) to the middleware. This Object will be passed in an `ActionDispatch::Request` object when called for you to do your magic. Apartment will use the return value of this proc to switch to the appropriate tenant. Use like so:
|
140
140
|
|
141
141
|
```ruby
|
142
142
|
# application.rb
|
@@ -164,7 +164,7 @@ end
|
|
164
164
|
|
165
165
|
### Excluding models
|
166
166
|
|
167
|
-
If you have some models that should always access the 'public'
|
167
|
+
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:
|
168
168
|
|
169
169
|
```ruby
|
170
170
|
config.excluded_models = ["User", "Company"] # these models will not be multi-tenanted, but remain in the global (public) namespace
|
@@ -172,7 +172,7 @@ config.excluded_models = ["User", "Company"] # these models will not be m
|
|
172
172
|
|
173
173
|
Note that a string representation of the model name is now the standard so that models are properly constantized when reloaded in development
|
174
174
|
|
175
|
-
Rails will always access the 'public'
|
175
|
+
Rails will always access the 'public' tenant when accessing these models, but note that tables will be created in all schemas. This may not be ideal, but its done this way because otherwise rails wouldn't be able to properly generate the schema.rb file.
|
176
176
|
|
177
177
|
> **NOTE - Many-To-Many Excluded Models:**
|
178
178
|
> Since model exclusions must come from referencing a real ActiveRecord model, `has_and_belongs_to_many` is NOT supported. In order to achieve a many-to-many relationship for excluded models, you MUST use `has_many :through`. This way you can reference the join model in the excluded models configuration.
|
@@ -240,7 +240,7 @@ Happy to accept PR's on the matter.
|
|
240
240
|
|
241
241
|
### Managing Migrations
|
242
242
|
|
243
|
-
In order to migrate all of your
|
243
|
+
In order to migrate all of your tenants (or posgresql schemas) you need to provide a list
|
244
244
|
of dbs to Apartment. You can make this dynamic by providing a Proc object to be called on migrations.
|
245
245
|
This object should yield an array of string representing each tenant name. Example:
|
246
246
|
|
@@ -252,13 +252,19 @@ config.tenant_names = lambda{ Customer.pluck(:tenant_name) }
|
|
252
252
|
config.tenant_names = ['tenant1', 'tenant2']
|
253
253
|
```
|
254
254
|
|
255
|
-
You can then migrate your
|
255
|
+
You can then migrate your tenants using the normal rake task:
|
256
256
|
|
257
|
-
|
257
|
+
```ruby
|
258
|
+
rake db:migrate
|
259
|
+
```
|
258
260
|
|
259
|
-
This
|
261
|
+
This just invokes `Apartment::Database.migrate(#{tenant_name})` for each tenant name supplied
|
260
262
|
from `Apartment.tenant_names`
|
261
263
|
|
264
|
+
Note that you can disable the default migrating of all tenants with `db:migrate` by setting
|
265
|
+
`Apartment.db_migrate_tenants = false` in your `Rakefile`. Note this must be done
|
266
|
+
*before* the rake tasks are loaded. ie. before `YourApp::Application.load_tasks` is called
|
267
|
+
|
262
268
|
### Handling Environments
|
263
269
|
|
264
270
|
By default, when not using postgresql schemas, Apartment will prepend the environment to the tenant name
|
data/lib/apartment.rb
CHANGED
@@ -11,7 +11,7 @@ module Apartment
|
|
11
11
|
extend Forwardable
|
12
12
|
|
13
13
|
ACCESSOR_METHODS = [:use_schemas, :seed_after_create, :prepend_environment, :append_environment]
|
14
|
-
WRITER_METHODS = [:tenant_names, :database_schema_file, :excluded_models, :default_schema, :persistent_schemas, :connection_class, :tld_length]
|
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)
|
17
17
|
attr_writer(*WRITER_METHODS)
|
@@ -28,6 +28,14 @@ module Apartment
|
|
28
28
|
@tenant_names.respond_to?(:call) ? @tenant_names.call : @tenant_names
|
29
29
|
end
|
30
30
|
|
31
|
+
# Whether or not db:migrate should also migrate tenants
|
32
|
+
# defaults to true
|
33
|
+
def db_migrate_tenants
|
34
|
+
return @db_migrate_tenants if defined?(@db_migrate_tenants)
|
35
|
+
|
36
|
+
@db_migrate_tenants = true
|
37
|
+
end
|
38
|
+
|
31
39
|
# Default to empty array
|
32
40
|
def excluded_models
|
33
41
|
@excluded_models || []
|
data/lib/apartment/railtie.rb
CHANGED
@@ -25,7 +25,7 @@ module Apartment
|
|
25
25
|
|
26
26
|
# Hook into ActionDispatch::Reloader to ensure Apartment is properly initialized
|
27
27
|
# Note that this doens't entirely work as expected in Development, because this is called before classes are reloaded
|
28
|
-
# See the
|
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
31
|
Apartment::Database.init
|
@@ -36,6 +36,7 @@ module Apartment
|
|
36
36
|
#
|
37
37
|
rake_tasks do
|
38
38
|
load 'tasks/apartment.rake'
|
39
|
+
require 'apartment/tasks/enhancements' if Apartment.db_migrate_tenants
|
39
40
|
end
|
40
41
|
|
41
42
|
#
|
data/lib/apartment/version.rb
CHANGED