Подтвердить что ты не робот

Создание приложения с несколькими арендаторами с использованием схем PostgreSQL и Rails

Материал, который я уже выяснил

Я изучаю, как создать многопользовательское приложение в Rails, которое обслуживает данные из разных схем на основе того, какой домен или поддомен используется для просмотра приложения.

У меня уже есть несколько вопросов:

Эти три момента охватывают многие общие вещи, которые мне нужно знать. Однако на следующих шагах у меня, похоже, много способов реализации вещей. Я надеюсь, что там будет лучший, более простой способ.

Наконец, на мой вопрос

Когда новый пользователь подписывается, я могу легко создать схему. Тем не менее, , какой был бы самый лучший и простой способ загрузить структуру, которая уже есть в остальных схемах? Вот несколько вопросов/сценариев, которые могут дать вам лучшую идею.

  • Должен ли я передать его в оболочку script, которая сбрасывает общедоступную схему во временную и импортирует ее обратно в мою основную базу данных (в значительной степени, как говорит Гай Наор в своем видео )? Здесь краткое резюме / script, которое я получил из полезных #postgres на freenode. Хотя это, вероятно, будет работать, мне придется делать много вещей за пределами Rails, что делает меня немного неудобным.., что также приводит меня к следующему вопросу.
  • Есть ли способ сделать это прямо из Ruby on Rails? Как и создание схемы PostgreSQL, просто загрузите схему базы данных Rails (schema.rb - я знаю, это запутанно) в эту схему PostgreSQL.
  • Есть ли gem/plugin, у которого уже есть эти вещи? Методы типа "create_pg_schema_and_load_rails_schema (the_new_schema_name)". Если нет, я, вероятно, буду работать над тем, чтобы сделать один, но я сомневаюсь, насколько хорошо он будет тестироваться со всеми движущимися частями (особенно, если я в конечном итоге использую оболочку script для создания и управления новыми схемами PostgreSQL).

Спасибо, и я надеюсь, что это было не слишком долго!

4b9b3361

Ответ 1

Обновление от 5 декабря 2011 г.

Благодаря Брэду Робертсону и его команде, Квартира драгоценный камень. Это очень полезно и делает много тяжелой работы.

Однако, если вы будете заниматься схемами, я настоятельно рекомендую знать, как это работает. Ознакомьтесь с прохождение Jerod Santo, так что вы узнаете, что делает этот аксессуар более или менее.

Обновление 20 августа 2011 г. 11:23 GMT + 8

Кто-то создал сообщение в блоге и довольно хорошо проходит весь этот процесс.

Обновление 11 мая 2010 г. 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 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 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

Ответ 2

Измените строку 38 на:

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

Я предполагаю, что postgres пытается найти существующие имена таблиц при загрузке schema.rb, и поскольку вы указали, что путь search_path содержит только новую схему, он терпит неудачу. Это, конечно, предполагает, что у вас все еще есть общедоступная схема в вашей базе данных.

Надеюсь, что это поможет.

Ответ 3

Есть ли 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

Также он заботится о правильном сбросе схем в файл schema.rb.