apartment 0.22.1 → 0.23.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -2
- data/.rspec +2 -1
- data/.travis.yml +3 -1
- data/Appraisals +7 -0
- data/Gemfile +0 -21
- data/HISTORY.md +6 -0
- data/README.md +13 -71
- data/Rakefile +4 -2
- data/TODO.md +0 -5
- data/apartment.gemspec +19 -0
- data/gemfiles/rails3.2.gemfile +7 -0
- data/gemfiles/rails4.0.gemfile +7 -0
- data/lib/apartment.rb +2 -28
- data/lib/apartment/adapters/abstract_adapter.rb +0 -2
- data/lib/apartment/adapters/abstract_jdbc_adapter.rb +2 -0
- data/lib/apartment/adapters/jdbc_mysql_adapter.rb +2 -0
- data/lib/apartment/adapters/jdbc_postgresql_adapter.rb +1 -1
- data/lib/apartment/adapters/mysql2_adapter.rb +2 -3
- data/lib/apartment/adapters/postgis_adapter.rb +0 -1
- data/lib/apartment/adapters/postgresql_adapter.rb +2 -3
- data/lib/apartment/adapters/sqlite3_adapter.rb +2 -0
- data/lib/apartment/database.rb +0 -4
- data/lib/apartment/elevators/domain.rb +2 -0
- data/lib/apartment/elevators/first_subdomain.rb +2 -0
- data/lib/apartment/elevators/generic.rb +3 -0
- data/lib/apartment/elevators/host_hash.rb +2 -0
- data/lib/apartment/elevators/subdomain.rb +19 -2
- data/lib/apartment/migrator.rb +2 -1
- data/lib/apartment/railtie.rb +2 -2
- data/lib/apartment/reloader.rb +0 -3
- data/lib/apartment/version.rb +2 -2
- data/lib/tasks/apartment.rake +2 -0
- data/spec/adapters/jdbc_mysql_adapter_spec.rb +1 -3
- data/spec/adapters/jdbc_postgresql_adapter_spec.rb +1 -3
- data/spec/adapters/mysql2_adapter_spec.rb +1 -2
- data/spec/adapters/postgresql_adapter_spec.rb +1 -2
- data/spec/adapters/sqlite3_adapter_spec.rb +1 -2
- data/spec/database_spec.rb +32 -50
- data/spec/dummy/app/models/user.rb +0 -2
- data/spec/dummy/config/application.rb +2 -0
- data/spec/dummy/config/environments/development.rb +2 -0
- data/spec/dummy/config/environments/production.rb +2 -0
- data/spec/dummy/config/environments/test.rb +1 -2
- data/spec/dummy/config/initializers/apartment.rb +1 -1
- data/spec/dummy/db/seeds.rb +1 -4
- data/spec/examples/elevator_examples.rb +4 -4
- data/spec/integration/apartment_rake_integration_spec.rb +15 -19
- data/spec/integration/middleware/domain_elevator_spec.rb +4 -3
- data/spec/integration/middleware/generic_elevator_spec.rb +4 -3
- data/spec/integration/middleware/subdomain_elevator_spec.rb +29 -3
- data/spec/integration/query_caching_spec.rb +8 -4
- data/spec/schemas/v1.rb +16 -0
- data/spec/schemas/v2.rb +43 -0
- data/spec/schemas/v3.rb +49 -0
- data/spec/spec_helper.rb +5 -11
- data/spec/support/apartment_helpers.rb +4 -2
- data/spec/support/contexts.rb +15 -19
- data/spec/support/requirements.rb +1 -17
- data/spec/support/setup.rb +47 -0
- data/spec/tasks/apartment_rake_spec.rb +6 -3
- data/spec/unit/config_spec.rb +3 -3
- data/spec/unit/middleware/domain_elevator_spec.rb +1 -2
- data/spec/{integration → unit}/middleware/first_subdomain_elevator_spec.rb +1 -0
- data/spec/unit/middleware/host_hash_elevator_spec.rb +1 -2
- data/spec/unit/middleware/subdomain_elevator_spec.rb +1 -2
- data/spec/unit/migrator_spec.rb +5 -4
- data/spec/unit/reloader_spec.rb +6 -4
- metadata +130 -14
- data/lib/apartment/delayed_job/enqueue.rb +0 -26
- data/lib/apartment/delayed_job/hooks.rb +0 -26
- data/lib/apartment/delayed_job/psych_ext.rb +0 -61
- data/lib/apartment/delayed_job/requirements.rb +0 -23
- data/lib/apartment/delayed_job/syck_ext.rb +0 -29
- data/spec/dummy/lib/fake_dj_class.rb +0 -6
- data/spec/integration/delayed_job_integration_spec.rb +0 -99
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7048e41db332f308d96362525ecd55389c7b6ad2
|
4
|
+
data.tar.gz: c303cac42eca0c9d5a22263fb8d2b3abb239b07e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ab730aab830bf546295ecd75dabc017dd1fe01a55bbf82b625ff0f9e70cd7a58034417afe25344c7c36ff9f9e1f75eec7a73a4d07432fc1f6acc4e03291548ab
|
7
|
+
data.tar.gz: 0d7041eaea15f04e43ab772adfbbebb51f35451215a619882162d337d9bb25bbffbf3c9bbfb0e73ece50935681a45adc8d1ecb55e9d1ceeae38823a2dbd73134
|
data/.gitignore
CHANGED
data/.rspec
CHANGED
data/.travis.yml
CHANGED
data/Appraisals
ADDED
data/Gemfile
CHANGED
@@ -3,27 +3,6 @@ source 'http://rubygems.org'
|
|
3
3
|
gemspec
|
4
4
|
|
5
5
|
gem 'rails', '>= 3.1.2'
|
6
|
-
gem 'rake', '~> 0.9'
|
7
|
-
gem 'rspec', '~> 2.11'
|
8
|
-
gem 'rspec-rails', '~> 2.11'
|
9
|
-
gem 'capybara', '~> 1.0.0'
|
10
|
-
gem 'delayed_job', '~> 3.0'
|
11
|
-
gem 'delayed_job_active_record'
|
12
|
-
|
13
|
-
platform :ruby do
|
14
|
-
gem 'mysql2', '~> 0.3.10'
|
15
|
-
gem 'pg', '>= 0.11.0'
|
16
|
-
gem 'sqlite3'
|
17
|
-
end
|
18
|
-
|
19
|
-
platform :jruby do
|
20
|
-
gem 'activerecord-jdbc-adapter'
|
21
|
-
gem 'activerecord-jdbcpostgresql-adapter'
|
22
|
-
gem 'activerecord-jdbcmysql-adapter'
|
23
|
-
gem 'jdbc-postgres', '9.2.1002'
|
24
|
-
gem 'jdbc-mysql'
|
25
|
-
gem 'jruby-openssl'
|
26
|
-
end
|
27
6
|
|
28
7
|
group :local do
|
29
8
|
gem 'pry'
|
data/HISTORY.md
CHANGED
data/README.md
CHANGED
@@ -75,19 +75,28 @@ In house, we use the subdomain elevator, which analyzes the subdomain of the req
|
|
75
75
|
|
76
76
|
```ruby
|
77
77
|
# application.rb
|
78
|
-
module
|
78
|
+
module MyApplication
|
79
79
|
class Application < Rails::Application
|
80
80
|
config.middleware.use 'Apartment::Elevators::Subdomain'
|
81
81
|
end
|
82
82
|
end
|
83
83
|
```
|
84
84
|
|
85
|
+
If you want to exclude a domain, for example if you don't want your application to treate www like a subdomain, in an initializer in your application, you can set the following:
|
86
|
+
|
87
|
+
```ruby
|
88
|
+
# config/initializers/apartment/subdomain_exclusions.rb
|
89
|
+
Apartment::Elevators::Subdomain.excluded_subdomains = ['www']
|
90
|
+
```
|
91
|
+
|
92
|
+
This functions much in the same way as Apartment.excluded_models. This example will prevent switching your database when the subdomain is www. Handy for subdomains like: "public", "www", and "admin" :)
|
93
|
+
|
85
94
|
**Switch on domain**
|
86
95
|
To switch based on full domain (excluding subdomains *ie 'www'* and top level domains *ie '.com'* ) use the following:
|
87
96
|
|
88
97
|
```ruby
|
89
98
|
# application.rb
|
90
|
-
module
|
99
|
+
module MyApplication
|
91
100
|
class Application < Rails::Application
|
92
101
|
config.middleware.use 'Apartment::Elevators::Domain'
|
93
102
|
end
|
@@ -99,7 +108,7 @@ To switch based on full host with a hash to find corresponding database name use
|
|
99
108
|
|
100
109
|
```ruby
|
101
110
|
# application.rb
|
102
|
-
module
|
111
|
+
module MyApplication
|
103
112
|
class Application < Rails::Application
|
104
113
|
config.middleware.use 'Apartment::Elevators::HostHash', {'example.com' => 'example_database'}
|
105
114
|
end
|
@@ -238,74 +247,7 @@ config.prepend_environment = !Rails.env.production?
|
|
238
247
|
```
|
239
248
|
|
240
249
|
## Delayed::Job
|
241
|
-
|
242
|
-
### Read me before using Delayed::Job!!!
|
243
|
-
> It should be noted that we now consider Delayed::Job usage with Apartment effectively deprecated
|
244
|
-
> It will be stripped out into it's own gem for backwards compatibility, but we've had far too
|
245
|
-
> many problems with it to continue supporting it.
|
246
|
-
>
|
247
|
-
> The main problem is that Delayed::Job [monkey](https://github.com/collectiveidea/delayed_job/blob/master/lib/delayed/psych_ext.rb) [patches](https://github.com/collectiveidea/delayed_job/blob/master/lib/delayed/syck_ext.rb) YAML quite a bit, which
|
248
|
-
> forces us to in tern [monkey](https://github.com/influitive/apartment/blob/development/lib/apartment/delayed_job/psych_ext.rb) [patch](https://github.com/influitive/apartment/blob/development/lib/apartment/delayed_job/syck_ext.rb) their monkey patches, which provides
|
249
|
-
> no end of frustrations whenever upgrades are made.
|
250
|
-
>
|
251
|
-
> To this end, we recommend you look into other solutions such as Resque or Sidekiq and write
|
252
|
-
> your own hooks to switch db per job. Our aim is to have separate gems for each of these
|
253
|
-
> worker libs and would love it if anyone would like to contribute something to achieve this
|
254
|
-
>
|
255
|
-
> If you are hell bent on using `Delayed::Job`, this is what has worked for us in Production
|
256
|
-
>
|
257
|
-
> ```ruby
|
258
|
-
> gem 'delayed_job', '= 3.0.1' # change at own risk!
|
259
|
-
> gem 'delayed_job_active_record', '= 0.3.2' # change at own risk!
|
260
|
-
> ```
|
261
|
-
>
|
262
|
-
|
263
|
-
If using Rails ~> 3.2, you *must* use `delayed_job ~> 3.0`. It has better Rails 3 support plus has some major changes that affect the serialization of models.
|
264
|
-
|
265
|
-
### If using Ruby 1.9.3-p362 you MUST use psych as your parser. YAML seems to fall down using syck
|
266
|
-
|
267
|
-
### If you're using syck on an earlier version of ruby, here's what you must do (in a rails app for instance)
|
268
|
-
This can be done in the `boot.rb` of your rails config *just above* where Bundler requires the gems from the Gemfile. It will look something like:
|
269
|
-
|
270
|
-
```ruby
|
271
|
-
require 'rubygems'
|
272
|
-
require 'yaml'
|
273
|
-
YAML::ENGINE.yamler = 'syck'
|
274
|
-
|
275
|
-
# Set up gems listed in the Gemfile.
|
276
|
-
gemfile = File.expand_path('../../Gemfile', __FILE__)
|
277
|
-
# ...
|
278
|
-
```
|
279
|
-
|
280
|
-
In order to make ActiveRecord models play nice with DJ and Apartment, include `Apartment::Delayed::Requirements` in any model that is being serialized by DJ. Also ensure that the `database` attribute (provided by Apartment::Delayed::Requirements) is set on this model *before* it is serialized, to ensure that when it is fetched again, it is done so in the proper Apartment db context. For example:
|
281
|
-
|
282
|
-
```ruby
|
283
|
-
class SomeModel < ActiveRecord::Base
|
284
|
-
include Apartment::Delayed::Requirements
|
285
|
-
end
|
286
|
-
```
|
287
|
-
|
288
|
-
Any classes that are being used as a Delayed::Job Job need to include the `Apartment::Delayed::Job::Hooks` module into the class. This ensures that when a job runs, it switches to the appropriate tenant before performing its task. It is also required (manually at the moment) that you set a `@database` attribute on your job so the hooks know what tennant to switch to
|
289
|
-
|
290
|
-
```ruby
|
291
|
-
class SomeDJ
|
292
|
-
include Apartment::Delayed::Job::Hooks
|
293
|
-
|
294
|
-
def initialize
|
295
|
-
@database = Apartment::Database.current_database
|
296
|
-
end
|
297
|
-
|
298
|
-
def perform
|
299
|
-
# do some stuff (will automatically switch to @database before performing and switch back after)
|
300
|
-
end
|
301
|
-
end
|
302
|
-
```
|
303
|
-
|
304
|
-
All jobs *must* stored in the global (public) namespace, so add it to the list of excluded models:
|
305
|
-
|
306
|
-
```ruby
|
307
|
-
config.excluded_models = ["Delayed::Job"]
|
308
|
-
```
|
250
|
+
### Has been removed... See apartment-sidekiq for a better backgrounding experience
|
309
251
|
|
310
252
|
## Contributing
|
311
253
|
|
data/Rakefile
CHANGED
@@ -2,6 +2,8 @@ require 'bundler' rescue 'You must `gem install bundler` and `bundle install` to
|
|
2
2
|
Bundler.setup
|
3
3
|
Bundler::GemHelper.install_tasks
|
4
4
|
|
5
|
+
require 'appraisal'
|
6
|
+
|
5
7
|
require "rspec"
|
6
8
|
require "rspec/core/rake_task"
|
7
9
|
|
@@ -63,7 +65,7 @@ namespace :mysql do
|
|
63
65
|
|
64
66
|
desc 'Build the MySQL test databases'
|
65
67
|
task :build_db do
|
66
|
-
%x{ mysqladmin -u #{my_config['username']} create #{my_config['database']} } rescue "test db already exists"
|
68
|
+
%x{ mysqladmin -u #{my_config['username']} --password=#{my_config['password']} create #{my_config['database']} } rescue "test db already exists"
|
67
69
|
ActiveRecord::Base.establish_connection my_config
|
68
70
|
ActiveRecord::Migrator.migrate('spec/dummy/db/migrate')
|
69
71
|
end
|
@@ -71,7 +73,7 @@ namespace :mysql do
|
|
71
73
|
desc "drop the MySQL test database"
|
72
74
|
task :drop_db do
|
73
75
|
puts "dropping database #{my_config['database']}"
|
74
|
-
%x{ mysqladmin -u #{my_config['username']} drop #{my_config['database']} --force}
|
76
|
+
%x{ mysqladmin -u #{my_config['username']} --password=#{my_config['password']} drop #{my_config['database']} --force}
|
75
77
|
end
|
76
78
|
|
77
79
|
end
|
data/TODO.md
CHANGED
@@ -24,11 +24,6 @@
|
|
24
24
|
think about Tenants. I proprose that we deprecate the `Apartment::Database` constant in favour of `Apartment::Tenant` for a nicer abstraction. See
|
25
25
|
http://myronmars.to/n/dev-blog/2011/09/deprecating-constants-and-classes-in-ruby for ideas on how to achieve this.
|
26
26
|
|
27
|
-
3. `Delayed::Job` has proven to be an absolute P.I.T.A. It's YAML hacks are beyond reproach and require further hacks in order to work properly.
|
28
|
-
I want to completely remove the Delayed::Job dependency from Apartment and make an `apartment-delayed-job` gem that can be worked on independently
|
29
|
-
(and hopefully eventually deprecated). To this end, I've started an `apartment-sidekiq` gem and would love to see an `apartment-resque` gem to deal
|
30
|
-
with those background workers from a multi-tenant perspective also.
|
31
|
-
|
32
27
|
4. Apartment::Database.process should be deprecated in favour of just passing an optional block to `switch`
|
33
28
|
|
34
29
|
5. Migrations right now can be a bit of a pain. Apartment currently migrates a single tenant completely up to date, then goes onto the next. If one of these
|
data/apartment.gemspec
CHANGED
@@ -20,4 +20,23 @@ Gem::Specification.new do |s|
|
|
20
20
|
|
21
21
|
s.add_dependency 'activerecord', '>= 3.1.2' # must be >= 3.1.2 due to bug in prepared_statements
|
22
22
|
s.add_dependency 'rack', '>= 1.3.6'
|
23
|
+
|
24
|
+
s.add_development_dependency 'appraisal'
|
25
|
+
s.add_development_dependency 'rake', '~> 0.9'
|
26
|
+
s.add_development_dependency 'rspec', '~> 2.11'
|
27
|
+
s.add_development_dependency 'rspec-rails', '~> 2.11'
|
28
|
+
s.add_development_dependency 'capybara', '~> 1.0.0'
|
29
|
+
|
30
|
+
if defined?(JRUBY_VERSION)
|
31
|
+
s.add_development_dependency 'activerecord-jdbc-adapter'
|
32
|
+
s.add_development_dependency 'activerecord-jdbcpostgresql-adapter'
|
33
|
+
s.add_development_dependency 'activerecord-jdbcmysql-adapter'
|
34
|
+
s.add_development_dependency 'jdbc-postgres', '9.2.1002'
|
35
|
+
s.add_development_dependency 'jdbc-mysql'
|
36
|
+
s.add_development_dependency 'jruby-openssl'
|
37
|
+
else
|
38
|
+
s.add_development_dependency 'mysql2', '~> 0.3.10'
|
39
|
+
s.add_development_dependency 'pg', '>= 0.11.0'
|
40
|
+
s.add_development_dependency 'sqlite3'
|
41
|
+
end
|
23
42
|
end
|
data/lib/apartment.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
require 'apartment/railtie' if defined?(Rails)
|
2
2
|
require 'active_support/core_ext/object/blank'
|
3
3
|
require 'forwardable'
|
4
|
+
require 'active_record'
|
5
|
+
require 'apartment/database'
|
4
6
|
|
5
7
|
module Apartment
|
6
8
|
|
@@ -63,33 +65,6 @@ module Apartment
|
|
63
65
|
warn "[Deprecation Warning] `use_postgresql_schemas=` is now deprecated, please use `use_schemas=`"
|
64
66
|
self.use_schemas = to_use_or_not_to_use
|
65
67
|
end
|
66
|
-
|
67
|
-
end
|
68
|
-
|
69
|
-
autoload :Database, 'apartment/database'
|
70
|
-
autoload :Migrator, 'apartment/migrator'
|
71
|
-
autoload :Reloader, 'apartment/reloader'
|
72
|
-
|
73
|
-
module Adapters
|
74
|
-
autoload :AbstractAdapter, 'apartment/adapters/abstract_adapter'
|
75
|
-
# Specific adapters will be loaded dynamically based on adapter in config
|
76
|
-
end
|
77
|
-
|
78
|
-
module Elevators
|
79
|
-
autoload :Generic, 'apartment/elevators/generic'
|
80
|
-
autoload :Subdomain, 'apartment/elevators/subdomain'
|
81
|
-
autoload :FirstSubdomain, 'apartment/elevators/first_subdomain'
|
82
|
-
autoload :Domain, 'apartment/elevators/domain'
|
83
|
-
autoload :HostHash, 'apartment/elevators/host_hash'
|
84
|
-
end
|
85
|
-
|
86
|
-
module Delayed
|
87
|
-
|
88
|
-
autoload :Requirements, 'apartment/delayed_job/requirements'
|
89
|
-
|
90
|
-
module Job
|
91
|
-
autoload :Hooks, 'apartment/delayed_job/hooks'
|
92
|
-
end
|
93
68
|
end
|
94
69
|
|
95
70
|
# Exceptions
|
@@ -112,5 +87,4 @@ module Apartment
|
|
112
87
|
|
113
88
|
# Raised when an ActiveRecord object does not have the required database field on it
|
114
89
|
class DJSerializationError < ApartmentError; end
|
115
|
-
|
116
90
|
end
|
@@ -48,7 +48,7 @@ module Apartment
|
|
48
48
|
#
|
49
49
|
def connect_to_new(database = nil)
|
50
50
|
return reset if database.nil?
|
51
|
-
raise ActiveRecord::StatementInvalid.new unless Apartment.connection.all_schemas.include? database.to_s
|
51
|
+
raise ActiveRecord::StatementInvalid.new("Could not find schema #{database}") unless Apartment.connection.all_schemas.include? database.to_s
|
52
52
|
|
53
53
|
@current_database = database.to_s
|
54
54
|
Apartment.connection.schema_search_path = full_search_path
|
@@ -1,5 +1,6 @@
|
|
1
|
-
|
1
|
+
require 'apartment/adapters/abstract_adapter'
|
2
2
|
|
3
|
+
module Apartment
|
3
4
|
module Database
|
4
5
|
|
5
6
|
def self.mysql2_adapter(config)
|
@@ -10,7 +11,6 @@ module Apartment
|
|
10
11
|
end
|
11
12
|
|
12
13
|
module Adapters
|
13
|
-
|
14
14
|
class Mysql2Adapter < AbstractAdapter
|
15
15
|
|
16
16
|
protected
|
@@ -73,7 +73,6 @@ module Apartment
|
|
73
73
|
# Ensure that if a schema *was* set, we override
|
74
74
|
table_name = klass.table_name.split('.', 2).last
|
75
75
|
|
76
|
-
# Not sure why, but Delayed::Job somehow ignores table_name_prefix... so we'll just manually set table name instead
|
77
76
|
klass.table_name = "#{default_database}.#{table_name}"
|
78
77
|
end
|
79
78
|
end
|
@@ -1,5 +1,6 @@
|
|
1
|
-
|
1
|
+
require 'apartment/adapters/abstract_adapter'
|
2
2
|
|
3
|
+
module Apartment
|
3
4
|
module Database
|
4
5
|
|
5
6
|
def self.postgresql_adapter(config)
|
@@ -10,7 +11,6 @@ module Apartment
|
|
10
11
|
end
|
11
12
|
|
12
13
|
module Adapters
|
13
|
-
|
14
14
|
# Default adapter when not using Postgresql Schemas
|
15
15
|
class PostgresqlAdapter < AbstractAdapter
|
16
16
|
|
@@ -48,7 +48,6 @@ module Apartment
|
|
48
48
|
# Ensure that if a schema *was* set, we override
|
49
49
|
table_name = klass.table_name.split('.', 2).last
|
50
50
|
|
51
|
-
# Not sure why, but Delayed::Job somehow ignores table_name_prefix... so we'll just manually set table name instead
|
52
51
|
klass.table_name = "#{Apartment.default_schema}.#{table_name}"
|
53
52
|
end
|
54
53
|
end
|
data/lib/apartment/database.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'forwardable'
|
2
2
|
|
3
3
|
module Apartment
|
4
|
-
|
5
4
|
# The main entry point to Apartment functions
|
6
5
|
#
|
7
6
|
module Database
|
@@ -36,7 +35,6 @@ module Apartment
|
|
36
35
|
end
|
37
36
|
|
38
37
|
begin
|
39
|
-
require "apartment/adapters/abstract_jdbc_adapter" if defined?(JRUBY_VERSION)
|
40
38
|
require "apartment/adapters/#{adapter_method}"
|
41
39
|
rescue LoadError
|
42
40
|
raise "The adapter `#{adapter_method}` is not yet supported"
|
@@ -64,7 +62,5 @@ module Apartment
|
|
64
62
|
def config
|
65
63
|
@config ||= Rails.configuration.database_configuration[Rails.env].symbolize_keys
|
66
64
|
end
|
67
|
-
|
68
65
|
end
|
69
|
-
|
70
66
|
end
|