apartment 0.13.1 → 0.14.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +4 -16
- data/Rakefile +11 -11
- data/apartment.gemspec +2 -2
- data/lib/apartment.rb +1 -5
- data/lib/apartment/adapters/abstract_adapter.rb +34 -34
- data/lib/apartment/adapters/postgresql_adapter.rb +2 -3
- data/lib/apartment/database.rb +12 -12
- data/lib/apartment/migrator.rb +11 -11
- data/lib/apartment/railtie.rb +23 -15
- data/lib/apartment/reloader.rb +5 -6
- data/lib/apartment/version.rb +1 -1
- data/lib/tasks/apartment.rake +32 -32
- data/spec/adapters/postgresql_adapter_spec.rb +0 -1
- data/spec/dummy/config/database.yml +1 -0
- data/spec/dummy/config/initializers/apartment.rb +4 -0
- data/spec/dummy/db/migrate/20110613152810_create_dummy_models.rb +1 -0
- data/spec/dummy/db/migrate/20111202022214_create_table_books.rb +13 -0
- data/spec/dummy/db/schema.rb +7 -1
- data/spec/integration/apartment_rake_integration_spec.rb +17 -12
- metadata +9 -10
data/README.md
CHANGED
@@ -1,16 +1,6 @@
|
|
1
1
|
# Apartment
|
2
2
|
*Multitenancy for Rails 3*
|
3
3
|
|
4
|
-
> IMPORTANT! While I will do everything possible to get Apartment working for Rails 3.1, I haven't, as of yet, had this opportunity.
|
5
|
-
|
6
|
-
> There have been significant changes in the adapters such as prepared statements that might cause some issues.
|
7
|
-
|
8
|
-
> If anyone is successfully using Apartment with 3.1 please let me know, but please ensure that you're testing data integrity properly (ie. that queries are made in the right schema) as prepared_statements
|
9
|
-
> could really throw a wrench in that one.
|
10
|
-
|
11
|
-
> I know for a fact that Rails 3.1 missed a patch to make postgresql more schema aware, but it seems to have made it into Rails 3.1.1. So at the very least, use 3.1.1
|
12
|
-
|
13
|
-
|
14
4
|
Apartment provides tools to help you deal with multiple databases in your Rails
|
15
5
|
application. If you need to have certain data sequestered based on account or company,
|
16
6
|
but still allow some data to exist in a common database, Apartment can help.
|
@@ -129,11 +119,7 @@ from `Apartment.database_names`
|
|
129
119
|
|
130
120
|
### Delayed::Job
|
131
121
|
|
132
|
-
In
|
133
|
-
is part of the ignored models. I have to look into this further, but until then use `Apartment::Delayed::Job.enqueue` to ensure that queues are placed in the public schema
|
134
|
-
|
135
|
-
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
|
136
|
-
that a `database` attribute 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:
|
122
|
+
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:
|
137
123
|
|
138
124
|
class SomeModel < ActiveRecord::Base
|
139
125
|
include Apartment::Delayed::Requirements
|
@@ -151,8 +137,10 @@ that a `database` attribute is set on this model *before* it is serialized, to e
|
|
151
137
|
end
|
152
138
|
end
|
153
139
|
|
154
|
-
##
|
140
|
+
## Development
|
155
141
|
|
142
|
+
* The Local setup for development assumes that a root user with no password exists for both mysql and postgresl
|
143
|
+
* Rake tasks (see the Rakefile) will help you setup your dbs necessary to run tests
|
156
144
|
* Please issue pull requests to the `development` branch. All development happens here, master is used for releases
|
157
145
|
* Ensure that your code is accompanied with tests. No code will be merged without tests
|
158
146
|
|
data/Rakefile
CHANGED
@@ -5,28 +5,28 @@ Bundler::GemHelper.install_tasks
|
|
5
5
|
require "rspec"
|
6
6
|
require "rspec/core/rake_task"
|
7
7
|
|
8
|
-
RSpec::Core::RakeTask.new(:spec) do |spec|
|
8
|
+
RSpec::Core::RakeTask.new(:spec => "db:test:prepare") do |spec|
|
9
9
|
spec.pattern = "spec/**/*_spec.rb"
|
10
10
|
end
|
11
11
|
|
12
12
|
namespace :spec do
|
13
13
|
|
14
14
|
[:tasks, :unit, :adapters, :integration].each do |type|
|
15
|
-
RSpec::Core::RakeTask.new(type) do |spec|
|
15
|
+
RSpec::Core::RakeTask.new(type => :spec) do |spec|
|
16
16
|
spec.pattern = "spec/#{type}/**/*_spec.rb"
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
-
namespace :unit do
|
21
|
-
RSpec::Core::RakeTask.new(:adapters) do |spec|
|
22
|
-
spec.pattern = "spec/unit/adapters/**/*_spec.rb"
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
20
|
end
|
27
21
|
|
28
22
|
task :default => :spec
|
29
23
|
|
24
|
+
namespace :db do
|
25
|
+
namespace :test do
|
26
|
+
task :prepare => %w{postgres:drop_db postgres:build_db mysql:drop_db mysql:build_db}
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
30
|
namespace :postgres do
|
31
31
|
require 'active_record'
|
32
32
|
require "#{File.join(File.dirname(__FILE__), 'spec', 'support', 'config')}"
|
@@ -35,7 +35,7 @@ namespace :postgres do
|
|
35
35
|
task :build_db do
|
36
36
|
%x{ createdb -E UTF8 #{pg_config['database']} } rescue "test db already exists"
|
37
37
|
ActiveRecord::Base.establish_connection pg_config
|
38
|
-
|
38
|
+
ActiveRecord::Migrator.migrate('spec/dummy/db/migrate')
|
39
39
|
end
|
40
40
|
|
41
41
|
desc "drop the PostgreSQL test database"
|
@@ -54,13 +54,13 @@ namespace :mysql do
|
|
54
54
|
task :build_db do
|
55
55
|
%x{ mysqladmin -u root create #{my_config['database']} } rescue "test db already exists"
|
56
56
|
ActiveRecord::Base.establish_connection my_config
|
57
|
-
|
57
|
+
ActiveRecord::Migrator.migrate('spec/dummy/db/migrate')
|
58
58
|
end
|
59
59
|
|
60
60
|
desc "drop the MySQL test database"
|
61
61
|
task :drop_db do
|
62
62
|
puts "dropping database #{my_config['database']}"
|
63
|
-
%x{ mysqladmin -u root drop #{my_config['database']} }
|
63
|
+
%x{ mysqladmin -u root drop #{my_config['database']} --force}
|
64
64
|
end
|
65
65
|
|
66
66
|
end
|
data/apartment.gemspec
CHANGED
@@ -18,14 +18,14 @@ Gem::Specification.new do |s|
|
|
18
18
|
s.require_paths = ["lib"]
|
19
19
|
s.rubygems_version = %q{1.3.7}
|
20
20
|
|
21
|
-
s.add_dependency 'rails', '~> 3.1.
|
21
|
+
s.add_dependency 'rails', '~> 3.1.2'
|
22
22
|
s.add_development_dependency 'rake', '~> 0.8.7'
|
23
23
|
s.add_development_dependency 'sqlite3'
|
24
24
|
s.add_development_dependency 'rspec', '~> 2.6.0'
|
25
25
|
s.add_development_dependency 'rspec-rails', '~> 2.6.1'
|
26
26
|
s.add_development_dependency 'capybara', '1.0.0'
|
27
27
|
s.add_development_dependency 'pg', '~> 0.11.0'
|
28
|
-
s.add_development_dependency 'mysql2', '0.
|
28
|
+
s.add_development_dependency 'mysql2', '~> 0.3.7'
|
29
29
|
s.add_development_dependency "silent-postgres", "~> 0.1.1"
|
30
30
|
s.add_development_dependency 'delayed_job', '~> 2.1.4'
|
31
31
|
end
|
data/lib/apartment.rb
CHANGED
@@ -13,11 +13,7 @@ module Apartment
|
|
13
13
|
|
14
14
|
# Be careful not to use `return` here so both Proc and lambda can be used without breaking
|
15
15
|
def database_names
|
16
|
-
|
17
|
-
@database_names.call
|
18
|
-
else
|
19
|
-
@database_names
|
20
|
-
end
|
16
|
+
@database_names.respond_to?(:call) ? @database_names.call : @database_names
|
21
17
|
end
|
22
18
|
|
23
19
|
# Default to none
|
@@ -49,7 +49,7 @@ module Apartment
|
|
49
49
|
ActiveRecord::Base.connection.execute("DROP DATABASE #{environmentify(database)}" )
|
50
50
|
|
51
51
|
rescue ActiveRecord::StatementInvalid => e
|
52
|
-
|
52
|
+
raise DatabaseNotFound, "The database #{environmentify(database)} cannot be found"
|
53
53
|
end
|
54
54
|
|
55
55
|
# Prepend the environment if configured and the environment isn't already there
|
@@ -59,35 +59,35 @@ module Apartment
|
|
59
59
|
#
|
60
60
|
def environmentify(database)
|
61
61
|
Apartment.prepend_environment && !database.include?(Rails.env) ? "#{Rails.env}_#{database}" : database
|
62
|
-
|
63
|
-
|
62
|
+
end
|
63
|
+
|
64
64
|
# Connect to db, do your biz, switch back to previous db
|
65
65
|
#
|
66
66
|
# @param {String?} database Database or schema to connect to
|
67
67
|
#
|
68
68
|
def process(database = nil)
|
69
69
|
current_db = current_database
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
70
|
+
switch(database)
|
71
|
+
yield if block_given?
|
72
|
+
|
73
|
+
ensure
|
74
|
+
switch(current_db) rescue reset
|
75
|
+
end
|
76
|
+
|
77
|
+
# Establish a new connection for each specific excluded model
|
78
78
|
#
|
79
79
|
def process_excluded_models
|
80
80
|
# All other models will shared a connection (at ActiveRecord::Base) and we can modify at will
|
81
|
-
|
82
|
-
|
81
|
+
Apartment.excluded_models.each do |excluded_model|
|
82
|
+
# Note that due to rails reloading, we now take string references to classes rather than
|
83
83
|
# actual object references. This way when we contantize, we always get the proper class reference
|
84
84
|
if excluded_model.is_a? Class
|
85
85
|
warn "[Deprecation Warning] Passing class references to excluded models is now deprecated, please use a string instead"
|
86
86
|
excluded_model = excluded_model.name
|
87
87
|
end
|
88
88
|
|
89
|
-
|
90
|
-
|
89
|
+
excluded_model.constantize.establish_connection @config
|
90
|
+
end
|
91
91
|
end
|
92
92
|
|
93
93
|
# Reset the database connection to the default
|
@@ -102,17 +102,17 @@ module Apartment
|
|
102
102
|
#
|
103
103
|
def switch(database = nil)
|
104
104
|
# Just connect to default db and return
|
105
|
-
|
105
|
+
return reset if database.nil?
|
106
106
|
|
107
107
|
connect_to_new(database)
|
108
|
-
|
108
|
+
end
|
109
109
|
|
110
110
|
# Load the rails seed file into the db
|
111
111
|
#
|
112
|
-
|
113
|
-
|
112
|
+
def seed_data
|
113
|
+
silence_stream(STDOUT){ load_or_abort("#{Rails.root}/db/seeds.rb") } # Don't log the output of seeding the db
|
114
114
|
end
|
115
|
-
|
115
|
+
alias_method :seed, :seed_data
|
116
116
|
|
117
117
|
protected
|
118
118
|
|
@@ -137,22 +137,22 @@ module Apartment
|
|
137
137
|
|
138
138
|
rescue ActiveRecord::StatementInvalid => e
|
139
139
|
raise DatabaseNotFound, "The database #{environmentify(database)} cannot be found."
|
140
|
-
|
140
|
+
end
|
141
141
|
|
142
142
|
# Import the database schema
|
143
143
|
#
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
144
|
+
def import_database_schema
|
145
|
+
ActiveRecord::Schema.verbose = false # do not log schema load output.
|
146
|
+
load_or_abort("#{Rails.root}/db/schema.rb")
|
147
|
+
end
|
148
|
+
|
149
|
+
# Return a new config that is multi-tenanted
|
150
150
|
#
|
151
151
|
def multi_tenantify(database)
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
152
|
+
@config.clone.tap do |config|
|
153
|
+
config[:database] = environmentify(database)
|
154
|
+
end
|
155
|
+
end
|
156
156
|
|
157
157
|
# Load a file or abort if it doesn't exists
|
158
158
|
#
|
@@ -166,9 +166,9 @@ module Apartment
|
|
166
166
|
|
167
167
|
# Remove all non-alphanumeric characters
|
168
168
|
#
|
169
|
-
|
170
|
-
|
171
|
-
|
169
|
+
def sanitize(database)
|
170
|
+
warn "[Deprecation Warning] Sanitize is no longer used, client should ensure proper database names"
|
171
|
+
database.gsub(/[\W]/,'')
|
172
172
|
end
|
173
173
|
|
174
174
|
end
|
@@ -27,8 +27,8 @@ module Apartment
|
|
27
27
|
super
|
28
28
|
rescue PGError => e
|
29
29
|
raise DatabaseNotFound, "Cannot find database #{environmentify(database)}"
|
30
|
-
|
31
|
-
|
30
|
+
end
|
31
|
+
|
32
32
|
end
|
33
33
|
|
34
34
|
# Separate Adapter for Postgresql when using schemas
|
@@ -93,7 +93,6 @@ module Apartment
|
|
93
93
|
#
|
94
94
|
def connect_to_new(database = nil)
|
95
95
|
return reset if database.nil?
|
96
|
-
ActiveRecord::Base.connection.clear_cache!
|
97
96
|
ActiveRecord::Base.connection.schema_search_path = database
|
98
97
|
|
99
98
|
rescue ActiveRecord::StatementInvalid => e
|
data/lib/apartment/database.rb
CHANGED
@@ -3,15 +3,15 @@ require 'active_support/core_ext/module/delegation'
|
|
3
3
|
module Apartment
|
4
4
|
|
5
5
|
# The main entry point to Apartment functions
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
module Database
|
7
|
+
|
8
|
+
extend self
|
9
9
|
|
10
|
-
delegate :create, :current_database, :process, :process_excluded_models, :reset, :seed, :switch, :to => :adapter
|
10
|
+
delegate :create, :current_database, :drop, :process, :process_excluded_models, :reset, :seed, :switch, :to => :adapter
|
11
11
|
|
12
12
|
# Initialize Apartment config options such as excluded_models
|
13
13
|
#
|
14
|
-
|
14
|
+
def init
|
15
15
|
process_excluded_models
|
16
16
|
end
|
17
17
|
|
@@ -20,10 +20,10 @@ module Apartment
|
|
20
20
|
# @return {subclass of Apartment::AbstractAdapter}
|
21
21
|
#
|
22
22
|
def adapter
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
23
|
+
@adapter ||= begin
|
24
|
+
adapter_method = "#{config[:adapter]}_adapter"
|
25
|
+
|
26
|
+
begin
|
27
27
|
require "apartment/adapters/#{adapter_method}"
|
28
28
|
rescue LoadError => e
|
29
29
|
raise "The adapter `#{config[:adapter]}` is not yet supported"
|
@@ -44,8 +44,8 @@ module Apartment
|
|
44
44
|
@config = nil
|
45
45
|
end
|
46
46
|
|
47
|
-
|
48
|
-
|
47
|
+
private
|
48
|
+
|
49
49
|
# Fetch the rails database configuration
|
50
50
|
#
|
51
51
|
def config
|
@@ -53,5 +53,5 @@ module Apartment
|
|
53
53
|
end
|
54
54
|
|
55
55
|
end
|
56
|
-
|
56
|
+
|
57
57
|
end
|
data/lib/apartment/migrator.rb
CHANGED
@@ -5,19 +5,19 @@ module Apartment
|
|
5
5
|
extend self
|
6
6
|
|
7
7
|
# Migrate to latest
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
8
|
+
def migrate(database)
|
9
|
+
Database.process(database){ ActiveRecord::Migrator.migrate(ActiveRecord::Migrator.migrations_path) }
|
10
|
+
end
|
11
|
+
|
12
12
|
# Migrate up/down to a specific version
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
def run(direction, database, version)
|
14
|
+
Database.process(database){ ActiveRecord::Migrator.run(direction, ActiveRecord::Migrator.migrations_path, version) }
|
15
|
+
end
|
16
16
|
|
17
17
|
# rollback latest migration `step` number of times
|
18
|
-
|
19
|
-
|
20
|
-
|
18
|
+
def rollback(database, step = 1)
|
19
|
+
Database.process(database){ ActiveRecord::Migrator.rollback(ActiveRecord::Migrator.migrations_path, step) }
|
20
|
+
end
|
21
21
|
end
|
22
|
-
|
22
|
+
|
23
23
|
end
|
data/lib/apartment/railtie.rb
CHANGED
@@ -1,12 +1,14 @@
|
|
1
1
|
require 'rails'
|
2
2
|
|
3
3
|
module Apartment
|
4
|
-
|
5
|
-
|
6
|
-
#
|
7
|
-
#
|
8
|
-
|
9
|
-
|
4
|
+
class Railtie < Rails::Railtie
|
5
|
+
|
6
|
+
#
|
7
|
+
# Set up our default config options
|
8
|
+
# Do this before the app initializers run so we don't override custom settings
|
9
|
+
#
|
10
|
+
config.before_initialize do
|
11
|
+
Apartment.configure do |config|
|
10
12
|
config.excluded_models = []
|
11
13
|
config.use_postgres_schemas = true
|
12
14
|
config.database_names = []
|
@@ -18,20 +20,26 @@ module Apartment
|
|
18
20
|
# Hook into ActionDispatch::Reloader to ensure Apartment is properly initialized
|
19
21
|
# Note that this doens't entirely work as expected in Development, because this is called before classes are reloaded
|
20
22
|
# See the above middleware/console declarations below to help with this. Hope to fix that soon.
|
23
|
+
#
|
21
24
|
config.to_prepare do
|
22
25
|
Apartment::Database.init
|
23
26
|
end
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
27
|
+
|
28
|
+
#
|
29
|
+
# Ensure rake tasks are loaded
|
30
|
+
#
|
31
|
+
rake_tasks do
|
32
|
+
load 'tasks/apartment.rake'
|
33
|
+
end
|
34
|
+
|
35
|
+
#
|
36
|
+
# The following initializers are a workaround to the fact that I can't properly hook into the rails reloader
|
37
|
+
# Note this is technically valid for any environment where cache_classes is false, for us, it's just development
|
38
|
+
#
|
31
39
|
if Rails.env.development?
|
32
40
|
|
33
41
|
# Apartment::Reloader is middleware to initialize things properly on each request to dev
|
34
|
-
|
42
|
+
initializer 'apartment.init' do |app|
|
35
43
|
app.config.middleware.use "Apartment::Reloader"
|
36
44
|
end
|
37
45
|
|
@@ -42,5 +50,5 @@ module Apartment
|
|
42
50
|
|
43
51
|
end
|
44
52
|
|
45
|
-
|
53
|
+
end
|
46
54
|
end
|
data/lib/apartment/reloader.rb
CHANGED
@@ -6,18 +6,17 @@ module Apartment
|
|
6
6
|
# Necessary due to code reload (annoying). I couldn't figure out how to properly hook into
|
7
7
|
# the Rails reload process *after* files are reloaded, so I've used this in the meantime.
|
8
8
|
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
|
12
|
-
|
13
|
-
@app = app
|
9
|
+
# Also see apartment/console for the re-definition of reload! that re-init's Apartment
|
10
|
+
#
|
11
|
+
def initialize(app)
|
12
|
+
@app = app
|
14
13
|
end
|
15
14
|
|
16
15
|
def call(env)
|
17
16
|
Database.init
|
18
17
|
@app.call(env)
|
19
18
|
end
|
20
|
-
|
19
|
+
|
21
20
|
end
|
22
21
|
|
23
22
|
end
|
data/lib/apartment/version.rb
CHANGED
data/lib/tasks/apartment.rake
CHANGED
@@ -1,59 +1,59 @@
|
|
1
1
|
apartment_namespace = namespace :apartment do
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
Apartment.database_names.each do |db|
|
7
|
-
puts("Migrating #{db} database")
|
8
|
-
Apartment::Migrator.migrate db
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
desc "Seed all multi-tenant databases"
|
13
|
-
task :seed => 'db:seed' do
|
3
|
+
desc "Migrate all multi-tenant databases"
|
4
|
+
task :migrate => 'db:migrate' do
|
14
5
|
|
15
|
-
|
6
|
+
Apartment.database_names.each do |db|
|
7
|
+
puts("Migrating #{db} database")
|
8
|
+
Apartment::Migrator.migrate db
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
desc "Seed all multi-tenant databases"
|
13
|
+
task :seed => 'db:seed' do
|
14
|
+
|
15
|
+
Apartment.database_names.each do |db|
|
16
16
|
puts("Seeding #{db} database")
|
17
17
|
Apartment::Database.process(db) do
|
18
18
|
Apartment::Database.seed
|
19
19
|
end
|
20
20
|
end
|
21
21
|
end
|
22
|
-
|
23
|
-
|
22
|
+
|
23
|
+
desc "Rolls the schema back to the previous version (specify steps w/ STEP=n) across all multi-tenant dbs."
|
24
24
|
task :rollback => 'db:rollback' do
|
25
25
|
step = ENV['STEP'] ? ENV['STEP'].to_i : 1
|
26
26
|
|
27
|
-
Apartment.database_names.each do |db|
|
27
|
+
Apartment.database_names.each do |db|
|
28
28
|
puts("Rolling back #{db} database")
|
29
29
|
Apartment::Migrator.rollback db, step
|
30
30
|
end
|
31
31
|
end
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
32
|
+
|
33
|
+
namespace :migrate do
|
34
|
+
|
35
|
+
desc 'Runs the "up" for a given migration VERSION across all multi-tenant dbs.'
|
36
|
+
task :up => 'db:migrate:up' do
|
37
|
+
version = ENV['VERSION'] ? ENV['VERSION'].to_i : nil
|
38
38
|
raise 'VERSION is required' unless version
|
39
|
-
|
40
|
-
Apartment.database_names.each do |db|
|
39
|
+
|
40
|
+
Apartment.database_names.each do |db|
|
41
41
|
puts("Migrating #{db} database up")
|
42
42
|
Apartment::Migrator.run :up, db, version
|
43
43
|
end
|
44
44
|
end
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
45
|
+
|
46
|
+
desc 'Runs the "down" for a given migration VERSION across all multi-tenant dbs.'
|
47
|
+
task :down => 'db:migrate:down' do
|
48
|
+
version = ENV['VERSION'] ? ENV['VERSION'].to_i : nil
|
49
49
|
raise 'VERSION is required' unless version
|
50
|
-
|
51
|
-
Apartment.database_names.each do |db|
|
50
|
+
|
51
|
+
Apartment.database_names.each do |db|
|
52
52
|
puts("Migrating #{db} database down")
|
53
53
|
Apartment::Migrator.run :down, db, version
|
54
54
|
end
|
55
55
|
end
|
56
|
-
|
56
|
+
|
57
57
|
desc 'Rollbacks the database one migration and re migrate up (options: STEP=x, VERSION=x).'
|
58
58
|
task :redo => 'db:migrate:redo' do
|
59
59
|
if ENV['VERSION']
|
@@ -64,7 +64,7 @@ apartment_namespace = namespace :apartment do
|
|
64
64
|
apartment_namespace['migrate'].invoke
|
65
65
|
end
|
66
66
|
end
|
67
|
-
|
67
|
+
|
68
68
|
end
|
69
|
-
|
69
|
+
|
70
70
|
end
|
@@ -48,7 +48,6 @@ describe Apartment::Adapters::PostgresqlAdapter do
|
|
48
48
|
end
|
49
49
|
|
50
50
|
it "should yield to block if passed" do
|
51
|
-
Apartment::Test.migrate # ensure we have latest schema in the public
|
52
51
|
subject.drop(schema2) # so we don't get errors on creation
|
53
52
|
|
54
53
|
@count = 0 # set our variable so its visible in and outside of blocks
|
data/spec/dummy/db/schema.rb
CHANGED
@@ -11,7 +11,13 @@
|
|
11
11
|
#
|
12
12
|
# It's strongly recommended to check this file into your version control system.
|
13
13
|
|
14
|
-
ActiveRecord::Schema.define(:version =>
|
14
|
+
ActiveRecord::Schema.define(:version => 20111202022214) do
|
15
|
+
|
16
|
+
create_table "books", :force => true do |t|
|
17
|
+
t.string "name"
|
18
|
+
t.integer "pages"
|
19
|
+
t.datetime "published"
|
20
|
+
end
|
15
21
|
|
16
22
|
create_table "companies", :force => true do |t|
|
17
23
|
t.boolean "dummy"
|
@@ -3,14 +3,16 @@ require 'rake'
|
|
3
3
|
|
4
4
|
describe "apartment rake tasks" do
|
5
5
|
|
6
|
-
before :all do
|
7
|
-
Apartment::Test.migrate # ensure we have latest schema in the public
|
8
|
-
end
|
9
|
-
|
10
6
|
before do
|
11
7
|
@rake = Rake::Application.new
|
12
8
|
Rake.application = @rake
|
13
9
|
Dummy::Application.load_tasks
|
10
|
+
|
11
|
+
# somehow this misc.rake file gets lost in the shuffle
|
12
|
+
# it defines a `rails_env` task that our db:migrate depends on
|
13
|
+
# No idea why, but during the tests, we somehow lose this tasks, so we get an error when testing migrations
|
14
|
+
# This is STUPID!
|
15
|
+
load "rails/tasks/misc.rake"
|
14
16
|
end
|
15
17
|
|
16
18
|
after do
|
@@ -25,23 +27,25 @@ describe "apartment rake tasks" do
|
|
25
27
|
end
|
26
28
|
|
27
29
|
context "with x number of databases" do
|
30
|
+
|
31
|
+
let(:x){ 1 + rand(5) } # random number of dbs to create
|
32
|
+
let(:db_names){ x.times.map{|y| "database_#{y}" } }
|
33
|
+
|
28
34
|
before do
|
29
|
-
|
30
|
-
|
31
|
-
@db_names << db_name = "schema_#{x}"
|
32
|
-
Apartment::Database.create db_name
|
35
|
+
db_names.collect do |db_name|
|
36
|
+
Apartment::Database.create(db_name)
|
33
37
|
Company.create :database => db_name
|
34
38
|
end
|
35
39
|
end
|
36
40
|
|
37
41
|
after do
|
38
|
-
|
42
|
+
db_names.each{ |db| Apartment::Database.drop(db) }
|
39
43
|
Company.delete_all
|
40
44
|
end
|
41
45
|
|
42
46
|
describe "#migrate" do
|
43
47
|
it "should migrate all databases" do
|
44
|
-
Apartment::Migrator.should_receive(:migrate).exactly(
|
48
|
+
Apartment::Migrator.should_receive(:migrate).exactly(db_names.length).times
|
45
49
|
|
46
50
|
@rake['apartment:migrate'].invoke
|
47
51
|
end
|
@@ -49,17 +53,18 @@ describe "apartment rake tasks" do
|
|
49
53
|
|
50
54
|
describe "#rollback" do
|
51
55
|
it "should rollback all dbs" do
|
52
|
-
|
56
|
+
db_names.each do |name|
|
53
57
|
Apartment::Migrator.should_receive(:rollback).with(name, anything)
|
54
58
|
end
|
55
59
|
|
56
60
|
@rake['apartment:rollback'].invoke
|
61
|
+
@rake['apartment:migrate'].invoke # migrate again so that our next test 'seed' can run (requires migrations to be complete)
|
57
62
|
end
|
58
63
|
end
|
59
64
|
|
60
65
|
describe "apartment:seed" do
|
61
66
|
it "should seed all databases" do
|
62
|
-
Apartment::Database.should_receive(:seed).exactly(
|
67
|
+
Apartment::Database.should_receive(:seed).exactly(db_names.length).times
|
63
68
|
|
64
69
|
@rake['apartment:seed'].invoke
|
65
70
|
end
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: apartment
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.
|
5
|
+
version: 0.14.0
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Ryan Brunner
|
@@ -11,7 +11,7 @@ autorequire:
|
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
13
|
|
14
|
-
date: 2011-
|
14
|
+
date: 2011-12-13 00:00:00 -05:00
|
15
15
|
default_executable:
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
@@ -21,7 +21,7 @@ dependencies:
|
|
21
21
|
requirements:
|
22
22
|
- - ~>
|
23
23
|
- !ruby/object:Gem::Version
|
24
|
-
version: 3.1.
|
24
|
+
version: 3.1.2
|
25
25
|
type: :runtime
|
26
26
|
prerelease: false
|
27
27
|
version_requirements: *id001
|
@@ -96,9 +96,9 @@ dependencies:
|
|
96
96
|
requirement: &id008 !ruby/object:Gem::Requirement
|
97
97
|
none: false
|
98
98
|
requirements:
|
99
|
-
- -
|
99
|
+
- - ~>
|
100
100
|
- !ruby/object:Gem::Version
|
101
|
-
version: 0.
|
101
|
+
version: 0.3.7
|
102
102
|
type: :development
|
103
103
|
prerelease: false
|
104
104
|
version_requirements: *id008
|
@@ -178,6 +178,7 @@ files:
|
|
178
178
|
- spec/dummy/config/environments/development.rb
|
179
179
|
- spec/dummy/config/environments/production.rb
|
180
180
|
- spec/dummy/config/environments/test.rb
|
181
|
+
- spec/dummy/config/initializers/apartment.rb
|
181
182
|
- spec/dummy/config/initializers/backtrace_silencers.rb
|
182
183
|
- spec/dummy/config/initializers/inflections.rb
|
183
184
|
- spec/dummy/config/initializers/mime_types.rb
|
@@ -186,13 +187,11 @@ files:
|
|
186
187
|
- spec/dummy/config/locales/en.yml
|
187
188
|
- spec/dummy/config/routes.rb
|
188
189
|
- spec/dummy/db/migrate/20110613152810_create_dummy_models.rb
|
190
|
+
- spec/dummy/db/migrate/20111202022214_create_table_books.rb
|
189
191
|
- spec/dummy/db/schema.rb
|
190
192
|
- spec/dummy/db/seeds.rb
|
191
193
|
- spec/dummy/db/test.sqlite3
|
192
194
|
- spec/dummy/lib/fake_dj_class.rb
|
193
|
-
- spec/dummy/log/development.log
|
194
|
-
- spec/dummy/log/production.log
|
195
|
-
- spec/dummy/log/server.log
|
196
195
|
- spec/dummy/public/404.html
|
197
196
|
- spec/dummy/public/422.html
|
198
197
|
- spec/dummy/public/500.html
|
@@ -226,7 +225,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
226
225
|
requirements:
|
227
226
|
- - ">="
|
228
227
|
- !ruby/object:Gem::Version
|
229
|
-
hash:
|
228
|
+
hash: 538032595049641835
|
230
229
|
segments:
|
231
230
|
- 0
|
232
231
|
version: "0"
|
@@ -235,7 +234,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
235
234
|
requirements:
|
236
235
|
- - ">="
|
237
236
|
- !ruby/object:Gem::Version
|
238
|
-
hash:
|
237
|
+
hash: 538032595049641835
|
239
238
|
segments:
|
240
239
|
- 0
|
241
240
|
version: "0"
|