题 清除旧的Rails迁移文件是个好主意吗?


我已经运行了大型Rails应用程序超过2年,而且我的ActiveRecord迁移文件夹日复一日地发展到150多个文件。

存在非常旧的模型,在应用程序中不再可用,仍在迁移中引用。我想删除它们。

你怎么看?您是否经常从代码库中清除旧迁移?


27
2017-11-22 18:10


起源




答案:


它们相对较小,所以我会选择保留它们,仅供记录。

你应该编写你的迁移而不引用模型或应用程序的其他部分,因为它们会回到你的困扰;)

看看这些指南:

http://guides.rubyonrails.org/migrations.html#using-models-in-your-migrations


4
2017-11-23 18:26



我尝试在没有模型引用的情况下编写迁移一段时间,结果证明这是一个非常令人头痛的问题,特别是如果我试图添加新的数据库约束。我必须编写一个rake任务来首先清理数据,然后再推送一个迁移来添加约束,因为当有尚未运行的迁移时,你无法运行rake任务。将这一切放在迁移中要容易得多。额外奖励是隐含的交易,因此失败回滚。 - lobati
@lobati:我没有在迁移中使用模型与新数据库约束之间建立联系。我在整个地方使用真正的FK,CHECK,触发器......并在迁移中使用SQL管理它们,我的迁移中不需要任何模型。 - mu is too short
@muistooshort我发现在添加约束或移动数据时能够依赖模型级验证和查询便利性是很好的。例如,当我们添加FK约束时,我们有时会发现相关记录丢失,因此我们可能希望以某种方式有条件地重构它或者只是销毁它。其中大部分内容可能都是用原始SQL处理的,但我也发现,如果我在查询中使用额外的抽象层,那将是很好的。 - lobati
@lobati:我倾向于将数据库视为一个完全独立的应用程序,其API是SQL。这使得数据库对其一致性负责,并且所有模型验证都是备份(为了一致性和完整性),这使得向外部世界传递错误更容易一些。导致一些重复工作,但这实际上是一个功能。就脂肪指法而言,这就是你将约束放在数据库中的原因。破碎的代码是暂时的,破碎的数据是永久的。在任何情况下,我们可能都在谈论同样的事情。 - mu is too short
@muistooshort我想我同意所有这些。不幸的是,我对这些事情并不总是那么明智,而且我最终会将我的旧工作与我不断改变的理念,或者其他人已有的代码库和数据库保持同步。旁注:如果Rails能够从数据库约束中推断出验证,那么它可能会很方便。 - lobati


一旦我点击主要网站发布,我就会将迁移推广到一个并重新开始。一旦迁移版本数量达到75左右,我就会觉得很脏。


14
2017-11-22 18:17



你怎么把它们合二为一?手动? - Alison R.
@AlisonR。 - 当你提问时,不确定这是否属实,但在Rails 3中你可以复制 schema.rb。 - Nathan Long
为什么要把它们合二为一? schema.rb 无论如何应该是数据库的规范来源。你可以跑 rake db:schema:load 获取最新的架构,然后 rake db:migrate 获取最新的迁移。 - lobati


Rails 4 Way 第177页: 塞巴斯蒂安说......

一个鲜为人知的事实是,您可以删除旧的迁移文件(同时   仍然保持较新的)保持 db/migrate 文件夹到   易于管理的尺寸。您可以将旧迁移移动到    db/archived_migrations 文件夹或类似的东西。一旦你修剪   您的迁移文件夹的大小,使用 rake db:reset 任务到   (重新)从中创建数据库 db/schema.rb 并将种子装入   你现在的环境。


13
2017-10-07 17:00





为什么?除非磁盘空间存在某种问题,否则我认为没有理由删除它们。我想如果你绝对肯定你永远不会再回滚任何东西,那么你可以。但是,似乎节省几KB的磁盘空间来做这件事是不值得的。此外,如果您只想删除引用旧模型的迁移,则必须手动查看它们,以确保不删除应用中仍然使用的任何内容。对我来说,很多努力都没什么好处。


3
2017-11-22 18:15



主要原因是因为模型已被完全删除,因此/ models文件夹中没有指向表的模型定义。 - Simone Carletti
让迁移创建然后删除表似乎效率低下,除非进行完整的数据库构建是一个时间关键的过程,否则没有理由搞乱它们。他们喜欢闲逛。 - Jeremy
如果你真的进行了很多迁移,它确实很有意义,我们已经有大约1000个并且现在需要花费大量时间来运行“rake db:migrate” - 即使有一个迁移要运行,因为(我想),Rails首先将所有这些加载(解析)到内存中。我们还没有清除过我们的迁移,但现在我在这里 - 我肯定会考虑。 - Alex Kovshovik
一个原因:我刚刚从应用程序中删除了Devise(转向单点登录)。它的原始迁移使用的东西 t.recoverable,没有宝石就不存在,所以我根本不能再运行那个迁移了。至少我不得不发表评论。 - Nathan Long


我个人喜欢在迁移文件中保持整洁。我认为,一旦您将所有更改推送到prod,您应该真正考虑归档迁移。我遇到的唯一困难是,当特拉维斯运行时,它运行一个 db:migrate,所以这些是我使用的步骤:

  1. 移动历史迁移 /db/migrate/ 至 /db/archive/release-x.y/

  2. 使用上次运行迁移中的版本号手动创建新的迁移文件 /db/archive/release-x.y 目录并将描述更改为类似的内容 from_previous_version。使用旧的版本号意味着它不会在您的prod机器上运行并且搞乱。

  3. 复制 schema.rb 里面的内容 ActiveRecord::Schema.define(version: 20141010044951) do 部分并粘贴到 change 你的方法 from_previous_version 更新日志

  4. 检查所有内容,罗伯特应该是你父母的兄弟。

唯一的另一个考虑因素是,如果您的迁移创建任何数据(我的测试场景包含所有自己的数据,所以我没有这个问题)


3
2017-10-14 01:02



特拉维斯是谁,谁是罗伯特? - wbeange
特拉维斯: travis-ci.org  和你的叔叔一样: en.wikipedia.org/wiki/Bob%27s_your_uncle - FuzzyJulz


我偶尔会清除已经在生产中应用的所有迁移,我至少看到两个原因:

  1. 更易于管理的文件夹。如果添加了一些新的迁移,则更容易发现。
  2. 更清晰的文本搜索结果(项目中的全局文本搜索不会导致大量无用的匹配,因为旧的迁移,比如3年前有人创建了一些列)。

3
2017-10-19 21:43





看到 http://edgeguides.rubyonrails.org/active_record_migrations.html#schema-dumping-and-you

迁移是  数据库的表示:structure.sql或schema.rb是。迁移也是  设置/初始化数据的好地方。 db/seeds 或者rake任务对于那种任务更好。

那么什么是迁移?在我看来,它们是如何更改数据库模式的指令 - 向前或向后(通过回滚)。除非出现问题,否则只能在以下情况下运行:

  1. 在我的本地开发机器上,作为一种测试迁移本身并编写模式/结构文件的方法。
  2. 在同事开发人员机器上,作为一种在不丢弃数据库的情况下更改架构的方法。
  3. 在生产计算机上作为一种在不删除数据库的情况下更改架构的方法。

一旦运行他们 应该 无关紧要。当然会发生错误,因此您肯定希望在需要回滚的情况下保持几个月的迁移。

CI环境没有 曾经 需要运行迁移。它会降低CI环境的速度并且容易出错(就像Rails指南所说的那样)。由于您的测试环境只有短暂的数据,因此您应该使用 rake db:setup,它将从schema.rb / structure.sql加载并完全忽略您的迁移文件。

如果您正在使用源代码管理,那么保持旧迁移没有任何好处;它们是源历史的一部分。将它们放在存档文件夹中可能是有意义的,如果这是你的咖啡。

尽管如此,我强烈认为清除旧的迁移是有意义的,原因如下:

  • 它们可能包含很旧的代码,它将不再运行(就像删除模型一样)。这为想要运行的其他开发人员创建了一个陷阱 rake db:migrate
  • 他们会放慢脚步 grep类似的任务,并且在某个年龄段之后无关紧要。

为什么他们无关紧要?再次出于两个原因:历史记录存储在源代码管理中,实际的数据库结构存储在structure.sql / schema.rb中。我的经验法则是,大约12个月以上的迁移完全无关紧要。我删除它们。如果有一些原因我想要回滚早于此的迁移,我确信数据库在那段时间内已经发生了足够的变化,需要编写新的迁移来执行该任务。

所以 怎么样 你摆脱了迁移?这些是我遵循的步骤:

  1. 删除迁移文件
  2. 编写rake任务以删除数据库的schema_migrations表中的相应行。
  3. rake db:migrate 重新生成structure.sql / schema.rb。
  4. 验证structure.sql / schema.rb中唯一更改的内容是删除与您删除的每个迁移相对应的行。
  5. 部署,然后在生产时从步骤2运行rake任务。
  6. 确保其他开发人员在其计算机上运行步骤2中的rake任务。

第二项是保持模式/结构准确的必要条件,这也是唯一真正重要的事情。


2
2018-06-14 23:14





是。我想如果你已经从数据库中完全删除了任何模型和相关表,那么值得将它放在迁移中。如果迁移中的模型引用不依赖于任何其他内容,则可以将其删除。虽然迁移永远不会再运行,因为它已经运行,即使您没有从现有迁移中删除它,但每当您将数据库迁移时,都会导致问题。

因此,从迁移中删除该引用会更好。在重大发布到实时数据库之前,重构/最小化迁移到一个或两个文件。


0
2017-11-22 19:12





一旦你感到舒服就可以删除旧的迁移,这是不错的。迁移的目的是拥有一个用于制作和回滚数据库更改的工具。一旦做出改变并在生产中进行了几个月,你很可能不再需要它们。我发现经过一段时间后,它们只会让你的回购,搜索和文件导航变得混乱。

有些人会从头开始运行迁移以重新加载他们的开发数据库,​​但这并不是他们的目的。您可以使用 rake db:schema:load 加载最新的架构,和 rake db:seed 用种子数据填充它。 rake db:reset 为你做这两件事。如果您有无法转储的数据库扩展 schema.rb 那你就可以用了 ActiveRecord的sql架构格式 并运行 rake db:structure:load 代替。


0
2018-06-11 19:35