dr-apartment 0.14.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/.gitignore +6 -0
- data/.rspec +2 -0
- data/.rvmrc +1 -0
- data/Gemfile +22 -0
- data/HISTORY.md +133 -0
- data/README.md +152 -0
- data/Rakefile +79 -0
- data/apartment.gemspec +32 -0
- data/lib/apartment.rb +69 -0
- data/lib/apartment/adapters/abstract_adapter.rb +176 -0
- data/lib/apartment/adapters/jdbcpostgresql_adapter.rb +115 -0
- data/lib/apartment/adapters/mysql_adapter.rb +18 -0
- data/lib/apartment/adapters/postgresql_adapter.rb +114 -0
- data/lib/apartment/console.rb +12 -0
- data/lib/apartment/database.rb +57 -0
- data/lib/apartment/delayed_job/active_record.rb +20 -0
- data/lib/apartment/delayed_job/enqueue.rb +20 -0
- data/lib/apartment/delayed_job/hooks.rb +25 -0
- data/lib/apartment/delayed_job/requirements.rb +23 -0
- data/lib/apartment/elevators/subdomain.rb +27 -0
- data/lib/apartment/migrator.rb +23 -0
- data/lib/apartment/railtie.rb +54 -0
- data/lib/apartment/reloader.rb +24 -0
- data/lib/apartment/version.rb +3 -0
- data/lib/tasks/apartment.rake +70 -0
- data/spec/adapters/mysql_adapter_spec.rb +36 -0
- data/spec/adapters/postgresql_adapter_spec.rb +137 -0
- data/spec/apartment_spec.rb +11 -0
- data/spec/config/database.yml +13 -0
- data/spec/dummy/Rakefile +7 -0
- data/spec/dummy/app/controllers/application_controller.rb +6 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/models/company.rb +3 -0
- data/spec/dummy/app/models/user.rb +3 -0
- data/spec/dummy/app/views/application/index.html.erb +1 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/config/application.rb +47 -0
- data/spec/dummy/config/boot.rb +10 -0
- data/spec/dummy/config/database.yml +16 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +26 -0
- data/spec/dummy/config/environments/production.rb +49 -0
- data/spec/dummy/config/environments/test.rb +35 -0
- data/spec/dummy/config/initializers/apartment.rb +4 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/inflections.rb +10 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/secret_token.rb +7 -0
- data/spec/dummy/config/initializers/session_store.rb +8 -0
- data/spec/dummy/config/locales/en.yml +5 -0
- data/spec/dummy/config/routes.rb +3 -0
- data/spec/dummy/db/migrate/20110613152810_create_dummy_models.rb +37 -0
- data/spec/dummy/db/migrate/20111202022214_create_table_books.rb +13 -0
- data/spec/dummy/db/schema.rb +48 -0
- data/spec/dummy/db/seeds.rb +8 -0
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/dummy/lib/fake_dj_class.rb +6 -0
- data/spec/dummy/public/404.html +26 -0
- data/spec/dummy/public/422.html +26 -0
- data/spec/dummy/public/500.html +26 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/public/stylesheets/.gitkeep +0 -0
- data/spec/dummy/script/rails +6 -0
- data/spec/integration/apartment_rake_integration_spec.rb +74 -0
- data/spec/integration/database_integration_spec.rb +200 -0
- data/spec/integration/delayed_job_integration_spec.rb +100 -0
- data/spec/integration/middleware/subdomain_elevator_spec.rb +63 -0
- data/spec/spec_helper.rb +31 -0
- data/spec/support/apartment_helpers.rb +32 -0
- data/spec/support/capybara_sessions.rb +15 -0
- data/spec/support/config.rb +11 -0
- data/spec/tasks/apartment_rake_spec.rb +118 -0
- data/spec/unit/config_spec.rb +78 -0
- data/spec/unit/middleware/subdomain_elevator_spec.rb +20 -0
- data/spec/unit/migrator_spec.rb +87 -0
- data/spec/unit/reloader_spec.rb +22 -0
- metadata +144 -0
@@ -0,0 +1,176 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
|
3
|
+
module Apartment
|
4
|
+
|
5
|
+
module Adapters
|
6
|
+
|
7
|
+
class AbstractAdapter
|
8
|
+
|
9
|
+
# @constructor
|
10
|
+
# @param {Hash} config Database config
|
11
|
+
# @param {Hash} defaults Some default options
|
12
|
+
#
|
13
|
+
def initialize(config, defaults = {})
|
14
|
+
@config = config
|
15
|
+
@defaults = defaults
|
16
|
+
end
|
17
|
+
|
18
|
+
# Create a new database, import schema, seed if appropriate
|
19
|
+
#
|
20
|
+
# @param {String} database Database name
|
21
|
+
#
|
22
|
+
def create(database)
|
23
|
+
create_database(database)
|
24
|
+
|
25
|
+
process(database) do
|
26
|
+
import_database_schema
|
27
|
+
|
28
|
+
# Seed data if appropriate
|
29
|
+
seed_data if Apartment.seed_after_create
|
30
|
+
|
31
|
+
yield if block_given?
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# Get the current database name
|
36
|
+
#
|
37
|
+
# @return {String} current database name
|
38
|
+
#
|
39
|
+
def current_database
|
40
|
+
ActiveRecord::Base.connection.current_database
|
41
|
+
end
|
42
|
+
|
43
|
+
# Drop the database
|
44
|
+
#
|
45
|
+
# @param {String} database Database name
|
46
|
+
#
|
47
|
+
def drop(database)
|
48
|
+
# ActiveRecord::Base.connection.drop_database note that drop_database will not throw an exception, so manually execute
|
49
|
+
ActiveRecord::Base.connection.execute("DROP DATABASE #{environmentify(database)}" )
|
50
|
+
|
51
|
+
rescue ActiveRecord::StatementInvalid => e
|
52
|
+
raise DatabaseNotFound, "The database #{environmentify(database)} cannot be found"
|
53
|
+
end
|
54
|
+
|
55
|
+
# Prepend the environment if configured and the environment isn't already there
|
56
|
+
#
|
57
|
+
# @param {String} database Database name
|
58
|
+
# @return {String} database name with Rails environment *optionally* prepended
|
59
|
+
#
|
60
|
+
def environmentify(database)
|
61
|
+
Apartment.prepend_environment && !database.include?(Rails.env) ? "#{Rails.env}_#{database}" : database
|
62
|
+
end
|
63
|
+
|
64
|
+
# Connect to db, do your biz, switch back to previous db
|
65
|
+
#
|
66
|
+
# @param {String?} database Database or schema to connect to
|
67
|
+
#
|
68
|
+
def process(database = nil)
|
69
|
+
current_db = current_database
|
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
|
+
#
|
79
|
+
def process_excluded_models
|
80
|
+
# All other models will shared a connection (at ActiveRecord::Base) and we can modify at will
|
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
|
+
# actual object references. This way when we contantize, we always get the proper class reference
|
84
|
+
if excluded_model.is_a? Class
|
85
|
+
warn "[Deprecation Warning] Passing class references to excluded models is now deprecated, please use a string instead"
|
86
|
+
excluded_model = excluded_model.name
|
87
|
+
end
|
88
|
+
|
89
|
+
excluded_model.constantize.establish_connection @config
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# Reset the database connection to the default
|
94
|
+
#
|
95
|
+
def reset
|
96
|
+
ActiveRecord::Base.establish_connection @config
|
97
|
+
end
|
98
|
+
|
99
|
+
# Switch to new connection (or schema if appopriate)
|
100
|
+
#
|
101
|
+
# @param {String} database Database name
|
102
|
+
#
|
103
|
+
def switch(database = nil)
|
104
|
+
# Just connect to default db and return
|
105
|
+
return reset if database.nil?
|
106
|
+
|
107
|
+
connect_to_new(database)
|
108
|
+
end
|
109
|
+
|
110
|
+
# Load the rails seed file into the db
|
111
|
+
#
|
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
|
+
end
|
115
|
+
alias_method :seed, :seed_data
|
116
|
+
|
117
|
+
protected
|
118
|
+
|
119
|
+
# Create the database
|
120
|
+
#
|
121
|
+
# @param {String} database Database name
|
122
|
+
#
|
123
|
+
def create_database(database)
|
124
|
+
ActiveRecord::Base.connection.create_database( environmentify(database) )
|
125
|
+
|
126
|
+
rescue ActiveRecord::StatementInvalid => e
|
127
|
+
raise DatabaseExists, "The database #{environmentify(database)} already exists."
|
128
|
+
end
|
129
|
+
|
130
|
+
# Connect to new database
|
131
|
+
#
|
132
|
+
# @param {String} database Database name
|
133
|
+
#
|
134
|
+
def connect_to_new(database)
|
135
|
+
ActiveRecord::Base.establish_connection multi_tenantify(database)
|
136
|
+
ActiveRecord::Base.connection.active? # call active? to manually check if this connection is valid
|
137
|
+
|
138
|
+
rescue ActiveRecord::StatementInvalid => e
|
139
|
+
raise DatabaseNotFound, "The database #{environmentify(database)} cannot be found."
|
140
|
+
end
|
141
|
+
|
142
|
+
# Import the database schema
|
143
|
+
#
|
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
|
+
#
|
151
|
+
def multi_tenantify(database)
|
152
|
+
@config.clone.tap do |config|
|
153
|
+
config[:database] = environmentify(database)
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
# Load a file or abort if it doesn't exists
|
158
|
+
#
|
159
|
+
def load_or_abort(file)
|
160
|
+
if File.exists?(file)
|
161
|
+
load(file)
|
162
|
+
else
|
163
|
+
abort %{#{file} doesn't exist yet}
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
# Remove all non-alphanumeric characters
|
168
|
+
#
|
169
|
+
def sanitize(database)
|
170
|
+
warn "[Deprecation Warning] Sanitize is no longer used, client should ensure proper database names"
|
171
|
+
database.gsub(/[\W]/,'')
|
172
|
+
end
|
173
|
+
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
module Apartment
|
2
|
+
|
3
|
+
module Database
|
4
|
+
|
5
|
+
def self.jdbcpostgresql_adapter(config)
|
6
|
+
Apartment.use_postgres_schemas ?
|
7
|
+
Adapters::PostgresqlSchemaAdapter.new(config, :schema_search_path => ActiveRecord::Base.connection.schema_search_path) :
|
8
|
+
Adapters::PostgresqlAdapter.new(config)
|
9
|
+
end
|
10
|
+
|
11
|
+
end
|
12
|
+
|
13
|
+
module Adapters
|
14
|
+
|
15
|
+
# Default adapter when not using Postgresql Schemas
|
16
|
+
class PostgresqlAdapter < AbstractAdapter
|
17
|
+
|
18
|
+
protected
|
19
|
+
|
20
|
+
# Connect to new database
|
21
|
+
# Abstract adapter will catch generic ActiveRecord error
|
22
|
+
# Catch specific adapter errors here
|
23
|
+
#
|
24
|
+
# @param {String} database Database name
|
25
|
+
#
|
26
|
+
def connect_to_new(database)
|
27
|
+
super
|
28
|
+
rescue PGError
|
29
|
+
raise DatabaseNotFound, "Cannot find database #{environmentify(database)}"
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
# Separate Adapter for Postgresql when using schemas
|
35
|
+
class PostgresqlSchemaAdapter < AbstractAdapter
|
36
|
+
puts ActiveRecord::Base.connection.class
|
37
|
+
|
38
|
+
# Get the current schema search path
|
39
|
+
#
|
40
|
+
# @return {String} current schema search path
|
41
|
+
#
|
42
|
+
def current_database
|
43
|
+
ActiveRecord::Base.connection.schema_search_path
|
44
|
+
end
|
45
|
+
|
46
|
+
# Drop the database schema
|
47
|
+
#
|
48
|
+
# @param {String} database Database (schema) to drop
|
49
|
+
#
|
50
|
+
def drop(database)
|
51
|
+
ActiveRecord::Base.connection.execute("DROP SCHEMA #{database} CASCADE")
|
52
|
+
|
53
|
+
rescue ActiveRecord::StatementInvalid
|
54
|
+
raise SchemaNotFound, "The schema #{database.inspect} cannot be found."
|
55
|
+
end
|
56
|
+
|
57
|
+
# Reset search path to default search_path
|
58
|
+
# Set the table_name to always use the public namespace for excluded models
|
59
|
+
#
|
60
|
+
def process_excluded_models
|
61
|
+
Apartment.excluded_models.each do |excluded_model|
|
62
|
+
# Note that due to rails reloading, we now take string references to classes rather than
|
63
|
+
# actual object references. This way when we contantize, we always get the proper class reference
|
64
|
+
if excluded_model.is_a? Class
|
65
|
+
warn "[Deprecation Warning] Passing class references to excluded models is now deprecated, please use a string instead"
|
66
|
+
excluded_model = excluded_model.name
|
67
|
+
end
|
68
|
+
|
69
|
+
excluded_model.constantize.tap do |klass|
|
70
|
+
# some models (such as delayed_job) seem to load and cache their column names before this,
|
71
|
+
# so would never get the public prefix, so reset first
|
72
|
+
klass.reset_column_information
|
73
|
+
|
74
|
+
# Ensure that if a schema *was* set, we override
|
75
|
+
table_name = klass.table_name.split('.', 2).last
|
76
|
+
|
77
|
+
# Not sure why, but Delayed::Job somehow ignores table_name_prefix... so we'll just manually set table name instead
|
78
|
+
klass.table_name = "public.#{table_name}"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# Reset schema search path to the default schema_search_path
|
84
|
+
#
|
85
|
+
# @return {String} default schema search path
|
86
|
+
#
|
87
|
+
def reset
|
88
|
+
ActiveRecord::Base.connection.schema_search_path = @defaults[:schema_search_path]
|
89
|
+
end
|
90
|
+
|
91
|
+
protected
|
92
|
+
|
93
|
+
# Set schema search path to new schema
|
94
|
+
#
|
95
|
+
def connect_to_new(database = nil)
|
96
|
+
return reset if database.nil?
|
97
|
+
ActiveRecord::Base.connection.schema_search_path = database
|
98
|
+
|
99
|
+
rescue ActiveRecord::StatementInvalid
|
100
|
+
raise SchemaNotFound, "The schema #{database.inspect} cannot be found."
|
101
|
+
end
|
102
|
+
|
103
|
+
# Create the new schema
|
104
|
+
#
|
105
|
+
def create_database(database)
|
106
|
+
ActiveRecord::Base.connection.execute("CREATE SCHEMA #{database}")
|
107
|
+
|
108
|
+
rescue ActiveRecord::StatementInvalid
|
109
|
+
raise SchemaExists, "The schema #{database} already exists."
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
module Apartment
|
2
|
+
|
3
|
+
module Database
|
4
|
+
|
5
|
+
def self.postgresql_adapter(config)
|
6
|
+
Apartment.use_postgres_schemas ?
|
7
|
+
Adapters::PostgresqlSchemaAdapter.new(config, :schema_search_path => ActiveRecord::Base.connection.schema_search_path) :
|
8
|
+
Adapters::PostgresqlAdapter.new(config)
|
9
|
+
end
|
10
|
+
|
11
|
+
end
|
12
|
+
|
13
|
+
module Adapters
|
14
|
+
|
15
|
+
# Default adapter when not using Postgresql Schemas
|
16
|
+
class PostgresqlAdapter < AbstractAdapter
|
17
|
+
|
18
|
+
protected
|
19
|
+
|
20
|
+
# Connect to new database
|
21
|
+
# Abstract adapter will catch generic ActiveRecord error
|
22
|
+
# Catch specific adapter errors here
|
23
|
+
#
|
24
|
+
# @param {String} database Database name
|
25
|
+
#
|
26
|
+
def connect_to_new(database)
|
27
|
+
super
|
28
|
+
rescue PGError
|
29
|
+
raise DatabaseNotFound, "Cannot find database #{environmentify(database)}"
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
# Separate Adapter for Postgresql when using schemas
|
35
|
+
class PostgresqlSchemaAdapter < AbstractAdapter
|
36
|
+
|
37
|
+
# Get the current schema search path
|
38
|
+
#
|
39
|
+
# @return {String} current schema search path
|
40
|
+
#
|
41
|
+
def current_database
|
42
|
+
ActiveRecord::Base.connection.schema_search_path
|
43
|
+
end
|
44
|
+
|
45
|
+
# Drop the database schema
|
46
|
+
#
|
47
|
+
# @param {String} database Database (schema) to drop
|
48
|
+
#
|
49
|
+
def drop(database)
|
50
|
+
ActiveRecord::Base.connection.execute("DROP SCHEMA #{database} CASCADE")
|
51
|
+
|
52
|
+
rescue ActiveRecord::StatementInvalid
|
53
|
+
raise SchemaNotFound, "The schema #{database.inspect} cannot be found."
|
54
|
+
end
|
55
|
+
|
56
|
+
# Reset search path to default search_path
|
57
|
+
# Set the table_name to always use the public namespace for excluded models
|
58
|
+
#
|
59
|
+
def process_excluded_models
|
60
|
+
Apartment.excluded_models.each do |excluded_model|
|
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
|
72
|
+
|
73
|
+
# Ensure that if a schema *was* set, we override
|
74
|
+
table_name = klass.table_name.split('.', 2).last
|
75
|
+
|
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
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
# Reset schema search path to the default schema_search_path
|
83
|
+
#
|
84
|
+
# @return {String} default schema search path
|
85
|
+
#
|
86
|
+
def reset
|
87
|
+
ActiveRecord::Base.connection.schema_search_path = @defaults[:schema_search_path]
|
88
|
+
end
|
89
|
+
|
90
|
+
protected
|
91
|
+
|
92
|
+
# Set schema search path to new schema
|
93
|
+
#
|
94
|
+
def connect_to_new(database = nil)
|
95
|
+
return reset if database.nil?
|
96
|
+
ActiveRecord::Base.connection.schema_search_path = database
|
97
|
+
|
98
|
+
rescue ActiveRecord::StatementInvalid
|
99
|
+
raise SchemaNotFound, "The schema #{database.inspect} cannot be found."
|
100
|
+
end
|
101
|
+
|
102
|
+
# Create the new schema
|
103
|
+
#
|
104
|
+
def create_database(database)
|
105
|
+
ActiveRecord::Base.connection.execute("CREATE SCHEMA #{database}")
|
106
|
+
|
107
|
+
rescue ActiveRecord::StatementInvalid
|
108
|
+
raise SchemaExists, "The schema #{database} already exists."
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
end
|
@@ -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 {}).call({})
|
9
|
+
# Manually init Apartment again once classes are reloaded
|
10
|
+
Apartment::Database.init
|
11
|
+
true
|
12
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'active_support/core_ext/module/delegation'
|
2
|
+
|
3
|
+
module Apartment
|
4
|
+
|
5
|
+
# The main entry point to Apartment functions
|
6
|
+
module Database
|
7
|
+
|
8
|
+
extend self
|
9
|
+
|
10
|
+
delegate :create, :current_database, :drop, :process, :process_excluded_models, :reset, :seed, :switch, :to => :adapter
|
11
|
+
|
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
|
31
|
+
|
32
|
+
unless respond_to?(adapter_method)
|
33
|
+
raise AdapterNotFound, "database configuration specifies nonexistent #{config[:adapter]} adapter"
|
34
|
+
end
|
35
|
+
|
36
|
+
send(adapter_method, config)
|
37
|
+
end
|
38
|
+
end
|
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
|
56
|
+
|
57
|
+
end
|