apartment 0.11.0 → 0.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/HISTORY.md +8 -0
- data/lib/apartment.rb +1 -1
- data/lib/apartment/adapters/abstract_adapter.rb +3 -0
- data/lib/apartment/adapters/postgresql_adapter.rb +28 -10
- data/lib/apartment/console.rb +12 -0
- data/lib/apartment/database.rb +43 -35
- data/lib/apartment/railtie.rb +34 -13
- data/lib/apartment/reloader.rb +23 -0
- data/lib/apartment/version.rb +1 -1
- data/spec/integration/database_integration_spec.rb +7 -2
- data/spec/spec_helper.rb +2 -2
- data/spec/support/apartment_helpers.rb +0 -7
- data/spec/unit/config_spec.rb +0 -6
- data/spec/unit/reloader_spec.rb +22 -0
- metadata +6 -3
data/HISTORY.md
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
# 0.11.1
|
2
|
+
* Sep 22, 2011
|
3
|
+
|
4
|
+
- Better use of Railties for initializing apartment
|
5
|
+
- The following changes were necessary as I haven't figured out how to properly hook into Rails reloading
|
6
|
+
- Added reloader middleware in development to init Apartment on each request
|
7
|
+
- Override `reload!` in console to also init Apartment
|
8
|
+
|
1
9
|
# 0.11.0
|
2
10
|
* Sep 20, 2011
|
3
11
|
|
data/lib/apartment.rb
CHANGED
@@ -9,7 +9,6 @@ module Apartment
|
|
9
9
|
# configure apartment with available options
|
10
10
|
def configure
|
11
11
|
yield self if block_given?
|
12
|
-
Database.init
|
13
12
|
end
|
14
13
|
|
15
14
|
# Be careful not to use `return` here so both Proc and lambda can be used without breaking
|
@@ -30,6 +29,7 @@ module Apartment
|
|
30
29
|
|
31
30
|
autoload :Database, 'apartment/database'
|
32
31
|
autoload :Migrator, 'apartment/migrator'
|
32
|
+
autoload :Reloader, 'apartment/reloader'
|
33
33
|
|
34
34
|
module Adapters
|
35
35
|
autoload :AbstractAdapter, 'apartment/adapters/abstract_adapter'
|
@@ -46,6 +46,7 @@ module Apartment
|
|
46
46
|
current_db = current_database
|
47
47
|
switch(database)
|
48
48
|
yield if block_given?
|
49
|
+
|
49
50
|
ensure
|
50
51
|
switch(current_db)
|
51
52
|
end
|
@@ -87,6 +88,8 @@ module Apartment
|
|
87
88
|
database
|
88
89
|
end
|
89
90
|
|
91
|
+
# Load the rails seed file into the db
|
92
|
+
#
|
90
93
|
def seed_data
|
91
94
|
load_or_abort("#{Rails.root}/db/seeds.rb")
|
92
95
|
end
|
@@ -7,6 +7,7 @@ module Apartment
|
|
7
7
|
Adapters::PostgresqlSchemaAdapter.new(config, :schema_search_path => ActiveRecord::Base.connection.schema_search_path) :
|
8
8
|
Adapters::PostgresqlAdapter.new(config)
|
9
9
|
end
|
10
|
+
|
10
11
|
end
|
11
12
|
|
12
13
|
module Adapters
|
@@ -18,15 +19,18 @@ module Apartment
|
|
18
19
|
# Separate Adapter for Postgresql when using schemas
|
19
20
|
class PostgresqlSchemaAdapter < AbstractAdapter
|
20
21
|
|
21
|
-
#
|
22
|
-
#
|
22
|
+
# Set schema path or connect to new db
|
23
|
+
#
|
23
24
|
def connect_to_new(database = nil)
|
24
25
|
return reset if database.nil?
|
25
26
|
ActiveRecord::Base.connection.schema_search_path = database
|
27
|
+
|
26
28
|
rescue ActiveRecord::StatementInvalid => e
|
27
29
|
raise SchemaNotFound, "The Schema #{database.inspect} cannot be found."
|
28
30
|
end
|
29
31
|
|
32
|
+
# Create a db schema
|
33
|
+
#
|
30
34
|
def create(database)
|
31
35
|
ActiveRecord::Base.connection.execute("CREATE SCHEMA #{database}")
|
32
36
|
|
@@ -36,10 +40,15 @@ module Apartment
|
|
36
40
|
# Seed data if appropriate
|
37
41
|
seed_data if Apartment.seed_after_create
|
38
42
|
end
|
43
|
+
|
39
44
|
rescue ActiveRecord::StatementInvalid => e
|
40
45
|
raise SchemaExists, "The schema #{database} already exists."
|
41
46
|
end
|
42
47
|
|
48
|
+
# Get the current schema search path
|
49
|
+
#
|
50
|
+
# @return {String} current schema search path
|
51
|
+
#
|
43
52
|
def current_database
|
44
53
|
ActiveRecord::Base.connection.schema_search_path
|
45
54
|
end
|
@@ -47,17 +56,26 @@ module Apartment
|
|
47
56
|
# Set the table_name to always use the public namespace for excluded models
|
48
57
|
#
|
49
58
|
def process_excluded_models
|
50
|
-
|
59
|
+
|
51
60
|
Apartment.excluded_models.each do |excluded_model|
|
52
|
-
|
53
|
-
#
|
54
|
-
|
61
|
+
# Note that due to rails reloading, we now take string references to classes rather than
|
62
|
+
# actual object references. This way when we contantize, we always get the proper class reference
|
63
|
+
if excluded_model.is_a? Class
|
64
|
+
warn "[Deprecation Warning] Passing class references to excluded models is now deprecated, please use a string instead"
|
65
|
+
excluded_model = excluded_model.name
|
66
|
+
end
|
67
|
+
|
68
|
+
excluded_model.constantize.tap do |klass|
|
69
|
+
# some models (such as delayed_job) seem to load and cache their column names before this,
|
70
|
+
# so would never get the public prefix, so reset first
|
71
|
+
klass.reset_column_information
|
55
72
|
|
56
|
-
|
57
|
-
|
73
|
+
# Ensure that if a schema *was* set, we override
|
74
|
+
table_name = klass.table_name.split('.', 2).last
|
58
75
|
|
59
|
-
|
60
|
-
|
76
|
+
# Not sure why, but Delayed::Job somehow ignores table_name_prefix... so we'll just manually set table name instead
|
77
|
+
klass.table_name = "public.#{table_name}"
|
78
|
+
end
|
61
79
|
end
|
62
80
|
end
|
63
81
|
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# A workaraound to get `reload!` to also call Apartment::Database.init
|
2
|
+
# This is unfortunate, but I haven't figured out how to hook into the reload process *after* files are reloaded
|
3
|
+
|
4
|
+
# reloads the environment
|
5
|
+
def reload!(print=true)
|
6
|
+
puts "Reloading..." if print
|
7
|
+
# This triggers the to_prepare callbacks
|
8
|
+
ActionDispatch::Callbacks.new(Proc.new {}, false).call({})
|
9
|
+
# Manually init Apartment again once classes are reloaded
|
10
|
+
Apartment::Database.init
|
11
|
+
true
|
12
|
+
end
|
data/lib/apartment/database.rb
CHANGED
@@ -1,49 +1,57 @@
|
|
1
1
|
require 'active_support/core_ext/module/delegation'
|
2
2
|
|
3
3
|
module Apartment
|
4
|
+
|
5
|
+
# The main entry point to Apartment functions
|
4
6
|
module Database
|
5
7
|
|
6
|
-
|
8
|
+
extend self
|
7
9
|
|
8
|
-
|
9
|
-
delegate :create, :current_database, :process, :process_excluded_models, :reset, :seed, :switch, :to => :adapter
|
10
|
+
delegate :create, :current_database, :process, :process_excluded_models, :reset, :seed, :switch, :to => :adapter
|
10
11
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
12
|
+
# Initialize Apartment config options such as excluded_models
|
13
|
+
#
|
14
|
+
def init
|
15
|
+
process_excluded_models
|
16
|
+
end
|
17
|
+
|
18
|
+
# Fetch the proper multi-tenant adapter based on Rails config
|
19
|
+
#
|
20
|
+
# @return {subclass of Apartment::AbstractAdapter}
|
21
|
+
#
|
22
|
+
def adapter
|
23
|
+
@adapter ||= begin
|
24
|
+
adapter_method = "#{config[:adapter]}_adapter"
|
25
|
+
|
26
|
+
begin
|
27
|
+
require "apartment/adapters/#{adapter_method}"
|
28
|
+
rescue LoadError => e
|
29
|
+
raise "The adapter `#{config[:adapter]}` is not yet supported"
|
30
|
+
end
|
26
31
|
|
27
|
-
|
28
|
-
|
29
|
-
end
|
30
|
-
|
31
|
-
send(adapter_method, config)
|
32
|
+
unless respond_to?(adapter_method)
|
33
|
+
raise AdapterNotFound, "database configuration specifies nonexistent #{config[:adapter]} adapter"
|
32
34
|
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def reload!
|
36
|
-
@adapter = nil
|
37
|
-
@config = nil
|
38
|
-
end
|
39
35
|
|
40
|
-
|
41
|
-
|
42
|
-
def config
|
43
|
-
@config ||= Rails.configuration.database_configuration[Rails.env].symbolize_keys
|
36
|
+
send(adapter_method, config)
|
44
37
|
end
|
45
38
|
end
|
46
|
-
|
47
|
-
|
39
|
+
|
40
|
+
# Reset config and adapter so they are regenerated
|
41
|
+
#
|
42
|
+
def reload!
|
43
|
+
@adapter = nil
|
44
|
+
@config = nil
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
# Fetch the rails database configuration
|
50
|
+
#
|
51
|
+
def config
|
52
|
+
@config ||= Rails.configuration.database_configuration[Rails.env].symbolize_keys
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
48
56
|
|
49
57
|
end
|
data/lib/apartment/railtie.rb
CHANGED
@@ -3,23 +3,44 @@ require 'rails'
|
|
3
3
|
module Apartment
|
4
4
|
class Railtie < Rails::Railtie
|
5
5
|
|
6
|
-
#
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
6
|
+
# Set up our default config options
|
7
|
+
# Do this before the app initializers run so we don't override custom settings
|
8
|
+
config.before_initialize do
|
9
|
+
Apartment.configure do |config|
|
10
|
+
config.excluded_models = []
|
11
|
+
config.use_postgres_schemas = true
|
12
|
+
config.database_names = []
|
13
|
+
config.seed_after_create = false
|
14
|
+
config.prepend_environment = true
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# Hook into ActionDispatch::Reloader to ensure Apartment is properly initialized
|
19
|
+
# Note that this doens't entirely work as expected in Development, because this is called before classes are reloaded
|
20
|
+
# See the above middleware declaration to help with this. Hope to fix that soon.
|
21
|
+
config.to_prepare do
|
22
|
+
Apartment::Database.init
|
19
23
|
end
|
20
24
|
|
21
25
|
rake_tasks do
|
22
26
|
load 'tasks/apartment.rake'
|
23
27
|
end
|
28
|
+
|
29
|
+
# The following initializers are a workaround to the fact that I can't properly hook into the rails reloader
|
30
|
+
# Note this is technically valid for any environment where cache_classes is false, for us, it's just development
|
31
|
+
if Rails.env.development?
|
32
|
+
|
33
|
+
# Apartment::Reloader is middleware to initialize things properly on each requestion dev
|
34
|
+
initializer 'apartment.init' do |app|
|
35
|
+
app.config.middleware.use "Apartment::Reloader"
|
36
|
+
end
|
37
|
+
|
38
|
+
# Overrides reload! to also call Apartment::Database.init as well so that the reloaded classes have the proper table_names
|
39
|
+
console do
|
40
|
+
require 'apartment/console'
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
24
45
|
end
|
25
46
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Apartment
|
2
|
+
|
3
|
+
class Reloader
|
4
|
+
|
5
|
+
# Middleware used in development to init Apartment for each request
|
6
|
+
# Necessary due to code reload (annoying). I couldn't figure out how to properly hook into
|
7
|
+
# the Rails reload process *after* files are reloaded, so I've used this in the meantime.
|
8
|
+
#
|
9
|
+
# Note that this has one MAJOR caveat. Doing `reload!` in the console in development WILL NOT run init again
|
10
|
+
# Thus, excluded models will not be processed again and will be queried from the current_schema rather than public.
|
11
|
+
# I hope to fix this soon
|
12
|
+
def initialize(app)
|
13
|
+
@app = app
|
14
|
+
end
|
15
|
+
|
16
|
+
def call(env)
|
17
|
+
Database.init
|
18
|
+
@app.call(env)
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
data/lib/apartment/version.rb
CHANGED
@@ -29,6 +29,8 @@ describe Apartment::Database do
|
|
29
29
|
config.excluded_models = [Company]
|
30
30
|
end
|
31
31
|
|
32
|
+
Apartment::Database.init
|
33
|
+
|
32
34
|
Company.table_name.should == "public.companies"
|
33
35
|
end
|
34
36
|
|
@@ -158,8 +160,11 @@ describe Apartment::Database do
|
|
158
160
|
|
159
161
|
context "with excluded models" do
|
160
162
|
|
161
|
-
|
162
|
-
|
163
|
+
before do
|
164
|
+
Apartment.configure do |config|
|
165
|
+
config.excluded_models = [Company]
|
166
|
+
end
|
167
|
+
Apartment::Database.init
|
163
168
|
end
|
164
169
|
|
165
170
|
it "should ignore excluded models" do
|
data/spec/spec_helper.rb
CHANGED
@@ -23,8 +23,8 @@ RSpec.configure do |config|
|
|
23
23
|
config.include RSpec::Integration::CapybaraSessions, :type => :request
|
24
24
|
|
25
25
|
config.before(:all) do
|
26
|
-
# Ensure that each test starts with a clean
|
27
|
-
# Necessary as some tests will leak things like current_schema into the next
|
26
|
+
# Ensure that each test starts with a clean connection
|
27
|
+
# Necessary as some tests will leak things like current_schema into the next test
|
28
28
|
ActiveRecord::Base.clear_all_connections!
|
29
29
|
end
|
30
30
|
|
@@ -4,7 +4,6 @@ module Apartment
|
|
4
4
|
extend self
|
5
5
|
|
6
6
|
def reset
|
7
|
-
Apartment::Database.instance_variable_set :@initialized, nil
|
8
7
|
Apartment.excluded_models = nil
|
9
8
|
Apartment.use_postgres_schemas = nil
|
10
9
|
end
|
@@ -29,11 +28,5 @@ module Apartment
|
|
29
28
|
ActiveRecord::Migrator.rollback(Rails.root + ActiveRecord::Migrator.migrations_path)
|
30
29
|
end
|
31
30
|
|
32
|
-
private
|
33
|
-
|
34
|
-
def sanitize(database)
|
35
|
-
database.gsub(/[\W]/,'')
|
36
|
-
end
|
37
|
-
|
38
31
|
end
|
39
32
|
end
|
data/spec/unit/config_spec.rb
CHANGED
@@ -17,11 +17,6 @@ describe Apartment do
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
-
it "should initialize Database" do
|
21
|
-
Apartment::Database.should_receive(:init).once
|
22
|
-
Apartment.configure
|
23
|
-
end
|
24
|
-
|
25
20
|
it "should set excluded models" do
|
26
21
|
Apartment.configure do |config|
|
27
22
|
config.excluded_models = excluded_models
|
@@ -44,7 +39,6 @@ describe Apartment do
|
|
44
39
|
end
|
45
40
|
Apartment.seed_after_create.should be_true
|
46
41
|
end
|
47
|
-
|
48
42
|
|
49
43
|
context "databases" do
|
50
44
|
it "should return object if it doesnt respond_to call" do
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Apartment::Reloader do
|
4
|
+
|
5
|
+
context "using postgresql schemas" do
|
6
|
+
|
7
|
+
before do
|
8
|
+
Apartment.excluded_models = ["Company"]
|
9
|
+
Company.reset_table_name # ensure we're clean
|
10
|
+
end
|
11
|
+
|
12
|
+
subject{ Apartment::Reloader.new(mock("Rack::Application", :call => nil)) }
|
13
|
+
|
14
|
+
it "should initialize apartment when called" do
|
15
|
+
Company.table_name.should_not include('public.')
|
16
|
+
subject.call(mock('env'))
|
17
|
+
Company.table_name.should include('public.')
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
end
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: apartment
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.11.
|
5
|
+
version: 0.11.1
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Ryan Brunner
|
@@ -147,6 +147,7 @@ files:
|
|
147
147
|
- lib/apartment/adapters/abstract_adapter.rb
|
148
148
|
- lib/apartment/adapters/mysql_adapter.rb
|
149
149
|
- lib/apartment/adapters/postgresql_adapter.rb
|
150
|
+
- lib/apartment/console.rb
|
150
151
|
- lib/apartment/database.rb
|
151
152
|
- lib/apartment/delayed_job/active_record.rb
|
152
153
|
- lib/apartment/delayed_job/enqueue.rb
|
@@ -155,6 +156,7 @@ files:
|
|
155
156
|
- lib/apartment/elevators/subdomain.rb
|
156
157
|
- lib/apartment/migrator.rb
|
157
158
|
- lib/apartment/railtie.rb
|
159
|
+
- lib/apartment/reloader.rb
|
158
160
|
- lib/apartment/version.rb
|
159
161
|
- lib/tasks/apartment.rake
|
160
162
|
- spec/adapters/mysql_adapter_spec.rb
|
@@ -209,6 +211,7 @@ files:
|
|
209
211
|
- spec/unit/config_spec.rb
|
210
212
|
- spec/unit/middleware/subdomain_elevator_spec.rb
|
211
213
|
- spec/unit/migrator_spec.rb
|
214
|
+
- spec/unit/reloader_spec.rb
|
212
215
|
has_rdoc: true
|
213
216
|
homepage: http://github.com/bradrobertson/apartment
|
214
217
|
licenses:
|
@@ -223,7 +226,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
223
226
|
requirements:
|
224
227
|
- - ">="
|
225
228
|
- !ruby/object:Gem::Version
|
226
|
-
hash:
|
229
|
+
hash: 3705726283453355884
|
227
230
|
segments:
|
228
231
|
- 0
|
229
232
|
version: "0"
|
@@ -232,7 +235,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
232
235
|
requirements:
|
233
236
|
- - ">="
|
234
237
|
- !ruby/object:Gem::Version
|
235
|
-
hash:
|
238
|
+
hash: 3705726283453355884
|
236
239
|
segments:
|
237
240
|
- 0
|
238
241
|
version: "0"
|