ruby-on-rails - 如何优雅地处理ActiveRecord中的 "Mysql2::Error: Invalid date"?

标签 ruby-on-rails activerecord error-handling database-migration legacy-database

我正在旧数据库上构建 Rails 3.2 应用程序,该数据库在不同的表中也有一些损坏的记录。最令人头疼的问题之一是它包含无效日期。

我已经设置了一个沙箱,我手动修复了一次以使我的代码正常工作。现在是部署的时候了。因此,沙箱每天晚上都会重置并从实时数据库复制,重建 ferret 索引并重新应用迁移。我们将经常部署到沙箱,以便在部署到实时设置之前获得最后的修复。

由于旧版 PHP 应用程序和新的 Rails 应用程序需要并行运行几周到几个月,因此我们不能简单地一次性修复日期(更新:仅供澄清,即意味着它们同时在同一个数据库上运行)。我需要一种方法来自动执行此操作,也许可以通过迁移或 rake 任务(我会选择后者)。

但问题是:ActiveRecord 在加载此类记录时会卡住,因此我无法通过 ruby​​ 代码中的一些硬编码假设来调查记录并修复日期。

第二个问题是遗留数据库存在不一致的情况,因为 PHP 代码没有使用事务,并且某些代码路径已损坏,留下了孤立的和损坏的表约束。我将在它们发生时处理它们,其中大多数已经在模型中得到处理。第一个问题与日期有关。

您通常会如何解决这个问题?也许甚至有一些神奇的 gem ,它支持通过拦截异常并运行一些尝试修复代码来迁移具有损坏记录的遗留数据库......

迁移路径使用 MySQL 和三个生产环境(使用实时数据库稳定、使用相同数据库进行暂存、以及每晚重置数据库克隆的沙箱)。我们决定不进行一次性数据映射/迁移,因为我们无法一步替换完整的遗留应用程序(它由一个包含大约 50000 篇文章、数百个主题、包含图像和下载的庞大文件数据库、支持大约 10 个网站的 CMS 组成) ,大约 12 年的数据和工作,来自不同编程技能的困惑 PHP 代码,来自不同迁移阶段的重复代码,从合作伙伴站点提取 RSS 内容,将其中的文章/帖子混合到我们自己应用程序主题的文章时间线中,以及还有更多有趣的东西...

第一步是迁移后端应用程序以获得一致的管理和发布界面。遗留前端应用程序仍然需要写入数据库(访问者创建的评论和其他内容)。因此修复数据库的过程必须能够在无人值守的情况下定期运行。

我们已经进行了修复,可以优雅地处理belongs_to和has_many中损坏的模型依赖关系。 Paperclip 集成旨在与所有发明的奇妙文件名映射一起使用。 Airbrake gem 会将所有应用程序崩溃报告给我们的 redmine 安装,以便我们快速了解所有剩余的怪癖。

旧应用程序已经过修改,可以与最新的 MySQL 版本一起使用,并且已迁移到当前的 MySQL 数据库服务器。

最佳答案

我也遇到了同样的问题。解决方案是告诉 mysql2 不要执行转换,如下所示:

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

参见mysql2 documentation有关如何构建客户端对象的详细信息。如果需要,请通过 ActiveRecord::Base.configurations 访问 Rails 数据库配置。

关于ruby-on-rails - 如何优雅地处理ActiveRecord中的 "Mysql2::Error: Invalid date"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16389313/

相关文章:

ruby-on-rails - 需要向 rails find 添加条件

ruby-on-rails - Rails 4 添加位置 header

ruby-on-rails - Rails 2.3.11 为表单创建模型并使用 ActiveRecord 验证

user-interface - 错误消息应该有多详细?

ruby-on-rails - 无法在 Rails 中将电子邮件作为 URL 中的参数发送

ruby-on-rails - ruby rails : Running Tests

ruby-on-rails - 如何通过 has_many 关系创建指定类型的对象?

ruby-on-rails - Ruby on Rails 将表与数量连接起来

asp.net - 有关ASP.NET MVC 2中错误处理的新建议

ruby - else block 中的Ruby异常处理