Как создать миграцию в подкаталоге с Rails? - PullRequest
3 голосов
/ 08 января 2011

Я пишу приложение модели SaaS.Моя база данных приложений состоит из двух логических частей:

  • таблиц приложений - таких как пользователь, роли ...
  • пользовательских таблиц (он может генерировать их на уровне пользовательского интерфейса), которые могут бытьотличается для каждого экземпляра приложения

Все таблицы создаются механизмом миграции rails.

Я хотел бы поместить пользовательские таблицы в другой каталог:

  • db / migrations - таблицы приложений
  • db / migrations / custom - таблицы, созданные пользователем

так что я могу сделать svn: ignore на db / migrations / custom, и когда я делаю обновления моего приложения на клиентских серверах, оно будет обновлять только миграции таблиц приложений.

Есть ли какие-либоспособ добиться этого в рельсах?

Ответы [ 5 ]

7 голосов
/ 09 января 2011

Задача rake db:migrate имеет жестко заданный путь к миграции. Но вы можете создать собственное задание для граблей. Например, создайте lib/tasks/custom_db_migrate.rake со следующим содержимым:

namespace :db do
  task :custom_migrate => :environment do
    ActiveRecord::Migration.verbose = ENV["VERBOSE"] ? ENV["VERBOSE"] == "true" : true
    ActiveRecord::Migrator.migrate("db/migrate/custom", ENV["VERSION"] ? ENV["VERSION"].to_i : nil)
    Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby
  end
end

Теперь вы можете запустить rake db:custom_migrate для запуска миграций, расположенных в db/migrate/custom. Но он не будет использовать миграции из пути по умолчанию.

Возможно, вы захотите прочитать исходный код для миграции ActiveRecord.

3 голосов
/ 05 апреля 2013

Если вы используете Sinatra и создаете свою собственную задачу rake, вы можете сделать следующее:

require './app'
require 'sinatra/activerecord/rake'

ActiveRecord::Migrator.migrations_paths = 'your/path/goes/here'

Когда вы запустите rake -T, вы получите пространство имен db:

rake db:create_migration  # create an ActiveRecord migration
rake db:migrate           # migrate the database (use version with VERSION=n)
rake db:rollback          # roll back the migration (use steps with STEP=n)
2 голосов
/ 09 января 2011

@ Спасибо Василию за ваш ответ. Прочитав его и пару вопросов от stackoverflow, я пришел к следующему решению:

Поскольку я пишу свой собственный генератор для создания пользовательских таблиц, я включил в него Rails :: Generators :: Migration, чтобы я мог переопределить метод next_migration_number следующим образом:

def self.next_migration_number(dirname)
 if ActiveRecord::Base.timestamped_migrations
   Time.now.utc.strftime("custom/%Y%m%d%H%M%S")
 else
   "custom/%.3d" % (current_migration_number(dirname) + 1)
 end
end

Теперь все миграции, созданные пользователем, создаются в каталоге db / migrations / custom.

Затем я написал обычную миграцию rails, которая выполняет все миграции из каталога db / migrations / custom:

class ExecuteCustomMigrations < ActiveRecord::Migration
   MIGRATIONS_PATH='db/migrate/custom'
   def self.up
     Dir["#{MIGRATIONS_PATH}/[0-9]*_*.rb"].
     sort.map{|filename|require filename}.flatten.
     each{|class_name| const_get(class_name).up}
   end

   def self.down
     Dir["#{MIGRATIONS_PATH}/[0-9]*_*.rb"].sort.reverse.
     map{|filename|require filename}.flatten.
     each{|class_name| const_get(class_name).down}
   end
end

После того, как пользователь создает пользовательскую таблицу, я вызываю эту миграцию с таким кодом:

Rake::Task["db:migrate:redo"].execute("VERSION=20110108213453")
0 голосов
/ 29 января 2019

Обновление для Rails 5/6;

Rails 5 рекомендует установить дополнительные пути миграции в вашем файле config/database.yml.Это очень просто, посмотрите этот пример;

development:
  migrations_paths:
  - "db/migrations"
  - "db/migrations/custom"

ActiveRecord::Migrator.migrations_path= будет устаревшим в Rails 6.

0 голосов
/ 02 января 2018

С помощью rails 4 мы видим, что каталоги миграции хранятся в массиве, к которому обращается "db / migrate"

Фрагмент кода из activerecord / lib / active_record /igration.rb

def migrations_paths
    @migrations_paths ||= ["db/migrate"]
    # just to not break things if someone uses: migrations_path = some_string
    Array(@migrations_paths) # Data stored in an array
end

Таким образом, мы можем добавить этот массив с помощью config в environment.rb, как пример

Rails.application.configure do
    config.paths["db/migrate"] << %Q{db/migrations}
    config.paths["db/migrate"] << %Q{db/migrations.custom}
end

Также я не смог найти это документированное, но дополнительные каталоги в db / migrate также ищутся и выполняются.

например, я помещаю группы миграций в каталоги выпуска

-db/migrate
    -3.0.0
       XXXXXcreate_user.rb
    -3.0.1
       XXXXXcreate_task.rb

Этот механизм также используется для добавления каталогов миграции движка Обсуждается здесь

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...