我正在一个遗留数据库上构建一个Rails 3.2应用程序,该数据库在不同的表中也有一些坏记录。最令人头疼的问题之一是它包含无效日期。
我设置了一个沙箱,我手动修复了一次,让我的代码工作。现在是部署的时候了。出于这个原因,沙箱每晚都会重置并从实时数据库中复制,重建雪貂索引,并重新应用迁移。我们将经常部署到沙箱中,以便在部署到实时设置之前进行最后的修复。
由于传统的PHP应用程序和这个新的Rails应用程序需要并行运行几周到几个月,我们不能简单地一次性固定日期(Update:只是为了澄清,这意味着它们同时在同一个数据库上运行(。我需要一种自动化的方法,也许是通过迁移或rake任务(我会选择后者(。
但问题是:ActiveRecord在加载这样的记录时会阻塞,所以我无法通过ruby代码中的一些硬编码假设来调查记录并确定日期。
第二个问题是遗留数据库存在不一致性,因为PHP代码没有使用事务,一些代码路径被破坏,留下了孤立的和破坏的表约束。我将在它们发生时处理它们,其中大多数已经在模型中得到了处理。第一个问题是日期。
你通常会怎么解决这个问题?也许还有一些神奇的宝石,它通过拦截异常和运行一些修复代码来支持迁移有损坏记录的遗留数据库。。。
迁移路径使用MySQL和三个生产环境(使用实时数据库稳定,使用同一数据库暂存,以及每晚重置数据库克隆的沙箱(。我们决定不进行一次性数据映射/迁移,因为我们无法在一步中替换完整的遗留应用程序(它由一个CMS组成,包含大约50000篇文章,数百个主题,包含图像和下载的巨大文件数据库,支持大约10个网站,大约12年的数据和工作,来自不同编程技能的混乱PHP代码,来自不同迁移阶段的重复代码,从合作伙伴网站引入RSS内容,将文章/帖子混合到我们自己的应用程序中的文章时间表中。(关于的话题,还有很多有趣的东西。。。
第一步是迁移后端应用程序以获得一致的管理和发布界面。遗留的前端应用程序仍然需要写入数据库(由访问者创建的评论和其他内容(。因此,修复数据库的过程必须能够定期在无人值守的情况下运行。
我们已经修复了belongs_to和has_many中损坏的模型依赖关系。Paperclip集成已被设计用于处理所有发明的奇妙的文件名映射。airbrakegem向我们的redmine安装报告所有应用程序崩溃,因此我们可以快速了解所有遗留的怪癖。
遗留应用程序已经被修改为使用最新的MySQL版本,并已迁移到当前的MySQL数据库服务器。
我也遇到了同样的问题。解决方案是告诉mysql2不要执行铸造,如下所示:
client.query(sql, cast: false).each do |row|
row['some_date'] = Date.parse(row['some_date']) rescue(nil)
end
有关如何构建客户端对象的详细信息,请参阅mysql2文档。如果需要,请通过ActiveRecord::Base.configurations
访问rails数据库配置。
创建一个数据导入rake任务,该任务可以完成所需的所有转换和修复(包括数据解析和修复(,并在每次从遗留应用程序获得新更新时运行它。该任务可以使用原始SQL(查找"execute"one_answers"exec_query"方法(,不必使用模型。这将是你一直在寻找的神奇"宝石"。显然,你不可能有一个一刀切的工具,因为每一个坏数据的情况都是独一无二的。但是,不要在新的代码库中创建拼凑的代码。
类似于:Rails:如何处理数据库中现有的无效日期?也没有正确的答案,所以我在下面转发我的解决方案。
我认为对我来说最简单的解决方案是在数据库中设置yml文件writecast:false,例如用于开发部分
development
<<: *default
adapter: mysql2
(... some other settings ...)
cast: false
我相信它会解决您的问题Date.parse()
例如Date.parse(foo.created_at(