45 votes

Création d'une application multi-locataire à l'aide des schémas et des Rails de PostgreSQL

Des choses que j'ai déjà compris

Je suis en train d'apprendre comment créer une application multi-locataires dans les Rails qui sert de données à partir de différents schémas basés sur ce domaine ou sous-domaine est utilisé pour afficher l'application.

J'ai déjà quelques inquiétudes répondu:

  1. Comment pouvez-vous obtenir un sous-domaine-fu de travailler avec des domaines ainsi? Voilà quelqu'un qui a posé la même question qui vous conduit vers ce blog.
  2. Quelle base de données, et comment est-il structuré? Voici un excellent parler par Guy Naor, et la bonne question à propos de PostgreSQL et de schémas.
  3. Je connais déjà mes schémas ont tous la même structure. Ils diffèrent dans les données qu'ils détiennent. Alors, comment pouvez-vous exécuter les migrations pour tous les schémas? Voici une réponse.

Ces trois points de couvrir beaucoup de la générale des trucs que j'ai besoin de savoir. Cependant, dans les prochaines étapes que j'ai semblent avoir de nombreux moyens de mise en œuvre de choses. J'espère qu'il y a une meilleure, la plus facile.

Enfin, à ma question

Lorsqu'un nouvel utilisateur se connecte, je peux facilement créer le schéma. Cependant, quelle serait la meilleure et la plus simple façon de charger la structure que le reste des schémas déjà? Voici quelques questions/scénarios qui pourraient vous donner une meilleure idée.

  1. Dois-je transmettre à un script shell qui vide le schéma public dans un temporaire, et les importations de revenir vers ma base de données principale (un peu comme ce Gars Naor dit dans sa vidéo)? Voici un résumé rapide/script que j'ai eu de l'aide de la #postgres sur freenode. Bien que ce sera probablement le travail, je vais avoir à faire beaucoup de choses en dehors des Rails, ce qui me rend un peu mal à l'aise.. ce qui m'amène à la question suivante.
  2. Est-il un moyen de le faire directement à partir de Ruby on Rails? Par exemple, créer une PostgreSQL schéma, puis il suffit de charger les Rails de schéma de base de données (schéma.rb - je sais, c'est source de confusion) dans PostgreSQL schéma.
  3. Est-il un gem/plugin qui a ces choses déjà? Des méthodes comme "create_pg_schema_and_load_rails_schema(the_new_schema_name)". Si il n'y a rien, je vais probablement travailler à en faire un, mais je doute sur comment bien testé ça va être avec toutes les pièces en mouvement (surtout si je finis à l'aide d'un script shell pour créer et gérer de nouveaux PostgreSQL schémas).

Merci, et j'espère que ce n'était pas trop long!

12voto

Ramon Tayag Points 1827

Mise À Jour Le 5 Décembre 2011

Grâce à Brad Robertson et son équipe, il y a l' Appartement de gem. Il est très utile et fait beaucoup de levage lourd.

Toutefois, si vous serez à bricoler avec des schémas, je vous suggère fortement de savoir comment il fonctionne réellement. Familiarisez-vous avec Jerod Santo procédure pas à pas , de sorte que vous saurez ce que l'Appartement gem est plus ou moins en train de faire.

Mise à jour Août 20, 2011 11:23 GMT+8

Quelqu'un a créé un blog et des promenades, bien que l'ensemble de ce processus plutôt bien.

Mise à jour le 11 Mai 2010 11:26 GMT+8

Depuis la nuit dernière, je ai été en mesure d'obtenir une méthode de travail qui crée un nouveau schéma et les charges de schéma.rb en elle. Vous ne savez pas si ce que je fais est correct (semble bien fonctionner, jusqu'à présent), mais c'est une étape de plus au moins. Si il y a une meilleure manière s'il vous plaît laissez-moi savoir.


  module SchemaUtils
   def self.add_schema_to_path(schema)
    conn = ActiveRecord::Base.connection
    conn.execute "SET search_path TO #{schema}, #{conn.schema_search_path}"
   end

   def self.reset_search_path
    conn = ActiveRecord::Base.connection
    conn.execute "SET search_path TO #{conn.schema_search_path}"
   end

   def self.create_and_migrate_schema(schema_name)
    conn = ActiveRecord::Base.connection

    schemas = conn.select_values("select * from pg_namespace where nspname != 'information_schema' AND nspname NOT LIKE 'pg%'")

    if schemas.include?(schema_name)
     tables = conn.tables
     Rails.logger.info "#{schema_name} exists already with these tables #{tables.inspect}"
    else
     Rails.logger.info "About to create #{schema_name}"
     conn.execute "create schema #{schema_name}"
    end

    # Save the old search path so we can set it back at the end of this method
    old_search_path = conn.schema_search_path

    # Tried to set the search path like in the methods above (from Guy Naor)
    # [METHOD 1]: conn.execute "SET search_path TO #{schema_name}"
    # But the connection itself seems to remember the old search path.
    # When Rails executes a schema it first asks if the table it will load in already exists and if :force => true. 
    # If both true, it will drop the table and then load it. 
    # The problem is that in the METHOD 1 way of setting things, ActiveRecord::Base.connection.schema_search_path still returns $user,public.
    # That means that when Rails tries to load the schema, and asks if the tables exist, it searches for these tables in the public schema.
    # See line 655 in Rails 2.3.5 activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
    # That's why I kept running into this error of the table existing when it didn't (in the newly created schema).
    # If used this way [METHOD 2], it works. ActiveRecord::Base.connection.schema_search_path returns the string we pass it.
    conn.schema_search_path = schema_name

    # Directly from databases.rake. 
    # In Rails 2.3.5 databases.rake can be found in railties/lib/tasks/databases.rake
    file = "#{Rails.root}/db/schema.rb"
    if File.exists?(file)
     Rails.logger.info "About to load the schema #{file}"
     load(file)
    else
     abort %{#{file} doesn't exist yet. It's possible that you just ran a migration!}
    end

    Rails.logger.info "About to set search path back to #{old_search_path}."
    conn.schema_search_path = old_search_path
   end
  end

3voto

Brendan Hay Points 11

Changer la ligne 38 à:

 conn.schema_search_path = "#{schema_name}, #{old_search_path}"
 

Je présume que postgres tente de rechercher les noms de tables existants lors du chargement de schema.rb et que vous avez défini le chemin search_path de manière à ne contenir que le nouveau schéma, il échoue. Bien entendu, cela suppose que vous avez toujours le schéma public dans votre base de données.

J'espère que cela pourra aider.

0voto

Sergey Potapov Points 277

Y a-t-il un gem / plugin qui a déjà ces choses?

pg_power fournit cette fonctionnalité pour créer / supprimer des schémas PostgreSQL en migration, comme ceci:

 def change
  # Create schema
  create_schema 'demography'

  # Create new table in specific schema
  create_table "countries", :schema => "demography" do |t|
    # columns goes here
  end

  # Drop schema
  drop_schema 'politics'
end
 

En outre, il prend soin de vider correctement les schémas dans le fichier schema.rb.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X