Si vous êtes en mesure de contrôler et de configurer chaque instance de Rails, et que vous pouvez vous permettre de gaspiller des ressources parce qu'elles sont en standby, épargnez vous quelques soucis et changez simplement le database.yml pour modifier la connexion à la base de données utilisée sur chaque instance. Si vous êtes préoccupé par les performances, cette approche ne sera pas suffisante.
Pour les modèles liés à une seule table unique sur une seule base de données, vous pouvez appeler establish_connection à l'intérieur du modèle :
establish_connection "database_name_#{RAILS_ENV}"
Comme décrit ici : http://apidock.com/rails/ActiveRecord/Base/establish_connection/class
Vous aurez certains modèles utilisant des tables d'une base de données et d'autres modèles différents utilisant des tables d'autres bases de données.
Si vous avez des tables identiques, communes sur différentes bases de données, et partagées par un seul modèle, ActiveRecord ne vous aidera pas. En 2009, j'ai eu besoin de cela sur un projet sur lequel je travaillais, en utilisant Rails 2.3.8. J'avais une base de données pour chaque client, et j'ai nommé les bases de données avec leurs IDs. J'ai donc créé une méthode pour changer la connexion dans 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
Et j'ai ajouté cette méthode comme un avant_filtre à tous les contrôleurs :
before_filter :change_database
Ainsi, pour chaque action de chaque contrôleur, lorsque params[:company_id] est défini et activé, la base de données est modifiée pour devenir la bonne.
Pour gérer les migrations j'ai étendu ActiveRecord::Migration, avec une méthode qui cherche tous les clients et itère un bloc avec chaque 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
Notez qu'en procédant ainsi, il vous serait impossible d'effectuer des requêtes dans la même action à partir de deux bases de données différentes. Vous pouvez appeler change_database mais cela devient désagréable lorsque vous essayez d'utiliser des méthodes qui exécutent des requêtes, à partir des objets qui ne sont plus liés à la bonne base de données. De plus, il est évident que vous ne pourrez pas joindre des tables qui appartiennent à des bases de données différentes.
Pour gérer cela correctement, ActiveRecord devrait être considérablement étendu. Il devrait y avoir un plugin pour vous aider à résoudre ce problème. Une recherche rapide m'a donné celui-ci :
DB-Charmer : http://kovyrin.github.com/db-charmer/
Je suis prêt à l'essayer. Faites-moi savoir ce qui fonctionne pour vous.
0 votes
imnithin.github.io/multiple-database.html