Rails迁移:仅用于架构更改或更新数据?

我是初级Rails开发人员,在工作中我们面临以下问题:

只需为一条记录更新列的值。 我们所做的是创建这样的迁移:

class DisableAccessForUser < ActiveRecord::Migration def change User.where(name: "User").first.update_column(:access, false) end end 

迁移仅适用于架构更改吗?

您还建议其他什么解决方案?

PS:我只能用代码更改它。 无法访问控制台。

简短版本是,因为迁移仅用于架构更改,所以您不希望使用它们来更改数据库中的实际数据。

主要问题是,如果使用rake db:schema:loadrake db:reset加载数据库结构,则其他开发人员可能会忽略您的数据操作迁移。 两者schema.rb使用schema.rb文件加载最新版本的结构,并且不接触迁移。

正如Nikita Singh在评论中指出的那样,我也会说改变行数据的最佳方法是实现一个简单的rake任务,可以根据需要运行,与迁移结构无关。 或者,对于第一次安装, seed.rb文件非常适合加载初始系统数据。

希望漫无边际的帮助。

更新

在一些“官方”来源中找到了一些文档:

  • Rails迁移指南 – 在迁移中使用模型 。 本节介绍了迁移文件中的数据操作可能导致其他开发人员出现问题的方案。
  • Rails迁移指南 – 迁移和种子数据 。 与上面相同的文档并没有真正解释为什么在迁移中放置种子或数据操作是不好的,只是说将所有这些都放在seed.rd文件中。
  • 这个答案 。 这个人基本上说的是我上面写的相同内容,除了它们提供了一本引用Agile Web Development with Rails(第3版)的书 ,部分由Rails的创建者David Heinemeier Hansson撰写。 我不会复制引用,因为您可以在该post中阅读它,但我相信它可以让您更好地了解为什么迁移中的种子或数据操作可能被视为不良做法。

迁移适用于架构更改。 但是当你从事许多合作项目时,比如每天从很多开发人员那里提取代码。

您可能会错过一些迁移(值更新迁移。架构更改没有问题)因为迁移取决于时间戳。

所以我们要做的是在单个命名空间中创建一个rake任务来更新一些表值(小心它不会覆盖)

每当我们从Git更新代码时,都会调用NameSpace中的所有rake任务。

迁移只是一种结构化方式,可以对模式和数据进行数据库更改。 在我看来,有些情况下使用迁移进行数据更改是合法的。

例如:

  1. 如果您持有的数据在数据库中大部分是不变的,但每年都会更改,那么每年进行一次迁移就可以更新了。 例如,如果您列出足球联赛中的球队,那么迁移将是每年更新当前球队的好方法。
  2. 如果要批量更改大表的属性。 例如,如果您的用户中有一个slug列,并且名称“some user”将被转换为slug“some_user”,现在您想将其更改为“some.user”。 这是我对迁移所做的事情。

话虽如此,我不会使用迁移来更改单个用户属性。 如果这是偶尔发生的事情,您应该制作一个仪表板,以便将来编辑这些数据。 否则,佣金任务可能是一个不错的选择。

在迁移中使用类进行数据更改是危险的,因为它不是未来的证据。 对类的更改很容易在将来中断迁移。

例如,假设您要向用户(sample_group)添加一个新列,并在对象加载(例如after_initialize)上执行的Rails生命周期回调中访问该列。 这将打破这种迁移。 如果你没有在保存时跳过回调和validation(通过使用update_column),那么还有更多方法可以打破这种迁移。

当我想在迁移中进行数据更改时,我通常会回退到SQL。 可以使用execute()方法在迁移中执行任何SQL语句。 要使用的确切SQL取决于正在使用的数据库,但您应该能够提出适当的数据库查询。 例如在MySQL中我相信以下内容应该有效:

  execute("UPDATE users SET access = 0 WHERE id IN (select id from users order by id limit 1);") 

这是未来的证据。

如果我没记错的话,更改特定记录可能会有效,但我不确定。

在任何情况下,这都不是一个好习惯,迁移应该只是用户的架构更改。 要更新一条记录,我会使用控制台。 只需在终端输入“rails console”并输入代码即可更改属性。

如果您正确执行,在正确的情况下使用迁移迁移数据库中的数据没有任何问题。

迁移中应该避免两个相关的事情(正如许多人提到的那样),这两者都不会妨碍迁移数据:

  1. 在迁移中使用模型是不安全的。 User模型中的代码可能会更改,当发生这种情况时,没有人会更新您的迁移,因此如果某个同事休假3个月,请回来,并尝试运行她去世时发生的所有迁移,但有人在同一时间重命名了User模型,你的迁移将被打破,并阻止她赶上。 这只是意味着您必须使用SQL,或者(如果您决定保持甚至与迁移实现无关)在您的迁移文件中直接包含ActiveRecord模型的独立副本(嵌套在迁移类下)。

  2. 对种子数据使用迁移也没有意义,特别是当有人第一次设置应用程序时,用于填充新数据库的数据,以便应用程序运行(或将具有人们期望在应用程序的全新实例中获得数据。 您无法使用迁移,因为您在首次设置数据库时未运行迁移,而是运行db:schema:load 。 因此,维护种子数据的特殊文件: seeds.rb 。 这只是意味着如果你确实需要在迁移中添加数据(为了让生产和每个人的dev数据加速),并且它有资格作为种子数据(运行应用程序所必需的),你需要将它添加到seeds.rb也是!

但是,这些都不意味着您不应使用迁移迁移现有数据库中的数据。 这就是它们的用途。 你应该使用它们!