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:
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.
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.
Danke und ich hoffe das war nicht zu lange!
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
Ä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.
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.