roomer 0.0.11 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/Appraisals +11 -0
- data/Gemfile +1 -28
- data/Rakefile +4 -1
- data/gemfiles/rails3.gemfile +9 -0
- data/gemfiles/rails3.gemfile.lock +91 -0
- data/gemfiles/rails31.gemfile +9 -0
- data/gemfiles/rails31.gemfile.lock +102 -0
- data/gemfiles/rails32.gemfile +9 -0
- data/gemfiles/rails32.gemfile.lock +100 -0
- data/lib/generators/roomer/install/templates/roomer.rb +4 -1
- data/lib/roomer.rb +5 -1
- data/lib/roomer/extensions/controller.rb +2 -0
- data/lib/roomer/extensions/model.rb +20 -0
- data/lib/roomer/helpers/postgres_helper.rb +11 -2
- data/lib/roomer/rails.rb +1 -0
- data/lib/roomer/schema.rb +18 -16
- data/lib/roomer/schema_dumper.rb +45 -1
- data/lib/roomer/utils.rb +16 -3
- data/lib/roomer/version.rb +2 -2
- data/roomer.gemspec +6 -3
- data/test/config.rb +1 -1
- data/test/config.yml +1 -2
- data/test/generators/migration_generator_test.rb +1 -1
- data/test/rails_app/config/database.yml +5 -2
- data/test/roomer/helpers/postgres_helper_test.rb +3 -3
- data/test/roomer/roomer_test.rb +1 -19
- data/test/test_helper.rb +0 -13
- metadata +76 -50
- data/.rvmrc +0 -2
data/.gitignore
CHANGED
data/Appraisals
ADDED
data/Gemfile
CHANGED
@@ -1,29 +1,2 @@
|
|
1
|
-
source
|
1
|
+
source :rubygems
|
2
2
|
gemspec
|
3
|
-
|
4
|
-
group :doc do
|
5
|
-
gem "yard"
|
6
|
-
end
|
7
|
-
|
8
|
-
group :test do
|
9
|
-
gem "webrat", "~> 0.7.2", :require => false
|
10
|
-
gem "mocha", "~> 0.9.12", :require => false
|
11
|
-
gem "ZenTest", "~> 4.6.2", :require => false
|
12
|
-
gem "autotest-growl", "~> 0.2.9", :require => false
|
13
|
-
end
|
14
|
-
|
15
|
-
platforms :ruby do
|
16
|
-
group :db do
|
17
|
-
gem "pg", ">= 0.11.0"
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
platforms :jruby do
|
22
|
-
gem "activerecord-jdbc-adapter"
|
23
|
-
end
|
24
|
-
|
25
|
-
platforms :mri_18 do
|
26
|
-
group :test do
|
27
|
-
gem "ruby-debug", ">= 0.10.3"
|
28
|
-
end
|
29
|
-
end
|
data/Rakefile
CHANGED
@@ -1,9 +1,12 @@
|
|
1
1
|
# encoding: UTF-8
|
2
|
-
|
2
|
+
require 'rubygems'
|
3
|
+
require 'bundler/setup'
|
3
4
|
require "bundler/gem_tasks"
|
4
5
|
require 'rake/testtask'
|
5
6
|
require 'rdoc/task'
|
6
7
|
|
8
|
+
require 'appraisal'
|
9
|
+
|
7
10
|
desc 'Run Roomer unit tests'
|
8
11
|
Rake::TestTask.new(:test) do |t|
|
9
12
|
t.libs << 'lib'
|
@@ -0,0 +1,91 @@
|
|
1
|
+
PATH
|
2
|
+
remote: /Users/gosuri/projects/roomer
|
3
|
+
specs:
|
4
|
+
roomer (0.0.11)
|
5
|
+
pg (>= 0.11.0)
|
6
|
+
rails (>= 3.0.9)
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: http://rubygems.org/
|
10
|
+
specs:
|
11
|
+
abstract (1.0.0)
|
12
|
+
actionmailer (3.0.9)
|
13
|
+
actionpack (= 3.0.9)
|
14
|
+
mail (~> 2.2.19)
|
15
|
+
actionpack (3.0.9)
|
16
|
+
activemodel (= 3.0.9)
|
17
|
+
activesupport (= 3.0.9)
|
18
|
+
builder (~> 2.1.2)
|
19
|
+
erubis (~> 2.6.6)
|
20
|
+
i18n (~> 0.5.0)
|
21
|
+
rack (~> 1.2.1)
|
22
|
+
rack-mount (~> 0.6.14)
|
23
|
+
rack-test (~> 0.5.7)
|
24
|
+
tzinfo (~> 0.3.23)
|
25
|
+
activemodel (3.0.9)
|
26
|
+
activesupport (= 3.0.9)
|
27
|
+
builder (~> 2.1.2)
|
28
|
+
i18n (~> 0.5.0)
|
29
|
+
activerecord (3.0.9)
|
30
|
+
activemodel (= 3.0.9)
|
31
|
+
activesupport (= 3.0.9)
|
32
|
+
arel (~> 2.0.10)
|
33
|
+
tzinfo (~> 0.3.23)
|
34
|
+
activeresource (3.0.9)
|
35
|
+
activemodel (= 3.0.9)
|
36
|
+
activesupport (= 3.0.9)
|
37
|
+
activesupport (3.0.9)
|
38
|
+
appraisal (0.4.1)
|
39
|
+
bundler
|
40
|
+
rake
|
41
|
+
arel (2.0.10)
|
42
|
+
builder (2.1.2)
|
43
|
+
erubis (2.6.6)
|
44
|
+
abstract (>= 1.0.0)
|
45
|
+
i18n (0.5.0)
|
46
|
+
json (1.7.5)
|
47
|
+
mail (2.2.19)
|
48
|
+
activesupport (>= 2.3.6)
|
49
|
+
i18n (>= 0.4.0)
|
50
|
+
mime-types (~> 1.16)
|
51
|
+
treetop (~> 1.4.8)
|
52
|
+
mime-types (1.19)
|
53
|
+
mocha (0.9.12)
|
54
|
+
pg (0.14.1)
|
55
|
+
polyglot (0.3.3)
|
56
|
+
rack (1.2.5)
|
57
|
+
rack-mount (0.6.14)
|
58
|
+
rack (>= 1.0.0)
|
59
|
+
rack-test (0.5.7)
|
60
|
+
rack (>= 1.0)
|
61
|
+
rails (3.0.9)
|
62
|
+
actionmailer (= 3.0.9)
|
63
|
+
actionpack (= 3.0.9)
|
64
|
+
activerecord (= 3.0.9)
|
65
|
+
activeresource (= 3.0.9)
|
66
|
+
activesupport (= 3.0.9)
|
67
|
+
bundler (~> 1.0)
|
68
|
+
railties (= 3.0.9)
|
69
|
+
railties (3.0.9)
|
70
|
+
actionpack (= 3.0.9)
|
71
|
+
activesupport (= 3.0.9)
|
72
|
+
rake (>= 0.8.7)
|
73
|
+
rdoc (~> 3.4)
|
74
|
+
thor (~> 0.14.4)
|
75
|
+
rake (0.9.2.2)
|
76
|
+
rdoc (3.12)
|
77
|
+
json (~> 1.4)
|
78
|
+
thor (0.14.6)
|
79
|
+
treetop (1.4.11)
|
80
|
+
polyglot
|
81
|
+
polyglot (>= 0.3.1)
|
82
|
+
tzinfo (0.3.33)
|
83
|
+
|
84
|
+
PLATFORMS
|
85
|
+
ruby
|
86
|
+
|
87
|
+
DEPENDENCIES
|
88
|
+
appraisal (~> 0.4.1)
|
89
|
+
mocha (~> 0.9.12)
|
90
|
+
rails (= 3.0.9)
|
91
|
+
roomer!
|
@@ -0,0 +1,102 @@
|
|
1
|
+
PATH
|
2
|
+
remote: /Users/gosuri/projects/roomer
|
3
|
+
specs:
|
4
|
+
roomer (0.0.11)
|
5
|
+
pg (>= 0.11.0)
|
6
|
+
rails (>= 3.0.9)
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: http://rubygems.org/
|
10
|
+
specs:
|
11
|
+
actionmailer (3.1.8)
|
12
|
+
actionpack (= 3.1.8)
|
13
|
+
mail (~> 2.3.3)
|
14
|
+
actionpack (3.1.8)
|
15
|
+
activemodel (= 3.1.8)
|
16
|
+
activesupport (= 3.1.8)
|
17
|
+
builder (~> 3.0.0)
|
18
|
+
erubis (~> 2.7.0)
|
19
|
+
i18n (~> 0.6)
|
20
|
+
rack (~> 1.3.6)
|
21
|
+
rack-cache (~> 1.2)
|
22
|
+
rack-mount (~> 0.8.2)
|
23
|
+
rack-test (~> 0.6.1)
|
24
|
+
sprockets (~> 2.0.4)
|
25
|
+
activemodel (3.1.8)
|
26
|
+
activesupport (= 3.1.8)
|
27
|
+
builder (~> 3.0.0)
|
28
|
+
i18n (~> 0.6)
|
29
|
+
activerecord (3.1.8)
|
30
|
+
activemodel (= 3.1.8)
|
31
|
+
activesupport (= 3.1.8)
|
32
|
+
arel (~> 2.2.3)
|
33
|
+
tzinfo (~> 0.3.29)
|
34
|
+
activeresource (3.1.8)
|
35
|
+
activemodel (= 3.1.8)
|
36
|
+
activesupport (= 3.1.8)
|
37
|
+
activesupport (3.1.8)
|
38
|
+
multi_json (>= 1.0, < 1.3)
|
39
|
+
appraisal (0.4.1)
|
40
|
+
bundler
|
41
|
+
rake
|
42
|
+
arel (2.2.3)
|
43
|
+
builder (3.0.4)
|
44
|
+
erubis (2.7.0)
|
45
|
+
hike (1.2.1)
|
46
|
+
i18n (0.6.1)
|
47
|
+
json (1.7.5)
|
48
|
+
mail (2.3.3)
|
49
|
+
i18n (>= 0.4.0)
|
50
|
+
mime-types (~> 1.16)
|
51
|
+
treetop (~> 1.4.8)
|
52
|
+
mime-types (1.19)
|
53
|
+
mocha (0.9.12)
|
54
|
+
multi_json (1.2.0)
|
55
|
+
pg (0.14.1)
|
56
|
+
polyglot (0.3.3)
|
57
|
+
rack (1.3.6)
|
58
|
+
rack-cache (1.2)
|
59
|
+
rack (>= 0.4)
|
60
|
+
rack-mount (0.8.3)
|
61
|
+
rack (>= 1.0.0)
|
62
|
+
rack-ssl (1.3.2)
|
63
|
+
rack
|
64
|
+
rack-test (0.6.2)
|
65
|
+
rack (>= 1.0)
|
66
|
+
rails (3.1.8)
|
67
|
+
actionmailer (= 3.1.8)
|
68
|
+
actionpack (= 3.1.8)
|
69
|
+
activerecord (= 3.1.8)
|
70
|
+
activeresource (= 3.1.8)
|
71
|
+
activesupport (= 3.1.8)
|
72
|
+
bundler (~> 1.0)
|
73
|
+
railties (= 3.1.8)
|
74
|
+
railties (3.1.8)
|
75
|
+
actionpack (= 3.1.8)
|
76
|
+
activesupport (= 3.1.8)
|
77
|
+
rack-ssl (~> 1.3.2)
|
78
|
+
rake (>= 0.8.7)
|
79
|
+
rdoc (~> 3.4)
|
80
|
+
thor (~> 0.14.6)
|
81
|
+
rake (0.9.2.2)
|
82
|
+
rdoc (3.12)
|
83
|
+
json (~> 1.4)
|
84
|
+
sprockets (2.0.4)
|
85
|
+
hike (~> 1.2)
|
86
|
+
rack (~> 1.0)
|
87
|
+
tilt (~> 1.1, != 1.3.0)
|
88
|
+
thor (0.14.6)
|
89
|
+
tilt (1.3.3)
|
90
|
+
treetop (1.4.11)
|
91
|
+
polyglot
|
92
|
+
polyglot (>= 0.3.1)
|
93
|
+
tzinfo (0.3.33)
|
94
|
+
|
95
|
+
PLATFORMS
|
96
|
+
ruby
|
97
|
+
|
98
|
+
DEPENDENCIES
|
99
|
+
appraisal (~> 0.4.1)
|
100
|
+
mocha (~> 0.9.12)
|
101
|
+
rails (= 3.1.8)
|
102
|
+
roomer!
|
@@ -0,0 +1,100 @@
|
|
1
|
+
PATH
|
2
|
+
remote: /Users/gosuri/projects/roomer
|
3
|
+
specs:
|
4
|
+
roomer (0.0.11)
|
5
|
+
pg (>= 0.11.0)
|
6
|
+
rails (>= 3.0.9)
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: http://rubygems.org/
|
10
|
+
specs:
|
11
|
+
actionmailer (3.2.8)
|
12
|
+
actionpack (= 3.2.8)
|
13
|
+
mail (~> 2.4.4)
|
14
|
+
actionpack (3.2.8)
|
15
|
+
activemodel (= 3.2.8)
|
16
|
+
activesupport (= 3.2.8)
|
17
|
+
builder (~> 3.0.0)
|
18
|
+
erubis (~> 2.7.0)
|
19
|
+
journey (~> 1.0.4)
|
20
|
+
rack (~> 1.4.0)
|
21
|
+
rack-cache (~> 1.2)
|
22
|
+
rack-test (~> 0.6.1)
|
23
|
+
sprockets (~> 2.1.3)
|
24
|
+
activemodel (3.2.8)
|
25
|
+
activesupport (= 3.2.8)
|
26
|
+
builder (~> 3.0.0)
|
27
|
+
activerecord (3.2.8)
|
28
|
+
activemodel (= 3.2.8)
|
29
|
+
activesupport (= 3.2.8)
|
30
|
+
arel (~> 3.0.2)
|
31
|
+
tzinfo (~> 0.3.29)
|
32
|
+
activeresource (3.2.8)
|
33
|
+
activemodel (= 3.2.8)
|
34
|
+
activesupport (= 3.2.8)
|
35
|
+
activesupport (3.2.8)
|
36
|
+
i18n (~> 0.6)
|
37
|
+
multi_json (~> 1.0)
|
38
|
+
appraisal (0.4.1)
|
39
|
+
bundler
|
40
|
+
rake
|
41
|
+
arel (3.0.2)
|
42
|
+
builder (3.0.4)
|
43
|
+
erubis (2.7.0)
|
44
|
+
hike (1.2.1)
|
45
|
+
i18n (0.6.1)
|
46
|
+
journey (1.0.4)
|
47
|
+
json (1.7.5)
|
48
|
+
mail (2.4.4)
|
49
|
+
i18n (>= 0.4.0)
|
50
|
+
mime-types (~> 1.16)
|
51
|
+
treetop (~> 1.4.8)
|
52
|
+
mime-types (1.19)
|
53
|
+
mocha (0.9.12)
|
54
|
+
multi_json (1.3.6)
|
55
|
+
pg (0.14.1)
|
56
|
+
polyglot (0.3.3)
|
57
|
+
rack (1.4.1)
|
58
|
+
rack-cache (1.2)
|
59
|
+
rack (>= 0.4)
|
60
|
+
rack-ssl (1.3.2)
|
61
|
+
rack
|
62
|
+
rack-test (0.6.2)
|
63
|
+
rack (>= 1.0)
|
64
|
+
rails (3.2.8)
|
65
|
+
actionmailer (= 3.2.8)
|
66
|
+
actionpack (= 3.2.8)
|
67
|
+
activerecord (= 3.2.8)
|
68
|
+
activeresource (= 3.2.8)
|
69
|
+
activesupport (= 3.2.8)
|
70
|
+
bundler (~> 1.0)
|
71
|
+
railties (= 3.2.8)
|
72
|
+
railties (3.2.8)
|
73
|
+
actionpack (= 3.2.8)
|
74
|
+
activesupport (= 3.2.8)
|
75
|
+
rack-ssl (~> 1.3.2)
|
76
|
+
rake (>= 0.8.7)
|
77
|
+
rdoc (~> 3.4)
|
78
|
+
thor (>= 0.14.6, < 2.0)
|
79
|
+
rake (0.9.2.2)
|
80
|
+
rdoc (3.12)
|
81
|
+
json (~> 1.4)
|
82
|
+
sprockets (2.1.3)
|
83
|
+
hike (~> 1.2)
|
84
|
+
rack (~> 1.0)
|
85
|
+
tilt (~> 1.1, != 1.3.0)
|
86
|
+
thor (0.16.0)
|
87
|
+
tilt (1.3.3)
|
88
|
+
treetop (1.4.11)
|
89
|
+
polyglot
|
90
|
+
polyglot (>= 0.3.1)
|
91
|
+
tzinfo (0.3.33)
|
92
|
+
|
93
|
+
PLATFORMS
|
94
|
+
ruby
|
95
|
+
|
96
|
+
DEPENDENCIES
|
97
|
+
appraisal (~> 0.4.1)
|
98
|
+
mocha (~> 0.9.12)
|
99
|
+
rails (= 3.2.8)
|
100
|
+
roomer!
|
@@ -47,7 +47,7 @@ Roomer.setup do |config|
|
|
47
47
|
|
48
48
|
# Use Tentant migrations directory?
|
49
49
|
# Default is set to false
|
50
|
-
|
50
|
+
config.use_tenanted_migrations_directory = true
|
51
51
|
|
52
52
|
# Directory where shared migrations are stored. Please make
|
53
53
|
# sure your migrations are present in this directory.
|
@@ -65,4 +65,7 @@ Roomer.setup do |config|
|
|
65
65
|
|
66
66
|
# Filename to use for shared schema
|
67
67
|
# config.shared_schema_filename = "shared_schema.rb"
|
68
|
+
|
69
|
+
# Safe to run on Heroku
|
70
|
+
# Roomer.heroku_safe = true
|
68
71
|
end
|
data/lib/roomer.rb
CHANGED
@@ -92,13 +92,17 @@ module Roomer
|
|
92
92
|
# This will be used only if use_tenanted_migration_directory is set to
|
93
93
|
# true if not usual rails migraiton directory db/migrate will be used
|
94
94
|
mattr_writer :tenanted_migrations_directory
|
95
|
-
@@tenanted_migrations_directory = File.join(migrations_directory,
|
95
|
+
@@tenanted_migrations_directory = File.join(migrations_directory, "tenanted")
|
96
96
|
|
97
97
|
|
98
98
|
# Directory where shared migrations are stored.
|
99
99
|
mattr_accessor :shared_migrations_directory
|
100
100
|
@@shared_migrations_directory = File.join(migrations_directory,shared_schema_name.to_s)
|
101
101
|
|
102
|
+
# When set to true will not dump schema files
|
103
|
+
mattr_accessor :heroku_safe
|
104
|
+
@@heroku_safe = true
|
105
|
+
|
102
106
|
# Fetches the migrations directory for Tenanted migrations.
|
103
107
|
# returns the standard rails migration directory "db/migrate" is the
|
104
108
|
# use_tenanted_migrations_directory is set to false
|
@@ -20,6 +20,8 @@ module Roomer
|
|
20
20
|
# Sets the current tenant, this method is set in the before_filter
|
21
21
|
# @throws if tenant is not found
|
22
22
|
def set_current_tenant!
|
23
|
+
return if Roomer.current_tenant.try(:url_identifier) == url_identifier
|
24
|
+
|
23
25
|
# Raise an exception if the current tenant is blank
|
24
26
|
raise "No tenant found for '#{url_identifier}' url identifier" if current_tenant.blank?
|
25
27
|
Roomer.current_tenant = current_tenant
|
@@ -43,9 +43,29 @@ module Roomer
|
|
43
43
|
roomer_set_table_name_prefix
|
44
44
|
reset_table_name
|
45
45
|
reset_column_information
|
46
|
+
reset_associations
|
46
47
|
end
|
47
48
|
|
48
49
|
protected
|
50
|
+
|
51
|
+
# Resets cached data in associations
|
52
|
+
# Fixes bug that mixed table_name_prefix
|
53
|
+
# between tenants
|
54
|
+
def reset_associations
|
55
|
+
reflections.each_value do |r|
|
56
|
+
r.instance_variable_set(:@quoted_table_name, nil)
|
57
|
+
table_name = r.instance_variable_get(:@table_name)
|
58
|
+
if (table_name)
|
59
|
+
table_name = table_name.split(".").last
|
60
|
+
klass = r.class_name.constantize
|
61
|
+
schema_name = klass.tenanted? ? Roomer.current_tenant.schema_name.to_s : Roomer.shared_schema_name.to_s
|
62
|
+
table_name = "#{schema_name}#{Roomer.schema_seperator}#{table_name}"
|
63
|
+
r.instance_variable_set(:@table_name, table_name)
|
64
|
+
r.instance_variable_set(:@quoted_table_name, connection.quote_table_name(table_name))
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
49
69
|
# Resolves the full table name prefix
|
50
70
|
def roomer_full_table_name_prefix(schema_name)
|
51
71
|
"#{schema_name.to_s}#{Roomer.schema_seperator}"
|
@@ -75,10 +75,10 @@ module Roomer
|
|
75
75
|
# Person.find(1) # => will execute "SELECT id FROM 'global.person' where 'id' = 1"
|
76
76
|
# end
|
77
77
|
def ensure_prefix(prefix, &block)
|
78
|
-
|
78
|
+
old_prefix = ActiveRecord::Base.table_name_prefix
|
79
79
|
ActiveRecord::Base.table_name_prefix = "#{prefix.to_s}#{Roomer.schema_seperator.to_s}"
|
80
80
|
yield
|
81
|
-
ActiveRecord::Base.table_name_prefix =
|
81
|
+
ActiveRecord::Base.table_name_prefix = old_prefix
|
82
82
|
end
|
83
83
|
|
84
84
|
# Ensures schema_migrations table exists and creates otherwise
|
@@ -93,6 +93,15 @@ module Roomer
|
|
93
93
|
ActiveRecord::Migrator.new(:up,Roomer.shared_migrations_directory)
|
94
94
|
end
|
95
95
|
|
96
|
+
# Get view definitions for given schema
|
97
|
+
# @returns [Array] with all definitions for a given schema
|
98
|
+
def view_definitions(schema_name)
|
99
|
+
ActiveRecord::Base.connection.select_all(%{
|
100
|
+
SELECT definition
|
101
|
+
FROM pg_views
|
102
|
+
WHERE schemaname = '#{schema_name}';
|
103
|
+
})
|
104
|
+
end
|
96
105
|
end
|
97
106
|
end
|
98
107
|
end
|
data/lib/roomer/rails.rb
CHANGED
data/lib/roomer/schema.rb
CHANGED
@@ -19,22 +19,24 @@ module Roomer
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def self.dump(scope=:tenanted)
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
22
|
+
unless Roomer.heroku_safe && ENV['HEROKU_UPID']
|
23
|
+
case scope
|
24
|
+
when :shared
|
25
|
+
schema_name = Roomer.shared_schema_name.to_s
|
26
|
+
filename = Roomer.shared_schema_filename
|
27
|
+
when :tenanted
|
28
|
+
tenant = Tenant.first
|
29
|
+
return if tenant.blank?
|
29
30
|
|
30
|
-
|
31
|
-
|
31
|
+
schema_name = Tenant.first.schema_name.to_s
|
32
|
+
filename = Roomer.tenanted_schema_filename
|
33
|
+
end
|
34
|
+
FileUtils.mkdir_p(Roomer.schemas_directory) unless File.exists?(Roomer.schemas_directory)
|
35
|
+
filepath = File.expand_path(File.join(Roomer.schemas_directory, filename))
|
36
|
+
ActiveRecord::Base.connection.schema_search_path = schema_name
|
37
|
+
ActiveRecord::Base.table_name_prefix = "#{schema_name}."
|
38
|
+
Roomer::SchemaDumper.dump(ActiveRecord::Base.connection, File.new(filepath, "w"))
|
32
39
|
end
|
33
|
-
FileUtils.mkdir_p(Roomer.schemas_directory) unless File.exists?(Roomer.schemas_directory)
|
34
|
-
filepath = File.expand_path(File.join(Roomer.schemas_directory, filename))
|
35
|
-
ActiveRecord::Base.connection.schema_search_path = schema_name
|
36
|
-
ActiveRecord::Base.table_name_prefix = "#{schema_name}."
|
37
|
-
Roomer::SchemaDumper.dump(ActiveRecord::Base.connection, File.new(filepath, "w"))
|
38
40
|
end
|
39
41
|
|
40
42
|
def self.load(schema_name, scope=:tenanted)
|
@@ -61,11 +63,11 @@ module Roomer
|
|
61
63
|
|
62
64
|
def self.current_schema
|
63
65
|
ActiveRecord::Base.table_name_prefix.split('.').first
|
64
|
-
end
|
66
|
+
end
|
65
67
|
|
66
68
|
def self.current_tenant
|
67
69
|
return nil if current_schema == Roomer.shared_schema_name.to_s
|
68
70
|
Tenant.find_by_schema_name(current_schema)
|
69
|
-
end
|
71
|
+
end
|
70
72
|
end
|
71
73
|
end
|
data/lib/roomer/schema_dumper.rb
CHANGED
@@ -1,6 +1,14 @@
|
|
1
1
|
module Roomer
|
2
2
|
class SchemaDumper < ActiveRecord::SchemaDumper
|
3
3
|
|
4
|
+
def dump(stream)
|
5
|
+
header(stream)
|
6
|
+
tables(stream)
|
7
|
+
views(stream)
|
8
|
+
trailer(stream)
|
9
|
+
stream
|
10
|
+
end
|
11
|
+
|
4
12
|
protected
|
5
13
|
def header(stream)
|
6
14
|
define_params = @version ? ":version => #{@version}" : ""
|
@@ -12,12 +20,48 @@ Roomer::Schema.define(#{define_params}) do
|
|
12
20
|
HEADER
|
13
21
|
end
|
14
22
|
|
23
|
+
def views(stream)
|
24
|
+
stream.puts <<VIEWS
|
25
|
+
# Database Views
|
26
|
+
# The following statements persist database views across tenants
|
27
|
+
|
28
|
+
VIEWS
|
29
|
+
# Make sure search_path is public so schema name gets dumped
|
30
|
+
# along with table names.
|
31
|
+
current_schema = @connection.schema_search_path
|
32
|
+
@connection.schema_search_path = "public"
|
33
|
+
views = @connection.select_all(%{
|
34
|
+
SELECT *
|
35
|
+
FROM pg_views
|
36
|
+
WHERE schemaname = '#{current_schema}';
|
37
|
+
})
|
38
|
+
# Reinstating previous search path to make sure nothing breaks
|
39
|
+
@connection.schema_search_path = current_schema
|
40
|
+
unless views.empty?
|
41
|
+
views.each do |view|
|
42
|
+
stream.puts <<VIEWS
|
43
|
+
execute("CREATE OR REPLACE VIEW \#{ActiveRecord::Base.table_name_prefix}#{view['viewname']} AS #{view['definition'].gsub(/#{current_schema}\./, '#{ActiveRecord::Base.table_name_prefix}')}")
|
44
|
+
VIEWS
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def roomer_index_name(index_name)
|
50
|
+
sections = index_name.split(".")
|
51
|
+
if sections.length > 1
|
52
|
+
if sections[0].split("_")[0] == "index"
|
53
|
+
sections[0] = "index"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
sections.join(".")
|
57
|
+
end
|
58
|
+
|
15
59
|
def indexes(table, stream)
|
16
60
|
if (indexes = @connection.indexes(table)).any?
|
17
61
|
add_index_statements = indexes.map do |index|
|
18
62
|
statement_parts = [ ('add_index ' + index.table.inspect) ]
|
19
63
|
statement_parts << index.columns.inspect
|
20
|
-
statement_parts << (':name => "' + index.name + '"')
|
64
|
+
statement_parts << (':name => "' + roomer_index_name(index.name) + '"')
|
21
65
|
statement_parts << ':unique => true' if index.unique
|
22
66
|
|
23
67
|
index_lengths = index.lengths.compact if index.lengths.is_a?(Array)
|
data/lib/roomer/utils.rb
CHANGED
@@ -40,8 +40,11 @@ module Roomer
|
|
40
40
|
# @return [Symbol] the current tenant key in the thread
|
41
41
|
def current_tenant=(val)
|
42
42
|
key = :"roomer_current_tenant"
|
43
|
-
Thread.current[key]
|
44
|
-
|
43
|
+
unless Thread.current[key].try(:url_identifier) == val.url_identifier
|
44
|
+
Thread.current[key] = val
|
45
|
+
ensure_tenant_model_reset
|
46
|
+
end
|
47
|
+
Thread.current[key]
|
45
48
|
end
|
46
49
|
|
47
50
|
# Fetches the current tenant
|
@@ -60,9 +63,19 @@ module Roomer
|
|
60
63
|
|
61
64
|
# Reset cached data in tenanted models
|
62
65
|
def ensure_tenant_model_reset
|
66
|
+
reset_models
|
67
|
+
end
|
68
|
+
|
69
|
+
protected
|
70
|
+
|
71
|
+
def reset_models
|
63
72
|
ActiveRecord::Base.descendants.each do |model|
|
64
|
-
model.roomer_reset
|
73
|
+
model.roomer_reset
|
65
74
|
end
|
66
75
|
end
|
76
|
+
|
77
|
+
def clean_environment
|
78
|
+
ActionDispatch::Reloader.cleanup!
|
79
|
+
end
|
67
80
|
end
|
68
81
|
end
|
data/lib/roomer/version.rb
CHANGED
data/roomer.gemspec
CHANGED
@@ -10,13 +10,16 @@ Gem::Specification.new do |s|
|
|
10
10
|
s.summary = "Roomer is a multitenant framework for Rails using PostgreSQL"
|
11
11
|
s.description = Roomer::VERSION::SUMMARY
|
12
12
|
|
13
|
-
s.authors = ["Greg Osuri","Daniel Ceballos"]
|
14
|
-
s.email = ["gosuri@gmail.com","dceballos@gmail.com"]
|
13
|
+
s.authors = ["Greg Osuri", "Daniel Ceballos"]
|
14
|
+
s.email = ["gosuri@gmail.com", "dceballos@gmail.com"]
|
15
15
|
|
16
16
|
s.files = `git ls-files`.split("\n")
|
17
17
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
18
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
19
|
s.require_paths = ["lib"]
|
20
20
|
|
21
|
-
s.add_dependency
|
21
|
+
s.add_dependency 'rails' , '>= 3.0.9'
|
22
|
+
s.add_dependency 'pg' , '>= 0.11.0'
|
23
|
+
|
24
|
+
s.add_development_dependency 'appraisal', '~> 0.4.1'
|
22
25
|
end
|
data/test/config.rb
CHANGED
data/test/config.yml
CHANGED
@@ -23,7 +23,7 @@ class MigrationGeneratorTest < Rails::Generators::TestCase
|
|
23
23
|
test "create migration for a tenanted model in tenant dir" do
|
24
24
|
Roomer.use_tenanted_migrations_directory = true
|
25
25
|
run_generator %w(add_tenant_bar_to_foos bar:string)
|
26
|
-
assert_migration "db/migrate/
|
26
|
+
assert_migration "db/migrate/tenanted/roomer_add_tenant_bar_to_foos.rb"
|
27
27
|
end
|
28
28
|
|
29
29
|
test "create migration for shared model" do
|
@@ -16,7 +16,7 @@ class PostgresHelperTest < ActiveSupport::TestCase
|
|
16
16
|
assert_nothing_raised { create_schema("old_test_schema") }
|
17
17
|
assert schemas.include? "old_test_schema"
|
18
18
|
assert_nothing_raised { drop_schema("old_test_schema") }
|
19
|
-
assert (
|
19
|
+
assert !(schemas.include?("old_test_schema"))
|
20
20
|
end
|
21
21
|
|
22
22
|
test 'ensure prefix' do
|
@@ -27,7 +27,7 @@ class PostgresHelperTest < ActiveSupport::TestCase
|
|
27
27
|
assert_equal ActiveRecord::Base.table_name_prefix, "old_prefix_"
|
28
28
|
end
|
29
29
|
|
30
|
-
test'ensure schema migrations' do
|
30
|
+
test 'ensure schema migrations' do
|
31
31
|
create_schema("test_schema")
|
32
32
|
ensure_prefix(:test_schema) do
|
33
33
|
ensure_schema_migrations
|
@@ -41,7 +41,7 @@ class PostgresHelperTest < ActiveSupport::TestCase
|
|
41
41
|
end
|
42
42
|
|
43
43
|
assert_nothing_raised do
|
44
|
-
assert (
|
44
|
+
assert !(schemas.include?("new_tenant"))
|
45
45
|
ensuring_schema(:new_tenant) do
|
46
46
|
assert schemas.include? "new_tenant"
|
47
47
|
assert_equal ActiveRecord::Base.table_name_prefix, "new_tenant."
|
data/test/roomer/roomer_test.rb
CHANGED
@@ -11,27 +11,9 @@ class RoomerTest < ActiveSupport::TestCase
|
|
11
11
|
test 'return migrations directory' do
|
12
12
|
assert_equal Roomer.tenanted_migrations_directory, "db/migrate"
|
13
13
|
Roomer.use_tenanted_migrations_directory = true
|
14
|
-
assert_equal Roomer.tenanted_migrations_directory, "db/migrate/
|
14
|
+
assert_equal Roomer.tenanted_migrations_directory, "db/migrate/tenanted"
|
15
15
|
end
|
16
16
|
|
17
|
-
|
18
17
|
test 'set the current tenant' do
|
19
|
-
tenant1 = mock()
|
20
|
-
tenant2 = mock()
|
21
|
-
|
22
|
-
assert_not_equal(tenant1,tenant2)
|
23
|
-
|
24
|
-
thread1 = Thread.new do
|
25
|
-
Roomer.current_tenant = tenant1
|
26
|
-
sleep 1
|
27
|
-
assert_equal(Roomer.current_tenant,tenant1)
|
28
|
-
end
|
29
|
-
|
30
|
-
thread2 = Thread.new do
|
31
|
-
Roomer.current_tenant = tenant2
|
32
|
-
assert_equal(Roomer.current_tenant,tenant2)
|
33
|
-
end
|
34
|
-
|
35
|
-
thread2.join
|
36
18
|
end
|
37
19
|
end
|
data/test/test_helper.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
|
2
1
|
# FIXME Remove Postgres Server Hard dependency
|
3
2
|
|
4
3
|
ENV["RAILS_ENV"] = "test"
|
@@ -7,17 +6,5 @@ require "roomer"
|
|
7
6
|
require "rails_app/config/environment"
|
8
7
|
require "rails/test_help"
|
9
8
|
|
10
|
-
require 'mocha'
|
11
|
-
#require 'webrat'
|
12
|
-
#Webrat.configure do |config|
|
13
|
-
# config.mode = :rails
|
14
|
-
# config.open_error_files = false
|
15
|
-
#end
|
16
|
-
|
17
|
-
# Add support to load paths so we can overwrite broken webrat setup
|
18
|
-
#$:.unshift File.expand_path('../support', __FILE__)
|
19
|
-
#Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
|
20
|
-
|
21
9
|
# For generators
|
22
10
|
require "rails/generators/test_case"
|
23
|
-
|
metadata
CHANGED
@@ -1,54 +1,77 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: roomer
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
5
|
prerelease:
|
6
|
-
segments:
|
7
|
-
- 0
|
8
|
-
- 0
|
9
|
-
- 11
|
10
|
-
version: 0.0.11
|
11
6
|
platform: ruby
|
12
|
-
authors:
|
7
|
+
authors:
|
13
8
|
- Greg Osuri
|
14
9
|
- Daniel Ceballos
|
15
10
|
autorequire:
|
16
11
|
bindir: bin
|
17
12
|
cert_chain: []
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
- !ruby/object:Gem::Dependency
|
13
|
+
date: 2012-10-16 00:00:00.000000000 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
22
16
|
name: rails
|
17
|
+
requirement: !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ! '>='
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 3.0.9
|
23
|
+
type: :runtime
|
23
24
|
prerelease: false
|
24
|
-
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
26
|
none: false
|
26
|
-
requirements:
|
27
|
-
- -
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
hash: 21
|
30
|
-
segments:
|
31
|
-
- 3
|
32
|
-
- 0
|
33
|
-
- 9
|
27
|
+
requirements:
|
28
|
+
- - ! '>='
|
29
|
+
- !ruby/object:Gem::Version
|
34
30
|
version: 3.0.9
|
31
|
+
- !ruby/object:Gem::Dependency
|
32
|
+
name: pg
|
33
|
+
requirement: !ruby/object:Gem::Requirement
|
34
|
+
none: false
|
35
|
+
requirements:
|
36
|
+
- - ! '>='
|
37
|
+
- !ruby/object:Gem::Version
|
38
|
+
version: 0.11.0
|
35
39
|
type: :runtime
|
36
|
-
|
37
|
-
|
38
|
-
|
40
|
+
prerelease: false
|
41
|
+
version_requirements: !ruby/object:Gem::Requirement
|
42
|
+
none: false
|
43
|
+
requirements:
|
44
|
+
- - ! '>='
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 0.11.0
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: appraisal
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.4.1
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: !ruby/object:Gem::Requirement
|
58
|
+
none: false
|
59
|
+
requirements:
|
60
|
+
- - ~>
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: 0.4.1
|
63
|
+
description: roomer 1.0.0
|
64
|
+
email:
|
39
65
|
- gosuri@gmail.com
|
40
66
|
- dceballos@gmail.com
|
41
67
|
executables: []
|
42
|
-
|
43
68
|
extensions: []
|
44
|
-
|
45
69
|
extra_rdoc_files: []
|
46
|
-
|
47
|
-
files:
|
70
|
+
files:
|
48
71
|
- .autotest
|
49
72
|
- .gitignore
|
50
|
-
- .rvmrc
|
51
73
|
- .travis.yml
|
74
|
+
- Appraisals
|
52
75
|
- Gemfile
|
53
76
|
- MIT-LICENSE
|
54
77
|
- README.md
|
@@ -78,6 +101,12 @@ files:
|
|
78
101
|
- doc/js/jquery.js
|
79
102
|
- doc/method_list.html
|
80
103
|
- doc/top-level-namespace.html
|
104
|
+
- gemfiles/rails3.gemfile
|
105
|
+
- gemfiles/rails3.gemfile.lock
|
106
|
+
- gemfiles/rails31.gemfile
|
107
|
+
- gemfiles/rails31.gemfile.lock
|
108
|
+
- gemfiles/rails32.gemfile
|
109
|
+
- gemfiles/rails32.gemfile.lock
|
81
110
|
- lib/generators/roomer/install/install_generator.rb
|
82
111
|
- lib/generators/roomer/install/templates/README
|
83
112
|
- lib/generators/roomer/install/templates/roomer.rb
|
@@ -148,38 +177,35 @@ files:
|
|
148
177
|
- test/test_helper.rb
|
149
178
|
homepage: https://github.com/gosuri/roomer
|
150
179
|
licenses: []
|
151
|
-
|
152
180
|
post_install_message:
|
153
181
|
rdoc_options: []
|
154
|
-
|
155
|
-
require_paths:
|
182
|
+
require_paths:
|
156
183
|
- lib
|
157
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
184
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
158
185
|
none: false
|
159
|
-
requirements:
|
160
|
-
- -
|
161
|
-
- !ruby/object:Gem::Version
|
162
|
-
|
163
|
-
segments:
|
186
|
+
requirements:
|
187
|
+
- - ! '>='
|
188
|
+
- !ruby/object:Gem::Version
|
189
|
+
version: '0'
|
190
|
+
segments:
|
164
191
|
- 0
|
165
|
-
|
166
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
192
|
+
hash: 2764573444954838764
|
193
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
167
194
|
none: false
|
168
|
-
requirements:
|
169
|
-
- -
|
170
|
-
- !ruby/object:Gem::Version
|
171
|
-
|
172
|
-
segments:
|
195
|
+
requirements:
|
196
|
+
- - ! '>='
|
197
|
+
- !ruby/object:Gem::Version
|
198
|
+
version: '0'
|
199
|
+
segments:
|
173
200
|
- 0
|
174
|
-
|
201
|
+
hash: 2764573444954838764
|
175
202
|
requirements: []
|
176
|
-
|
177
203
|
rubyforge_project:
|
178
|
-
rubygems_version: 1.8.
|
204
|
+
rubygems_version: 1.8.24
|
179
205
|
signing_key:
|
180
206
|
specification_version: 3
|
181
207
|
summary: Roomer is a multitenant framework for Rails using PostgreSQL
|
182
|
-
test_files:
|
208
|
+
test_files:
|
183
209
|
- test/config.rb
|
184
210
|
- test/config.yml
|
185
211
|
- test/generators/install_generator_test.rb
|
data/.rvmrc
DELETED