Railsで、アプリケーションの表示に使用されるドメインまたはサブドメインに基づいてさまざまなスキーマからのデータを提供するマルチテナントアプリケーションを作成する方法を学習しています。
私はすでにいくつかの懸念に答えています:
これらの3つのポイントは、私が知る必要のある一般的なことの多くをカバーしています。しかし、次のステップでは、物事を実装する方法がたくさんあるようです。より良い、より簡単な方法があることを願っています。
新しいユーザーがサインアップすると、スキーマを簡単に作成できます。ただし、残りのスキーマがすでに持っている構造をロードするための最良かつ最も簡単な方法は何でしょうか?ここにいくつかの質問/シナリオがありますあなたはより良い考えです。
ありがとう、そして私はそれが長すぎなかったことを願っています!
2011年12月5日更新
ブラッド・ロバートソンと彼のチームのおかげで、 アパートの宝石 があります。それは非常に便利で、多くの手間のかかる作業を行います。
ただし、スキーマをいじくり回す場合は、スキーマが実際にどのように機能するかを知っておくことを強くお勧めします。 Jerod Santoのウォークスルー をよく理解してください。そうすれば、アパートの宝石が多かれ少なかれ何をしているのかがわかります。
2011年8月20日11:23 GMT + 8を更新
誰かが ブログ投稿 を作成し、このプロセス全体をかなりうまく歩きます。
2010年5月11日11:26 GMT + 8を更新
昨夜から、新しいスキーマを作成してそれにschema.rbをロードするメソッドを機能させることができました。私がしていることが正しいかどうかはわかりませんが(これまでのところうまく機能しているようです)、少なくとも一歩近づいています。もっと良い方法があれば教えてください。
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
38行目を次のように変更します。
conn.schema_search_path = "#{schema_name}, #{old_search_path}"
Postgresがschema.rbをロードするときに既存のテーブル名を検索しようとしていると思いますが、search_pathを新しいスキーマのみを含むように設定しているため、失敗します。もちろん、これは、データベースにまだパブリックスキーマがあることを前提としています。
お役に立てば幸いです。
これらのものをすでに持っている宝石/プラグインはありますか?
pg_power は、次のように、移行時にPostgreSQLスキーマを作成/削除するためのこの機能を提供します。
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
また、schema.rbファイルにスキーマを正しくダンプすることにも注意を払います。