2

Я создаю приложение Rails 3.2 в старой базе данных, которая также имеет некоторые сломанные записи в разных таблицах. Одна из проблем, которая дает большую головную боль, заключается в том, что она включает недопустимые даты.Как изящно обрабатывать «Mysql2 :: Ошибка: Недействительная дата» в ActiveRecord?

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

Как приложение наследия PHP и это приложение новый Rails должен работать параллельно в течение нескольких недель до нескольких месяцев, мы не можем просто разовые исправить даты (Update: только для уточнения, это означает, что они работают на одна и та же база данных одновременно). Мне нужен способ автоматизировать это, возможно, с задачей миграции или грабли (я бы пошел за последним).

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

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

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

Путь миграции использует MySQL и три производственные среды (стабильная с активной базой данных , постановка с той же базой данных и песочница с клонированием базы данных каждую ночь). Мы решили не делать одноразовое сопоставление/миграцию данных, потому что мы не можем заменить полное устаревшее приложение за один шаг (он состоит из CMS с около 50000 статьями, сотнями тем, огромной файловой базой с изображениями и загрузками, поддерживая около 10 веб-сайтов , около 12 лет данных и работы, беспорядочный PHP-код из разных навыков программирования, дублированный код с разных этапов миграции, вытягивание содержимого RSS с сайтов-партнеров для смешивания статей/сообщений оттуда в графиках статей в наших темах нашего приложения и много интересного ...

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

У нас уже есть исправления, которые изящно обрабатывают разбитые зависимости моделей в role_to и has_many. Интеграция Paperclip была разработана для работы со всеми фантастическими сопоставлениями имен файлов. И драгоценный камень airbrake сообщает о всех сбоях приложений в нашей установке redmine, поэтому мы получаем краткий обзор всех левых причуд.

Унаследованные приложения уже были изменены для работы с последней версией MySQL и были перенесены на текущий сервер базы данных MySQL.

ответ

-1

Я считаю, что это решит вашу проблему Date.parse()

например Date.parse (Foo.created_at)

+0

Нет, на самом деле. Article.find (article_with_broken_date) выдает исключение, поэтому нет возможности исправить дату и сохранить запись снова. – hurikhan77

0

Создайте задачу импорта данных, которая делает все необходимые вам преобразования и исправления (включая синтаксический анализ и исправление данных) и запускает их каждый раз, когда вы получаете новое обновление из устаревшего приложения. Задача может использовать методы raw SQL (look-up "execute" и "exec_query"), она не должна работать с моделями. Это будет ваш волшебный «драгоценный камень», который вы искали. Очевидно, что у вас не может быть одного инструмента для всех, так как каждый случай сломанных данных уникален. Но просто не создавайте kludges в своей новой базе кода.

+0

Не уверен, понял ли я ваш рабочий процесс. Я не хочу импортировать данные. Унаследованное приложение и приложение Rails ДОЛЖНЫ использовать одну и ту же базу данных одновременно, потому что они работают параллельно, и мы постепенно делаем переход от старого к современному. Работа с «execute» и «exec_query», вероятно, сработает - но, на мой взгляд, именно это и есть kludge. Я должен использовать свои модели для доступа к сломанным данным и позволить ему исправить себя логикой, реализованной в модели. – hurikhan77

+0

Непонятно из вашего исходного сообщения, что оба приложения должны использовать одну и ту же базу данных. Или я что-то не понял. Если это так, то мое решение, по-видимому, не сработает для вас. Но я категорически возражаю против того, что модели «исправляют сломанные данные по логике, реализованной в них». Логика, которую должна содержать ваша модель, должна быть о бизнес-логике, а не о некоторых хаках и обходных решениях для разбитых данных. Потому что эти kludges будут накапливаться, загрязнять вашу бизнес-логику и в конечном итоге сделать код трудно понять. Я предлагаю вам не идти так :-) –

+0

Собственно, оно содержится в исходном сообщении: «Поскольку устаревшее приложение PHP и это новое приложение Rails необходимо запускать параллельно в течение нескольких недель или месяцев, мы не можем просто один раз исправить даты », но я добавил, что это становится более ясным. Логика в моих моделях разработана, чтобы быть изящной с ошибками из старой БД (мы вполне можем угадать с предположениями в коде, какая информация отсутствует и вставить ее на лету), то же самое касается дат (на самом деле такая дата, как offline_at 0000-00-00 16:30 означает, что он отключается в тот же день, что и состояния on-line, старый код PHP обрабатывает такие случаи в коде). – hurikhan77

2

У меня была та же проблема. Решение было сказать mysql2 не выполнить отливку, например:

client.query(sql, cast: false).each do |row| 
    row['some_date'] = Date.parse(row['some_date']) rescue(nil) 
end 

См mysql2 documentation подробную информацию о том, как построить объект клиента. Если необходимо, установите конфигурацию db через рельсы через ActiveRecord::Base.configurations.

+1

Выглядит громоздко, но многообещающе ... – hurikhan77

+0

@ hurikhan77 Он решает проблему, сообщая mysql2, чтобы не приписывать дату, что позволяет нам изящно выручить и установить неверную дату на нуль. Как это громоздко? Пожалуйста, отметьте это как правильное, если оно решит вашу проблему, как и для меня. – Zubin

+0

Я помечаю его как решение, как только вернусь к проекту, чтобы проверить его.BTW, «громоздкий» не был отрицательным, пожалуйста, прочитайте как «сложный по сравнению с использованием собственного AR». В частности, я бы не хотел писать команды SQL. Надеюсь, что существует способ остановить приведение типов в AR. – hurikhan77

0

Похож на: Rails: How to handle existing invalid dates in database?, а также без правильного ответа, поэтому отправлю решение ниже.

Я думаю, что самое простое решение, которое работало для меня было установить в database.yml файл записи бросание: ложные, например, для разработки Раздел

development 
    <<: *default 
    adapter: mysql2  
    (... some other settings ...) 
    cast: false