apartment 0.21.0 → 0.21.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/.travis.yml +1 -0
- data/Gemfile +2 -1
- data/HISTORY.md +6 -0
- data/README.md +1 -1
- data/lib/apartment/adapters/abstract_adapter.rb +18 -14
- data/lib/apartment/adapters/abstract_jdbc_adapter.rb +7 -37
- data/lib/apartment/adapters/jdbc_postgresql_adapter.rb +19 -79
- data/lib/apartment/adapters/postgresql_adapter.rb +8 -23
- data/lib/apartment/adapters/sqlite3_adapter.rb +51 -0
- data/lib/apartment/elevators/first_subdomain.rb +6 -5
- data/lib/apartment/version.rb +1 -1
- data/spec/adapters/sqlite3_adapter_spec.rb +28 -0
- data/spec/config/database.yml.sample +5 -1
- data/spec/integration/delayed_job_integration_spec.rb +18 -8
- data/spec/integration/query_caching_spec.rb +37 -0
- metadata +43 -39
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
data/HISTORY.md
CHANGED
data/README.md
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# Apartment
|
2
|
-
[![Code Climate](https://codeclimate.com/
|
2
|
+
[![Code Climate](https://codeclimate.com/github/influitive/apartment.png)](https://codeclimate.com/github/influitive/apartment)
|
3
3
|
[![Build Status](https://secure.travis-ci.org/influitive/apartment.png?branch=development)](http://travis-ci.org/influitive/apartment)
|
4
4
|
|
5
5
|
*Multitenancy for Rails 3 and ActiveRecord*
|
@@ -1,9 +1,7 @@
|
|
1
1
|
require 'active_record'
|
2
2
|
|
3
3
|
module Apartment
|
4
|
-
|
5
4
|
module Adapters
|
6
|
-
|
7
5
|
class AbstractAdapter
|
8
6
|
|
9
7
|
# @constructor
|
@@ -52,7 +50,7 @@ module Apartment
|
|
52
50
|
# Apartment.connection.drop_database note that drop_database will not throw an exception, so manually execute
|
53
51
|
Apartment.connection.execute("DROP DATABASE #{environmentify(database)}" )
|
54
52
|
|
55
|
-
rescue
|
53
|
+
rescue *rescuable_exceptions
|
56
54
|
raise DatabaseNotFound, "The database #{environmentify(database)} cannot be found"
|
57
55
|
end
|
58
56
|
|
@@ -74,13 +72,6 @@ module Apartment
|
|
74
72
|
def process_excluded_models
|
75
73
|
# All other models will shared a connection (at Apartment.connection_class) and we can modify at will
|
76
74
|
Apartment.excluded_models.each do |excluded_model|
|
77
|
-
# Note that due to rails reloading, we now take string references to classes rather than
|
78
|
-
# actual object references. This way when we contantize, we always get the proper class reference
|
79
|
-
if excluded_model.is_a? Class
|
80
|
-
warn "[Deprecation Warning] Passing class references to excluded models is now deprecated, please use a string instead"
|
81
|
-
excluded_model = excluded_model.name
|
82
|
-
end
|
83
|
-
|
84
75
|
excluded_model.constantize.establish_connection @config
|
85
76
|
end
|
86
77
|
end
|
@@ -99,7 +90,9 @@ module Apartment
|
|
99
90
|
# Just connect to default db and return
|
100
91
|
return reset if database.nil?
|
101
92
|
|
102
|
-
connect_to_new(database)
|
93
|
+
connect_to_new(database).tap do
|
94
|
+
ActiveRecord::Base.connection.clear_query_cache
|
95
|
+
end
|
103
96
|
end
|
104
97
|
|
105
98
|
# Load the rails seed file into the db
|
@@ -118,7 +111,7 @@ module Apartment
|
|
118
111
|
def create_database(database)
|
119
112
|
Apartment.connection.create_database( environmentify(database) )
|
120
113
|
|
121
|
-
rescue
|
114
|
+
rescue *rescuable_exceptions
|
122
115
|
raise DatabaseExists, "The database #{environmentify(database)} already exists."
|
123
116
|
end
|
124
117
|
|
@@ -130,7 +123,7 @@ module Apartment
|
|
130
123
|
Apartment.establish_connection multi_tenantify(database)
|
131
124
|
Apartment.connection.active? # call active? to manually check if this connection is valid
|
132
125
|
|
133
|
-
rescue
|
126
|
+
rescue *rescuable_exceptions
|
134
127
|
raise DatabaseNotFound, "The database #{environmentify(database)} cannot be found."
|
135
128
|
end
|
136
129
|
|
@@ -179,6 +172,17 @@ module Apartment
|
|
179
172
|
end
|
180
173
|
end
|
181
174
|
|
175
|
+
# Exceptions to rescue from on db operations
|
176
|
+
#
|
177
|
+
def rescuable_exceptions
|
178
|
+
[ActiveRecord::StatementInvalid] + [rescue_from].flatten
|
179
|
+
end
|
180
|
+
|
181
|
+
# Extra exceptions to rescue from
|
182
|
+
#
|
183
|
+
def rescue_from
|
184
|
+
[]
|
185
|
+
end
|
182
186
|
end
|
183
187
|
end
|
184
|
-
end
|
188
|
+
end
|
@@ -1,43 +1,8 @@
|
|
1
1
|
module Apartment
|
2
|
-
|
3
2
|
module Adapters
|
4
|
-
|
5
3
|
class AbstractJDBCAdapter < AbstractAdapter
|
6
4
|
|
7
|
-
|
8
|
-
#
|
9
|
-
# @param {String} database Database name
|
10
|
-
#
|
11
|
-
def drop(database)
|
12
|
-
super(database)
|
13
|
-
|
14
|
-
rescue ActiveRecord::StatementInvalid, ActiveRecord::JDBCError
|
15
|
-
raise DatabaseNotFound, "The database #{environmentify(database)} cannot be found"
|
16
|
-
end
|
17
|
-
|
18
|
-
protected
|
19
|
-
|
20
|
-
# Create the database
|
21
|
-
#
|
22
|
-
# @param {String} database Database name
|
23
|
-
#
|
24
|
-
def create_database(database)
|
25
|
-
super(database)
|
26
|
-
|
27
|
-
rescue ActiveRecord::StatementInvalid, ActiveRecord::JDBCError
|
28
|
-
raise DatabaseExists, "The database #{environmentify(database)} already exists."
|
29
|
-
end
|
30
|
-
|
31
|
-
# Connect to new database
|
32
|
-
#
|
33
|
-
# @param {String} database Database name
|
34
|
-
#
|
35
|
-
def connect_to_new(database)
|
36
|
-
super(database)
|
37
|
-
|
38
|
-
rescue ActiveRecord::StatementInvalid, ActiveRecord::JDBCError
|
39
|
-
raise DatabaseNotFound, "The database #{environmentify(database)} cannot be found."
|
40
|
-
end
|
5
|
+
protected
|
41
6
|
|
42
7
|
# Return a new config that is multi-tenanted
|
43
8
|
#
|
@@ -46,6 +11,11 @@ module Apartment
|
|
46
11
|
config[:url] = "#{config[:url].gsub(/(\S+)\/.+$/, '\1')}/#{environmentify(database)}"
|
47
12
|
end
|
48
13
|
end
|
14
|
+
private
|
15
|
+
|
16
|
+
def rescue_from
|
17
|
+
ActiveRecord::JDBCError
|
18
|
+
end
|
49
19
|
end
|
50
20
|
end
|
51
|
-
end
|
21
|
+
end
|
@@ -1,5 +1,6 @@
|
|
1
|
-
|
1
|
+
require 'apartment/adapters/postgresql_adapter'
|
2
2
|
|
3
|
+
module Apartment
|
3
4
|
module Database
|
4
5
|
|
5
6
|
def self.jdbc_postgresql_adapter(config)
|
@@ -12,91 +13,42 @@ module Apartment
|
|
12
13
|
module Adapters
|
13
14
|
|
14
15
|
# Default adapter when not using Postgresql Schemas
|
15
|
-
class JDBCPostgresqlAdapter <
|
16
|
+
class JDBCPostgresqlAdapter < PostgresqlAdapter
|
16
17
|
|
17
|
-
|
18
|
-
|
19
|
-
# Connect to new database
|
20
|
-
# Abstract adapter will catch generic ActiveRecord error
|
21
|
-
# Catch specific adapter errors here
|
22
|
-
#
|
23
|
-
# @param {String} database Database name
|
24
|
-
#
|
25
|
-
def connect_to_new(database)
|
26
|
-
super(database)
|
27
|
-
rescue ActiveRecord::StatementInvalid, ActiveRecord::JDBCError
|
28
|
-
raise DatabaseNotFound, "Cannot find database #{environmentify(database)}"
|
29
|
-
end
|
18
|
+
protected
|
30
19
|
|
31
20
|
def create_database(database)
|
32
21
|
# There is a bug in activerecord-jdbcpostgresql-adapter (1.2.5) that will cause
|
33
22
|
# an exception if no options are passed into the create_database call.
|
34
23
|
Apartment.connection.create_database(environmentify(database), { :thisisahack => '' })
|
35
24
|
|
36
|
-
rescue
|
25
|
+
rescue *rescuable_exceptions
|
37
26
|
raise DatabaseExists, "The database #{environmentify(database)} already exists."
|
38
27
|
end
|
39
|
-
end
|
40
|
-
|
41
|
-
# Separate Adapter for Postgresql when using schemas
|
42
|
-
class JDBCPostgresqlSchemaAdapter < AbstractJDBCAdapter
|
43
|
-
|
44
|
-
# Drop the database schema
|
45
|
-
#
|
46
|
-
# @param {String} database Database (schema) to drop
|
47
|
-
#
|
48
|
-
def drop(database)
|
49
|
-
Apartment.connection.execute(%{DROP SCHEMA "#{database}" CASCADE})
|
50
|
-
|
51
|
-
rescue ActiveRecord::StatementInvalid, ActiveRecord::JDBCError
|
52
|
-
raise SchemaNotFound, "The schema #{database.inspect} cannot be found."
|
53
|
-
end
|
54
28
|
|
55
|
-
#
|
56
|
-
# Set the table_name to always use the default namespace for excluded models
|
29
|
+
# Return a new config that is multi-tenanted
|
57
30
|
#
|
58
|
-
def
|
59
|
-
|
60
|
-
|
61
|
-
# actual object references. This way when we contantize, we always get the proper class reference
|
62
|
-
if excluded_model.is_a? Class
|
63
|
-
warn "[Deprecation Warning] Passing class references to excluded models is now deprecated, please use a string instead"
|
64
|
-
excluded_model = excluded_model.name
|
65
|
-
end
|
66
|
-
|
67
|
-
excluded_model.constantize.tap do |klass|
|
68
|
-
# some models (such as delayed_job) seem to load and cache their column names before this,
|
69
|
-
# so would never get the default prefix, so reset first
|
70
|
-
klass.reset_column_information
|
71
|
-
|
72
|
-
# Ensure that if a schema *was* set, we override
|
73
|
-
table_name = klass.table_name.split('.', 2).last
|
74
|
-
|
75
|
-
# Not sure why, but Delayed::Job somehow ignores table_name_prefix... so we'll just manually set table name instead
|
76
|
-
klass.table_name = "#{Apartment.default_schema}.#{table_name}"
|
77
|
-
end
|
31
|
+
def multi_tenantify(database)
|
32
|
+
@config.clone.tap do |config|
|
33
|
+
config[:url] = "#{config[:url].gsub(/(\S+)\/.+$/, '\1')}/#{environmentify(database)}"
|
78
34
|
end
|
79
35
|
end
|
80
36
|
|
81
|
-
|
82
|
-
#
|
83
|
-
# @return {String} default schema search path
|
84
|
-
#
|
85
|
-
def reset
|
86
|
-
@current_database = Apartment.default_schema
|
87
|
-
Apartment.connection.schema_search_path = full_search_path
|
88
|
-
end
|
37
|
+
private
|
89
38
|
|
90
|
-
def
|
91
|
-
|
39
|
+
def rescue_from
|
40
|
+
ActiveRecord::JDBCError
|
92
41
|
end
|
42
|
+
end
|
93
43
|
|
94
|
-
|
44
|
+
# Separate Adapter for Postgresql when using schemas
|
45
|
+
class JDBCPostgresqlSchemaAdapter < PostgresqlSchemaAdapter
|
95
46
|
|
96
47
|
# Set schema search path to new schema
|
97
48
|
#
|
98
49
|
def connect_to_new(database = nil)
|
99
50
|
return reset if database.nil?
|
51
|
+
raise ActiveRecord::StatementInvalid.new unless Apartment.connection.all_schemas.include? database.to_s
|
100
52
|
|
101
53
|
@current_database = database.to_s
|
102
54
|
Apartment.connection.schema_search_path = full_search_path
|
@@ -105,22 +57,10 @@ module Apartment
|
|
105
57
|
raise SchemaNotFound, "One of the following schema(s) is invalid: #{full_search_path}"
|
106
58
|
end
|
107
59
|
|
108
|
-
|
109
|
-
#
|
110
|
-
def create_database(database)
|
111
|
-
Apartment.connection.execute(%{CREATE SCHEMA "#{database}"})
|
60
|
+
private
|
112
61
|
|
113
|
-
|
114
|
-
|
115
|
-
end
|
116
|
-
|
117
|
-
private
|
118
|
-
|
119
|
-
# Generate the final search path to set including persistent_schemas
|
120
|
-
#
|
121
|
-
def full_search_path
|
122
|
-
persistent_schemas = Apartment.persistent_schemas.join(', ')
|
123
|
-
@current_database.to_s + (persistent_schemas.empty? ? "" : ", #{persistent_schemas}")
|
62
|
+
def rescue_from
|
63
|
+
ActiveRecord::JDBCError
|
124
64
|
end
|
125
65
|
end
|
126
66
|
end
|
@@ -14,20 +14,11 @@ module Apartment
|
|
14
14
|
# Default adapter when not using Postgresql Schemas
|
15
15
|
class PostgresqlAdapter < AbstractAdapter
|
16
16
|
|
17
|
-
|
17
|
+
private
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
# Catch specific adapter errors here
|
22
|
-
#
|
23
|
-
# @param {String} database Database name
|
24
|
-
#
|
25
|
-
def connect_to_new(database)
|
26
|
-
super
|
27
|
-
rescue PGError
|
28
|
-
raise DatabaseNotFound, "Cannot find database #{environmentify(database)}"
|
19
|
+
def rescue_from
|
20
|
+
PGError
|
29
21
|
end
|
30
|
-
|
31
22
|
end
|
32
23
|
|
33
24
|
# Separate Adapter for Postgresql when using schemas
|
@@ -40,7 +31,7 @@ module Apartment
|
|
40
31
|
def drop(database)
|
41
32
|
Apartment.connection.execute(%{DROP SCHEMA "#{database}" CASCADE})
|
42
33
|
|
43
|
-
rescue
|
34
|
+
rescue *rescuable_exceptions
|
44
35
|
raise SchemaNotFound, "The schema #{database.inspect} cannot be found."
|
45
36
|
end
|
46
37
|
|
@@ -49,13 +40,6 @@ module Apartment
|
|
49
40
|
#
|
50
41
|
def process_excluded_models
|
51
42
|
Apartment.excluded_models.each do |excluded_model|
|
52
|
-
# Note that due to rails reloading, we now take string references to classes rather than
|
53
|
-
# actual object references. This way when we contantize, we always get the proper class reference
|
54
|
-
if excluded_model.is_a? Class
|
55
|
-
warn "[Deprecation Warning] Passing class references to excluded models is now deprecated, please use a string instead"
|
56
|
-
excluded_model = excluded_model.name
|
57
|
-
end
|
58
|
-
|
59
43
|
excluded_model.constantize.tap do |klass|
|
60
44
|
# some models (such as delayed_job) seem to load and cache their column names before this,
|
61
45
|
# so would never get the default prefix, so reset first
|
@@ -89,11 +73,12 @@ module Apartment
|
|
89
73
|
#
|
90
74
|
def connect_to_new(database = nil)
|
91
75
|
return reset if database.nil?
|
76
|
+
raise ActiveRecord::StatementInvalid.new unless Apartment.connection.schema_exists? database
|
92
77
|
|
93
78
|
@current_database = database.to_s
|
94
79
|
Apartment.connection.schema_search_path = full_search_path
|
95
80
|
|
96
|
-
rescue
|
81
|
+
rescue *rescuable_exceptions
|
97
82
|
raise SchemaNotFound, "One of the following schema(s) is invalid: #{full_search_path}"
|
98
83
|
end
|
99
84
|
|
@@ -102,7 +87,7 @@ module Apartment
|
|
102
87
|
def create_database(database)
|
103
88
|
Apartment.connection.execute(%{CREATE SCHEMA "#{database}"})
|
104
89
|
|
105
|
-
rescue
|
90
|
+
rescue *rescuable_exceptions
|
106
91
|
raise SchemaExists, "The schema #{database} already exists."
|
107
92
|
end
|
108
93
|
|
@@ -116,4 +101,4 @@ module Apartment
|
|
116
101
|
end
|
117
102
|
end
|
118
103
|
end
|
119
|
-
end
|
104
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Apartment
|
2
|
+
module Database
|
3
|
+
def self.sqlite3_adapter(config)
|
4
|
+
Adapters::Sqlite3Adapter.new(config)
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
module Adapters
|
9
|
+
class Sqlite3Adapter < AbstractAdapter
|
10
|
+
def initialize(config)
|
11
|
+
@default_dir = File.expand_path(File.dirname(config[:database]))
|
12
|
+
|
13
|
+
super
|
14
|
+
end
|
15
|
+
|
16
|
+
def drop(database)
|
17
|
+
raise DatabaseNotFound,
|
18
|
+
"The database #{environmentify(database)} cannot be found." unless File.exists?(database_file(database))
|
19
|
+
|
20
|
+
File.delete(database_file(database))
|
21
|
+
end
|
22
|
+
|
23
|
+
def current_database
|
24
|
+
File.basename(Apartment.connection.instance_variable_get(:@config)[:database], '.sqlite3')
|
25
|
+
end
|
26
|
+
|
27
|
+
protected
|
28
|
+
|
29
|
+
def connect_to_new(database)
|
30
|
+
raise DatabaseNotFound,
|
31
|
+
"The database #{environmentify(database)} cannot be found." unless File.exists?(database_file(database))
|
32
|
+
|
33
|
+
super database_file(database)
|
34
|
+
end
|
35
|
+
|
36
|
+
def create_database(database)
|
37
|
+
raise DatabaseExists,
|
38
|
+
"The database #{environmentify(database)} already exists." if File.exists?(database_file(database))
|
39
|
+
|
40
|
+
f = File.new(database_file(database), File::CREAT)
|
41
|
+
f.close
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def database_file(database)
|
47
|
+
"#{@default_dir}/#{database}.sqlite3"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -1,14 +1,15 @@
|
|
1
1
|
module Apartment
|
2
2
|
module Elevators
|
3
|
-
# Provides a rack based db switching solution based on
|
4
|
-
#
|
3
|
+
# Provides a rack based db switching solution based on the first subdomain
|
4
|
+
# of a given domain name.
|
5
|
+
# eg:
|
6
|
+
# - example1.domain.com => example1
|
7
|
+
# - example2.something.domain.com => example2
|
5
8
|
class FirstSubdomain < Subdomain
|
6
9
|
|
7
10
|
def parse_database_name(request)
|
8
|
-
|
9
|
-
subdomain && subdomain.match(/(\w+)(\.\w+)?/)[1]
|
11
|
+
super.split('.')[0]
|
10
12
|
end
|
11
|
-
|
12
13
|
end
|
13
14
|
end
|
14
15
|
end
|
data/lib/apartment/version.rb
CHANGED
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'apartment/adapters/sqlite3_adapter'
|
3
|
+
|
4
|
+
describe Apartment::Adapters::Sqlite3Adapter do
|
5
|
+
unless defined?(JRUBY_VERSION)
|
6
|
+
|
7
|
+
let(:config){ Apartment::Test.config['connections']['sqlite'].symbolize_keys }
|
8
|
+
subject{ Apartment::Database.sqlite3_adapter config }
|
9
|
+
|
10
|
+
context "using connections" do
|
11
|
+
def database_names
|
12
|
+
db_dir = File.expand_path("../../dummy/db", __FILE__)
|
13
|
+
Dir.glob("#{db_dir}/*.sqlite3").map { |file| File.basename(file, '.sqlite3') }
|
14
|
+
end
|
15
|
+
|
16
|
+
let(:default_database) do
|
17
|
+
subject.process { File.basename(Apartment::Test.config['connections']['sqlite']['database'], '.sqlite3') }
|
18
|
+
end
|
19
|
+
|
20
|
+
it_should_behave_like "a generic apartment adapter"
|
21
|
+
it_should_behave_like "a connection based apartment adapter"
|
22
|
+
|
23
|
+
after(:all) do
|
24
|
+
File.delete(Apartment::Test.config['connections']['sqlite']['database'])
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -43,18 +43,28 @@ describe Apartment::Delayed do
|
|
43
43
|
user.database.should == database
|
44
44
|
end
|
45
45
|
|
46
|
-
|
47
|
-
|
48
|
-
|
46
|
+
context 'when there are defined callbacks' do
|
47
|
+
before do
|
48
|
+
User.class_eval do
|
49
|
+
after_find :set_name
|
50
|
+
|
51
|
+
def set_name
|
52
|
+
self.name = "Some Name"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
49
56
|
|
50
|
-
|
51
|
-
|
57
|
+
after do
|
58
|
+
User.class_eval do
|
59
|
+
reset_callbacks :find
|
52
60
|
end
|
53
61
|
end
|
54
62
|
|
55
|
-
|
56
|
-
|
57
|
-
|
63
|
+
it "should not overwrite any previous after_initialize declarations" do
|
64
|
+
user = User.first
|
65
|
+
user.database.should == database
|
66
|
+
user.name.should == "Some Name"
|
67
|
+
end
|
58
68
|
end
|
59
69
|
|
60
70
|
it "should set the db on a new record before it saves" do
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'query caching' do
|
4
|
+
before do
|
5
|
+
Apartment.configure do |config|
|
6
|
+
config.excluded_models = ["Company"]
|
7
|
+
config.database_names = lambda{ Company.scoped.collect(&:database) }
|
8
|
+
end
|
9
|
+
|
10
|
+
db_names.each do |db_name|
|
11
|
+
Apartment::Database.create(db_name)
|
12
|
+
Company.create :database => db_name
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
after do
|
17
|
+
db_names.each{ |db| Apartment::Database.drop(db) }
|
18
|
+
Company.delete_all
|
19
|
+
end
|
20
|
+
|
21
|
+
let(:db_names) { 2.times.map{ Apartment::Test.next_db } }
|
22
|
+
|
23
|
+
it 'clears the ActiveRecord::QueryCache after switching databases' do
|
24
|
+
db_names.each do |db_name|
|
25
|
+
Apartment::Database.switch db_name
|
26
|
+
User.create! name: db_name
|
27
|
+
end
|
28
|
+
|
29
|
+
ActiveRecord::Base.connection.enable_query_cache!
|
30
|
+
|
31
|
+
Apartment::Database.switch db_names.first
|
32
|
+
User.find_by_name(db_names.first).name.should == db_names.first
|
33
|
+
|
34
|
+
Apartment::Database.switch db_names.last
|
35
|
+
User.find_by_name(db_names.first).should be_nil
|
36
|
+
end
|
37
|
+
end
|
metadata
CHANGED
@@ -1,50 +1,51 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: apartment
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
|
4
|
+
version: 0.21.1
|
5
|
+
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Ryan Brunner
|
9
9
|
- Brad Robertson
|
10
|
-
autorequire:
|
10
|
+
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2013-
|
13
|
+
date: 2013-05-31 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activerecord
|
17
|
-
|
17
|
+
requirement: !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
18
19
|
requirements:
|
19
|
-
- -
|
20
|
+
- - ! '>='
|
20
21
|
- !ruby/object:Gem::Version
|
21
22
|
version: 3.1.2
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
22
26
|
none: false
|
23
|
-
requirement: !ruby/object:Gem::Requirement
|
24
27
|
requirements:
|
25
|
-
- -
|
28
|
+
- - ! '>='
|
26
29
|
- !ruby/object:Gem::Version
|
27
30
|
version: 3.1.2
|
28
|
-
none: false
|
29
|
-
prerelease: false
|
30
|
-
type: :runtime
|
31
31
|
- !ruby/object:Gem::Dependency
|
32
32
|
name: rack
|
33
|
-
|
33
|
+
requirement: !ruby/object:Gem::Requirement
|
34
|
+
none: false
|
34
35
|
requirements:
|
35
|
-
- -
|
36
|
+
- - ! '>='
|
36
37
|
- !ruby/object:Gem::Version
|
37
38
|
version: 1.3.6
|
39
|
+
type: :runtime
|
40
|
+
prerelease: false
|
41
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
42
|
none: false
|
39
|
-
requirement: !ruby/object:Gem::Requirement
|
40
43
|
requirements:
|
41
|
-
- -
|
44
|
+
- - ! '>='
|
42
45
|
- !ruby/object:Gem::Version
|
43
46
|
version: 1.3.6
|
44
|
-
|
45
|
-
|
46
|
-
type: :runtime
|
47
|
-
description: Apartment allows Rack applications to deal with database multitenancy through ActiveRecord
|
47
|
+
description: Apartment allows Rack applications to deal with database multitenancy
|
48
|
+
through ActiveRecord
|
48
49
|
email:
|
49
50
|
- ryan@influitive.com
|
50
51
|
- brad@influitive.com
|
@@ -52,12 +53,12 @@ executables: []
|
|
52
53
|
extensions: []
|
53
54
|
extra_rdoc_files: []
|
54
55
|
files:
|
55
|
-
-
|
56
|
-
-
|
57
|
-
-
|
58
|
-
-
|
59
|
-
-
|
60
|
-
-
|
56
|
+
- .gitignore
|
57
|
+
- .pryrc
|
58
|
+
- .rspec
|
59
|
+
- .rvmrc
|
60
|
+
- .travis.yml
|
61
|
+
- .vagrant
|
61
62
|
- Cheffile
|
62
63
|
- Cheffile.lock
|
63
64
|
- Gemfile
|
@@ -75,6 +76,7 @@ files:
|
|
75
76
|
- lib/apartment/adapters/mysql2_adapter.rb
|
76
77
|
- lib/apartment/adapters/postgis_adapter.rb
|
77
78
|
- lib/apartment/adapters/postgresql_adapter.rb
|
79
|
+
- lib/apartment/adapters/sqlite3_adapter.rb
|
78
80
|
- lib/apartment/console.rb
|
79
81
|
- lib/apartment/database.rb
|
80
82
|
- lib/apartment/delayed_job/enqueue.rb
|
@@ -100,6 +102,7 @@ files:
|
|
100
102
|
- spec/adapters/jdbc_postgresql_adapter_spec.rb
|
101
103
|
- spec/adapters/mysql2_adapter_spec.rb
|
102
104
|
- spec/adapters/postgresql_adapter_spec.rb
|
105
|
+
- spec/adapters/sqlite3_adapter_spec.rb
|
103
106
|
- spec/apartment_spec.rb
|
104
107
|
- spec/config/database.yml.sample
|
105
108
|
- spec/database_spec.rb
|
@@ -148,6 +151,7 @@ files:
|
|
148
151
|
- spec/integration/middleware/first_subdomain_elevator_spec.rb
|
149
152
|
- spec/integration/middleware/generic_elevator_spec.rb
|
150
153
|
- spec/integration/middleware/subdomain_elevator_spec.rb
|
154
|
+
- spec/integration/query_caching_spec.rb
|
151
155
|
- spec/spec_helper.rb
|
152
156
|
- spec/support/apartment_helpers.rb
|
153
157
|
- spec/support/capybara_sessions.rb
|
@@ -163,34 +167,32 @@ files:
|
|
163
167
|
homepage: https://github.com/influitive/apartment
|
164
168
|
licenses:
|
165
169
|
- MIT
|
166
|
-
post_install_message:
|
170
|
+
post_install_message:
|
167
171
|
rdoc_options: []
|
168
172
|
require_paths:
|
169
173
|
- lib
|
170
174
|
required_ruby_version: !ruby/object:Gem::Requirement
|
175
|
+
none: false
|
171
176
|
requirements:
|
172
|
-
- -
|
177
|
+
- - ! '>='
|
173
178
|
- !ruby/object:Gem::Version
|
179
|
+
version: '0'
|
174
180
|
segments:
|
175
181
|
- 0
|
176
|
-
hash:
|
177
|
-
version: !binary |-
|
178
|
-
MA==
|
179
|
-
none: false
|
182
|
+
hash: 2789245529283699970
|
180
183
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
184
|
+
none: false
|
181
185
|
requirements:
|
182
|
-
- -
|
186
|
+
- - ! '>='
|
183
187
|
- !ruby/object:Gem::Version
|
188
|
+
version: '0'
|
184
189
|
segments:
|
185
190
|
- 0
|
186
|
-
hash:
|
187
|
-
version: !binary |-
|
188
|
-
MA==
|
189
|
-
none: false
|
191
|
+
hash: 2789245529283699970
|
190
192
|
requirements: []
|
191
|
-
rubyforge_project:
|
192
|
-
rubygems_version: 1.8.
|
193
|
-
signing_key:
|
193
|
+
rubyforge_project:
|
194
|
+
rubygems_version: 1.8.25
|
195
|
+
signing_key:
|
194
196
|
specification_version: 3
|
195
197
|
summary: A Ruby gem for managing database multitenancy
|
196
198
|
test_files:
|
@@ -198,6 +200,7 @@ test_files:
|
|
198
200
|
- spec/adapters/jdbc_postgresql_adapter_spec.rb
|
199
201
|
- spec/adapters/mysql2_adapter_spec.rb
|
200
202
|
- spec/adapters/postgresql_adapter_spec.rb
|
203
|
+
- spec/adapters/sqlite3_adapter_spec.rb
|
201
204
|
- spec/apartment_spec.rb
|
202
205
|
- spec/config/database.yml.sample
|
203
206
|
- spec/database_spec.rb
|
@@ -246,6 +249,7 @@ test_files:
|
|
246
249
|
- spec/integration/middleware/first_subdomain_elevator_spec.rb
|
247
250
|
- spec/integration/middleware/generic_elevator_spec.rb
|
248
251
|
- spec/integration/middleware/subdomain_elevator_spec.rb
|
252
|
+
- spec/integration/query_caching_spec.rb
|
249
253
|
- spec/spec_helper.rb
|
250
254
|
- spec/support/apartment_helpers.rb
|
251
255
|
- spec/support/capybara_sessions.rb
|