Múltiples bases de datos en Rails
Se Puede hacer esto? En una sola aplicación, que gestiona muchos proyectos con SQLite. Lo que quiero es tener una base de datos diferente para cada proyecto que gestione mi aplicación.. así que múltiples copias de una base de datos idéntica estructura, pero con diferentes datos en ellos. Voy a elegir qué copia utilizar en base params en el URI.
Esto se hace para 1. seguridad.. Soy un novato en este tipo de programación y no quiero que suceda que por alguna razón mientras trabajo en un Proyecto otro se corrompe.. 2. fácil copia de seguridad y archivo de proyectos antiguos
7 answers
Rails por defecto no está diseñado para una arquitectura de bases de datos múltiples y, en la mayoría de los casos, no tiene ningún sentido. Pero sí, puede utilizar diferentes bases de datos y conexiones.
Aquí hay algunas referencias:
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-12-02 11:50:57
Si es capaz de controlar y configurar cada instancia de Rails, y puede permitirse el lujo de desperdiciar recursos debido a que están en espera, ahórrese algunos problemas y simplemente cambie la base de datos.yml para modificar la conexión de base de datos utilizada en cada instancia. Si le preocupa el rendimiento, este enfoque no lo logrará.
Para los modelos enlazados a una sola tabla única en una sola base de datos, puede llamar a establish_connection dentro del modelo:
establish_connection "database_name_#{RAILS_ENV}"
Como se describe aquí: http://apidock.com/rails/ActiveRecord/Base/establish_connection/class
Tendrá algunos modelos usando tablas de una base de datos y otros modelos diferentes usando tablas de otras bases de datos.
Si tiene tablas idénticas, comunes en diferentes bases de datos y compartidas por un solo modelo, ActiveRecord no lo ayudará. En el 2009 lo necesité en un proyecto en el que estaba trabajando, usando Rails 2.3.8. Tenía una base de datos para cada cliente, y nombré las bases de datos con sus identificaciones. Así que creé un método para cambiar la conexión dentro de ApplicationController:
def change_database database_id = params[:company_id]
return if database_id.blank?
configuration = ActiveRecord::Base.connection.instance_eval { @config }.clone
configuration[:database] = "database_name_#{database_id}_#{RAILS_ENV}"
MultipleDatabaseModel.establish_connection configuration
end
Y agregó ese método como un before_filter a todos los controladores:
before_filter :change_database
Así que para cada acción de cada controlador, cuando params[:company_id] se define y establece, cambiará la base de datos a la correcta.
Para manejar las migraciones extendí ActiveRecord:: Migration, con un método que busca todos los clientes e itera un bloque con cada ID:
class ActiveRecord::Migration
def self.using_databases *args
configuration = ActiveRecord::Base.connection.instance_eval { @config }
former_database = configuration[:database]
companies = args.blank? ? Company.all : Company.find(args)
companies.each do |company|
configuration[:database] = "database_name_#{company[:id]}_#{RAILS_ENV}"
ActiveRecord::Base.establish_connection configuration
yield self
end
configuration[:database] = former_database
ActiveRecord::Base.establish_connection configuration
end
end
Tenga en cuenta que por al hacer esto, sería imposible realizar consultas dentro de la misma acción desde dos bases de datos diferentes. Puede llamar a change_database de nuevo, pero se volverá desagradable cuando intente usar métodos que ejecuten consultas, desde los objetos que ya no están vinculados a la base de datos correcta. Además, es obvio que no podrá unir tablas que pertenezcan a diferentes bases de datos.
Para manejar esto correctamente, ActiveRecord debe ampliarse considerablemente. Ya debería haber un plugin para ayudarle con este problema. Una investigación rápida me dio este:
DB-Charmer: http://kovyrin.github.com/db-charmer /
Estoy dispuesto a probarlo. Hazme saber qué funciona para ti.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-10-04 08:35:38
Superé esto agregando esto a la parte superior de mis modelos usando la otra base de datos
class Customer < ActiveRecord::Base
ENV["RAILS_ENV"] == "development" ? host = 'devhost' : host = 'prodhost'
self.establish_connection(
:adapter => "mysql",
:host => "localhost",
:username => "myuser",
:password => "mypass",
:database => "somedatabase"
)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-02-25 17:24:39
También deberías echar un vistazo a este proyecto llamado DB Charmer: http://kovyrin.net/2009/11/03/db-charmer-activerecord-connection-magic-plugin /
DbCharmer es un plugin simple pero potente para ActiveRecord que hace algunas cosas:
- Le permite administrar fácilmente las conexiones de los modelos AR (método
switch_connection_to
)- Le permite cambiar las conexiones predeterminadas de los modelos AR a servidores/bases de datos separados
- le Permite elegir fácilmente donde su query should go (
on_*
familia de métodos)- Le permite enviar automáticamente consultas de lectura a sus esclavos mientras que los maestros manejarían todas las actualizaciones.
- Añade múltiples migraciones de bases de datos a ActiveRecord
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-12-02 12:08:51
Vale la pena señalar que en todas estas soluciones debe recordar cerrar las conexiones de base de datos personalizadas. se quedará sin conexiones y verá problemas de tiempo de espera de solicitud extraños de lo contrario.
Una solución fácil es clear_active_connections! en un after_filter en su controlador.
after_filter :close_custom_db_connection
def close_custom_db_connection
MyModelWithACustomDBConnection.clear_active_connections!
end
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-12-14 17:09:27
En su configuración/base de datos.yml hacer algo como esto
default: &default
adapter: postgresql
encoding: unicode
pool: 5
development:
<<: *default
database: mysite_development
test:
<<: *default
database: mysite_test
production:
<<: *default
host: 10.0.1.55
database: mysite_production
username: postgres_user
password: <%= ENV['DATABASE_PASSWORD'] %>
db2_development:
<<: *default
database: db2_development
db2_test:
<<: *default
database: db2_test
db2_production:
<<: *default
host: 10.0.1.55
database: db2_production
username: postgres_user
password: <%= ENV['DATABASE_PASSWORD'] %>
Luego en sus modelos puede hacer referencia a db2 con
class Customers < ActiveRecord::Base
establish_connection "db2_#{Rails.env}".to_sym
end
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-23 21:57:59
Lo que has descrito en la pregunta es multitenancia (bases de datos estructuradas de forma idéntica con diferentes datos en cada una). El Apartamento gem es ideal para esto.
Para la cuestión general de múltiples bases de datos en Rails: ActiveRecord soporta múltiples bases de datos, pero Rails no proporciona una forma de administrarlas. Recientemente creé la gema Multiverso para abordar esto.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-13 06:26:11