it-swarm.com.de

Erstellen einer mandantenfähigen Anwendung mit den PostgreSQL-Schemas und Rails

Sachen, die ich schon herausgefunden habe

Ich lerne, wie in Rails eine mandantenfähige Anwendung erstellt wird, die Daten aus verschiedenen Schemata basierend auf der Domäne oder Subdomäne bereitstellt, die zum Anzeigen der Anwendung verwendet wird.

Ich habe schon ein paar Bedenken beantwortet:

  1. Wie können Sie Subdomain-Fu dazu bringen, auch mit Domains zu arbeiten? Hier ist jemand, der die gleiche Frage gestellt hat was dich zu diesem Blog führt .
  2. Welche Datenbank und wie wird sie aufgebaut sein? Hier ist ein ausgezeichneter Vortrag von Guy Naor und eine gute Frage zu PostgreSQL und Schemata .
  3. Ich weiß bereits, dass meine Schemata alle dieselbe Struktur haben werden. Sie unterscheiden sich in den Daten, die sie enthalten. Also, wie können Sie Migrationen für alle Schemata ausführen? Hier ist eine Antwort .

Diese drei Punkte decken eine Menge der allgemeinen Dinge ab, die ich wissen muss. In den nächsten Schritten scheint es mir jedoch viele Möglichkeiten zu geben, Dinge umzusetzen. Ich hoffe, dass es einen besseren und einfacheren Weg gibt.

Zum Schluss zu meiner Frage

Wenn sich ein neuer Benutzer anmeldet, kann ich das Schema problemlos erstellen. Jedoch Was wäre die beste und einfachste Möglichkeit, die Struktur zu laden, die die übrigen Schemata bereits haben? Hier sind einige Fragen/Szenarien, die Ihnen eine bessere Vorstellung geben könnten.

  1. Soll ich es an ein Shell-Skript weitergeben , das das öffentliche Schema in ein temporäres Schema kopiert und es wieder in meine Hauptdatenbank importiert (so wie Guy Naor es in seinem Video sagt)? Hier ist eine kurze Zusammenfassung/ein Skript, das ich von dem hilfreichen #postgres auf freenode bekommen habe. Während dies wahrscheinlich funktionieren wird, muss ich eine Menge Dinge außerhalb von Rails erledigen, was mich etwas unbehaglich macht. Das bringt mich auch zur nächsten Frage.
  2. Gibt es eine Möglichkeit, dies direkt von Ruby on Rails aus zu tun ? Erstellen Sie beispielsweise ein PostgreSQL-Schema und laden Sie dann einfach das Rails-Datenbankschema (schema.rb - ich weiß, es ist verwirrend) in dieses PostgreSQL-Schema.
  3. Gibt es ein Juwel/Plugin, das diese Dinge bereits hat? Methoden wie "create_pg_schema_and_load_Rails_schema (the_new_schema_name)". Wenn es keins gibt, werde ich wahrscheinlich daran arbeiten, eines zu erstellen, aber ich bin mir nicht sicher, wie gut es mit all den sich bewegenden Teilen getestet wird (insbesondere, wenn ich ein Shell-Skript zum Erstellen und Verwalten neuer PostgreSQL-Schemas verwende).

Danke und ich hoffe das war nicht zu lange!

45
Ramon Tayag

Update 5. Dezember 2011

Dank Brad Robertson und seinem Team gibt es das Apartment Juwel . Es ist sehr nützlich und macht einen großen Teil des schweren Hebens.

Wenn Sie jedoch an Schemata basteln, empfehle ich dringend, zu wissen, wie es tatsächlich funktioniert. Machen Sie sich mit Jerod Santos Lösungsweg vertraut, damit Sie wissen, was das Apartment-Juwel mehr oder weniger tut.

Aktualisierung am 20. August 2011 um 11:23 Uhr GMT + 8

Jemand hat einen Blogpost erstellt und geht diesen ganzen Prozess ziemlich gut durch.

Update 11. Mai 2010 11:26 GMT + 8

Seit letzter Nacht kann ich eine Methode zum Laufen bringen, die ein neues Schema erstellt und schema.rb darin lädt. Ich bin mir nicht sicher, ob das, was ich tue, korrekt ist (scheint bisher gut zu funktionieren), aber es ist zumindest ein Schritt näher. Wenn es einen besseren Weg gibt, lass es mich bitte wissen.


  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
12
Ramon Tayag

Ändern Sie Zeile 38 in:

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

Ich gehe davon aus, dass postgres versucht, beim Laden von schema.rb nach vorhandenen Tabellennamen zu suchen, und da Sie den Suchpfad so festgelegt haben, dass er nur das neue Schema enthält, schlägt dies fehl. Dies setzt natürlich voraus, dass Sie noch das öffentliche Schema in Ihrer Datenbank haben.

Hoffentlich hilft das.

3
Brendan Hay

Gibt es ein Juwel/Plugin, das diese Dinge bereits hat?

pg_power bietet diese Funktionalität zum Erstellen/Löschen von PostgreSQL-Schemas bei der Migration:

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

Außerdem wird darauf geachtet, dass die Schemata korrekt in die Datei schema.rb geschrieben werden.

0
Sergey Potapov