web-dev-qa-db-fra.com

Plusieurs bases de données dans Rails

Cela peut-il être fait? Dans une seule application, qui gère de nombreux projets avec SQLite . Ce que je veux, c'est une base de données différente pour chaque projet géré par mon application ... donc plusieurs copies d'une base de données de structure identique, mais contenant des données différentes. Je choisirai quelle copie utiliser sur la base des paramètres de l'URI.

Ceci est fait pour 1. la sécurité .. Je suis un novice dans ce type de programmation et je ne veux pas que, pour une raison quelconque, tout en travaillant sur un projet, un autre soit corrompu .. 2. sauvegarde et archivage faciles de anciens projets

50
luca

Par défaut, Rails n'est pas conçu pour une architecture à plusieurs bases de données et, dans la plupart des cas, cela n'a aucun sens.

Voici quelques références:

39
Simone Carletti

Si vous êtes en mesure de contrôler et de configurer chaque instance Rails et que vous pouvez vous permettre de gaspiller des ressources en raison de leur mise en veille, évitez les problèmes 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 suffira pas.

Pour les modèles liés à une seule table unique sur une seule base de données, vous pouvez appeler Establ_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

Certains modèles utilisent des tables d’une base de données et d’autres modèles utilisent 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'avais besoin de cela pour un projet sur lequel je travaillais, 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 identifiants. 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 ajouté cette méthode en tant que before_filter à tous les contrôleurs:

before_filter :change_database

Ainsi, pour chaque action de chaque contrôleur, lorsque params [: id_entreprise] est défini et défini, la base de données sera remplacée par la bonne.

Pour gérer les migrations, j'ai étendu ActiveRecord :: Migration, avec une méthode qui recherche 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 faisant cela, il vous serait impossible de faire des requêtes dans la même action à partir de deux bases de données différentes. Vous pouvez appeler change_database à nouveau, mais cela deviendra désagréable si vous essayez d'utiliser des méthodes qui exécutent des requêtes, à partir des objets qui ne sont plus liés à la base de données correcte. De plus, il est évident que vous ne pourrez pas joindre des tables appartenant à différentes bases de données.

Pour gérer cela correctement, ActiveRecord doit être considérablement étendu. Il devrait déjà y avoir un plugin pour vous aider avec 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.

26
adeandrade

Je l'ai dépassé en ajoutant ceci au sommet de mes modèles en utilisant l'autre base de données

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"
    )
12
rdaniels

Vous devriez également consulter ce projet appelé DB Charmer: http://kovyrin.net/2009/11/03/db-charmer-activerecord-connection-magic-plugin/

DbCharmer est un plugin simple mais puissant pour ActiveRecord qui fait quelques choses:

  1. Permet de gérer facilement les connexions des modèles AR (méthode switch_connection_to
  2. Permet de basculer les connexions par défaut des modèles AR sur un serveur/une base de données distinct
  3. Vous permet de choisir facilement où votre requête doit aller (famille de méthodes on_*)
  4. Vous permet d'envoyer automatiquement des requêtes de lecture à vos esclaves tandis que les maîtres gèrent toutes les mises à jour.
  5. Ajoute plusieurs migrations de bases de données à ActiveRecord 
4
SquareCog

Il convient de noter que dans toutes ces solutions, vous devez vous rappeler de fermer les connexions de base de données personnalisées. Vous serez à court de connexions et voyez les problèmes étranges de dépassement de délai de demande autrement.

Une solution simple consiste à clear_active_connections! dans un filtre after_filter de votre contrôleur.

after_filter :close_custom_db_connection

def close_custom_db_connection
  MyModelWithACustomDBConnection.clear_active_connections!
end
2
Steven Soroka

La meilleure solution que j'ai trouvée jusqu'à présent est la suivante:

Il y a 3 architectures de base de données que nous pouvons approcher.

  • Base de données unique pour un seul locataire
  • Schéma séparé pour chaque locataire
  • Schéma partagé pour les locataires

Remarque: ils ont certains avantages et inconvénients dépend de votre cas d'utilisation.

Je viens de ceci Blog ! Se tient très utile pour moi.

Vous pouvez utiliser le joyau Appartement pour Rails

Vous pouvez suivre la référence vidéo sur Gorails for apartment

0
Dibyajit Goswami

Ce que vous avez décrit dans la question est la multi-organisation (bases de données structurées de manière identique avec des données différentes dans chacune). Le appartement bijou est idéal pour cela.

Pour la question générale de plusieurs bases de données dans Rails: ActiveRecord prend en charge plusieurs bases de données, mais Rails ne permet pas de les gérer. J'ai récemment créé le Multiverse gem pour résoudre ce problème.

0
Andrew Kane

dans votre config/database.yml faire quelque chose comme ça

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'] %>

alors dans vos modèles, vous pouvez référencer db2 avec

class Customers < ActiveRecord::Base
  establish_connection "db2_#{Rails.env}".to_sym
end
0
rdaniels