环境
ruby 1.9.3p194(2012-04-20修订版35410)[x86_64-darwin10.8.0];轨道3.2.6;OSX 10.6.8
问题
- 即使在重置数据库(rakedb:reset)之后,迁移也会生成错误的表、字段和模式,其中包括表、字段、限制、索引等,这些都是早期迁移规范所反对的
背景
-
我在两个OSX 10.6.8系统之间来回移动了一个github协作项目在以前的某个时刻,迁移是通过在一个初始迁移中合并预期的表定义从头开始的(消除了以前许多迁移规范的大量混乱和费力的处理)
-
几个月来,修订后的迁移忠实地生成了表和模式。
-
在从可移植系统同步公共存储库后,将我们的项目拉到我的主要开发系统后,进一步的迁移将保留许多表和字段,这些表和字段实际上没有在任何现有迁移中定义,也不是由其他合作者的开发环境中的相同迁移生成的换句话说,许多不起作用/不推荐使用的字段和表以某种方式从规范中持久存在,这些规范早在我们修订的迁移中删除之前就已经存在了因此,即使在运行rakedb:reset之后,db:migrate也会在这个系统上生成错误的表和模式
-
据推测,以前的规定保留在开发环境中的某个地方,有必要以某种方式删除、修订或覆盖以前不再存在的定义,尽管如此,这些定义仍会在不希望的表和字段中沉淀
-
在纠正这一问题时,被迫撤销现有工作是非常不可取的。
问题
那么,重新生成符合我们在项目中保留的迁移规范的迁移、表和架构的正确有效的方法是什么
请参阅以下参考资料:
- http://guides.rubyonrails.org/migrations.html#schema-倾销和你
- rakedb:schema:负载与迁移
基本上,你可以运行
rake db:schema:load
要直接从schema.rb文件加载数据库模式,请注意在生产中执行此操作,因为这可能会删除生产数据
FIX
通过推导以下过程,我终于能够生成与我们的迁移规范一致的模式和表:
-
首先,我手动删除了模式的do和最终结束符之间的所有指令。rb,并且(无论是否重要)我进一步将版本重新定义为0:
ActiveRecord::Schema.define(:version => 0) do end
-
接下来,我运行rake-db:drop-db:create-db:reset(首先删除表,只是为了消除SQL引擎进程中工件可能持久存在的可能性)。
-
最后,在重新填充表之前,我运行了rake-db:migrate(无论出于何种原因,我的环境都拒绝在一条语句中使用前三个命令运行[我经常运行rake-db:drop-db:create-db:schema:load-db:fixtures:load来重建和重新填充表])。
注意事项
-
在试图诊断可能的促成因素时,项目搜索在除了我的错误模式之外的任何文件中都没有发现对不推荐使用的表或字段的引用因此,我推测由于某种原因(可能是处理错误?)错误的现有架构引用在进一步的过程中持续存在。
-
在任何情况下,在从我的本地schema.rb中删除所有指令后,重置和定期迁移成功地生成了一个模式,该模式确实对我们的迁移规范非常忠实,而之前的工作生成了错误地保留冗余表、字段等的模式,似乎从以前的(已失效的)本地模式中持久存在
-
因此,很有可能,如果rake-db:reset显然是从一个不起作用的模式生成表和模式,而该过程尚未根据现有的迁移规范重建,则这些结果(我现在已经重复复制了这些结果)表明db:reset中存在逻辑缺陷,这应该是本身清除先前的模式,因此,db:reset既不保留也不错误地依赖于前一个模式的规范。
-
为了那些在编写迁移时可能会无意中出现错误的人的安全,我还建议在重建合法的模式db:reset之前,先将现有的(已失效的)模式复制到一个有时间戳的备份中,通过可能必要地依赖前一个模式的记录,可以纠正有问题的迁移。