Создание многопользовательского приложения с использованием схем PostgreSQL и Rails
вещи, которые я уже понял
Я изучаю, как создать многопользовательское приложение в Rails, которое обслуживает данные из разных схем на основе того, какой домен или поддомен используется для просмотра приложения.
у меня уже есть несколько вопросов ответил:
- как вы можете заставить subdomain-fu работать с доменами? вот кто-то, кто задал тот же вопрос что приводит вас к этот блог.
- какая база данных и как она будет структурирована? вот отличный разговор Гая Наора, а лучше вопрос о PostgreSQL и схемы.
- Я уже знаю, что мои схемы будут иметь одинаковую структуру. Они будут отличаться по данным, которые они хранят. Итак,как вы можете запускать миграции для всех схем? здесь ответ.
те 3 пункта покрывают много общие вещи, которые мне нужно знать. Однако на следующих шагах у меня, похоже, есть много способов реализации. Я надеюсь, что есть лучший, более простой способ.
наконец, на мой вопрос
когда новый пользователь регистрируется, я могу легко создать схему. Однако,каков был бы лучший и самый простой способ загрузить структуру, которую уже имеют остальные схемы? вот некоторые вопросы/сценарии, которые могут дать вам лучше идея.
- должен ли я передать его shell script это сбрасывает публичную схему во временную и импортирует ее обратно в мою основную базу данных (в значительной степени, как говорит Гай Наор в своем видео)? Вот краткое резюме / скрипт, который я получил от полезного #postgres на freenode. Хотя это, вероятно, сработает, мне придется делать много вещей за пределами рельсов, что делает меня немного неудобным.. что также приводит меня к следующему вопрос.
- есть ли способ сделать это прямо из Ruby on Rails? Например, создайте схему PostgreSQL, а затем просто загрузите схему базы данных Rails (schema.rb-я знаю, это запутанно) в эту схему PostgreSQL.
- есть ли gem / плагин, который уже имеет эти вещи? методы, такие как"create_pg_schema_and_load_rails_schema(the_new_schema_name)". Если нет, я, вероятно, буду работать над его созданием, но я сомневаюсь в том, насколько хорошо проверено это будет со всеми движущимися частями (особенно если я использую сценарий оболочки для создания и управления новыми схемами PostgreSQL).
спасибо, и я надеюсь, что не слишком долго!
3 ответов
Обновление 5 Декабря 2011
благодаря Брэду Робертсону и его команде, есть квартиры. Это очень полезно и делает много тяжелой работы.
однако, если вы будете возиться со схемами, я настоятельно рекомендую знать, как это на самом деле работает. Ознакомьтесь с прохождение игры Jerod Santo's, так что вы будете знать, что квартира драгоценный камень более или менее делает.
Обновление 20 Авг, 2011 11: 23 GMT+8
кто-то создал блоге и пусть гуляет весь этот процесс довольно хорошо.
обновление 11 мая 2010 11: 26 GMT+8
С прошлой ночи я смог получить метод для работы, который создает новую схему и загружает схему.РБ в этом. Не уверен, что то, что я делаю, правильно (пока работает нормально), но это, по крайней мере, шаг ближе. Если есть лучший способ, пожалуйста, дайте мне знать.
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 пытается найти существующие имена таблиц при загрузке схемы.rb и поскольку вы установили search_path только для новой схемы,это не удается. Это, конечно, предполагает, что у вас все еще есть открытая схема в вашей базе данных.
надеюсь, что это поможет.
есть ли gem / плагин, который уже имеет эти вещи?
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
также он заботится о правильном сбрасывании схем в схему.файл rb.