Миграция БД и обратные вызовы [JRuby 1.5.2 или Rails 2.2.3] - PullRequest
0 голосов
/ 13 января 2011

Фон
У нас есть скрипт миграции рельсов, как показано ниже:
...
...
0011_update_column1_for_internal_projects.rb
...
...
0022_create_audits.rb

Мы создали обратные вызовы after_create / update / delete для модели InternalProject, которая обновляет таблицу Audits для отслеживания события, которое произошло в модели.

Фрагмент кода
Скрипт переноса БД - 0011 - имеет self.up метод, определенный ниже:

def self.up  
    InternalProject.all.each do |project|
        project.column1 = project.column2
        project.save!
    end
end  

Побочный эффект
С помощью скрипта 0022 мы попали в ситуацию, когда скрипт 0011 не переносится, потому что у нас есть тестовые приборы для загрузки некоторых начальных данных для внутренних проектов.Теперь этот сбой, потому что при сохранении InternalProject срабатывает обратный вызов, и в этот момент состояние БД, поскольку 0022 не запускается, таблица Audit не существует, и поэтому мы получаем ошибку SQL с жалобой на то, что таблица не существует.

Мой вопрос
1. Как исправить скрипт переноса БД 0011, чтобы предотвратить вызовы обратных вызовов при сохранении InternalProject?Я хотел бы знать аккуратный способ сделать это.
2. У меня возникает вопрос, удаляется ли такой скрипт обновления.Это плохая идея?Должны ли мы иметь скрипты для манипулирования данными при переносе БД?
3. Если в скриптах переноса БД есть скрипты манипулирования данными , можем ли мы что-то с этим сделать?

Ответы [ 2 ]

1 голос
/ 13 января 2011

Попробуйте добавить это в вашу миграцию 0011

  def self.up  
    InternalProject.all.each do |project|
      project.column1 = project.column2
      project.save(:validate => false) # don't run validations! (notice we're calling `save` and NOT `save!`)
    end
  end
  1. См. Выше

  2. Это нормально - манипулировать данными в ваших миграциях, чтобы они соответствовали эволюции схемы. Однако при развертывании вашего проекта в новой среде (например, при первом развертывании в рабочей среде) вы должны запустить rake db:create вместо миграции.

  3. Не уверен, что я понимаю ваш вопрос, но имеет смысл использовать манипулирование данными в процессе миграции (вместо отдельного скрипта). Держите то, что принадлежит вместе, вместе. Тем не менее, ничто не мешает вам иметь отдельный файл миграции для переноса данных.

0 голосов
/ 02 февраля 2011

Я закончил тем, что вставил ANSI-совместимый SQL-скрипт в блок кода, как показано ниже.Не могу придумать ни одного безотказного способа.

  def self.up
     InternalProject.all.each do |internal_project|
          InternalProject.connection.execute("UPDATE projects SET sales_leader='#{internal_project.owner_name}' where type='InternalProject' and owner_id=#{internal_project.owner_id}")
     end
  end   

Если кто-нибудь придумает / найдет лучшее решение, чем это, пожалуйста, оставьте свою мысль / опыт.

...