ChatGPT解决这个技术问题 Extra ChatGPT

通过迁移为列添加默认值

如何通过迁移向已存在的列添加默认值?

我可以找到的所有文档都向您展示了如果该列尚不存在但在这种情况下存在的情况下如何执行此操作。


M
Maurício Linhares

这是你应该如何做的:

change_column :users, :admin, :boolean, :default => false

但是一些数据库,比如 PostgreSQL,不会更新之前创建的行的字段,所以请确保在迁移时手动更新字段。


如果您需要可逆迁移,请将其放在 up 块而不是 change 块中。您可以将 down 块留空。它不会将表恢复到原始状态,但可以回滚迁移。
这会保持数据完整吗?
在 PostgreSQL 上,是的,我不知道在其他数据库上会发生什么。
我在 PostgreSQL 上尝试过,它更新了以前创建的字段。
@AboozarRajabi 我刚刚在 PostgreSQL 上尝试过它并没有更新以前创建的字段。
S
Soviut
change_column_default :employees, :foreign, false

@DenisLins我同意你的看法,所以我做了一些研究来弄清楚为什么它可能不支持,结果证明特定数据库适配器可能不支持它,因为它是在那个级别实现的。在抽象模型中实现之前,接受的答案仍然是最安全的选择。 apidock.com/rails/ActiveRecord/ConnectionAdapters/…
除此之外,如果您希望它是可逆的,则需要指定 from:to: :)
在此提交中,Rails 5+ 中添加了使用 fromtogithub.com/rails/rails/pull/20018/files
d
davegson

对于 Rails 4+,请使用 change_column_default

def change
  change_column_default :table, :column, value
end

这非常棒,特别是如果您有一个正在添加列并为现有记录设置默认值的迁移。例如:def change ` add_column :foos, :name, default: "something for existing values"` ` change_column_default :foos, :name, default: ""` end
这种迁移有一个奇怪的行为。在您的示例中,这是不可逆转的。 edgeguides.rubyonrails.org/active_record_migrations.html 建议以这种方式使用它:change_column_default :products, :approved, from: true, to: false — 但它也不起作用。
不能使用它回滚吗?
通常是的,对于几乎所有“更改”子句,因为所有先前的状态通常都是显式的,例如列的存在、它的类型等。当且仅当存在以前有效的显式默认值。由于默认值未定义很常见,因此您可能会遇到问题。
b
bfcoder

使用 def change 意味着您应该编写可逆的迁移。并且 change_column 是不可逆的。你可以上升,但你不能下降,因为 change_column 是不可逆的。

相反,虽然它可能是几行额外的行,但您应该使用 def updef down

因此,如果您有一列没有默认值,那么您应该这样做以添加默认值。

def up
  change_column :users, :admin, :boolean, default: false
end

def down
  change_column :users, :admin, :boolean, default: nil
end

或者,如果您想更改现有列的默认值。

def up
  change_column :users, :admin, :boolean, default: false
end

def down
  change_column :users, :admin, :boolean, default: true
end

J
James Bush

**导轨 4.X +**

从 Rails 4 开始,您无法生成迁移以将列添加到具有默认值的表中,以下步骤将新列添加到具有默认值 true 或 false 的现有表中。

1. 从命令行运行迁移以添加新列

$ rails generate migration add_columnname_to_tablename columnname:boolean

上面的命令将在您的表中添加一个新列。

2. 通过编辑创建的新迁移文件将新列值设置为 TRUE/FALSE。

class AddColumnnameToTablename < ActiveRecord::Migration
  def change
    add_column :table_name, :column_name, :boolean, default: false
  end
end

**3。要对您的应用程序数据库表进行更改,请在终端中运行以下命令**

$ rake db:migrate

这与 rails 3+ 或 2+ 有什么不同?
有谁知道这是否已合并到 Rails 5 中?
@sambecker 我知道回复您的评论可能有点晚了,但它在 Rails 6.0.3.1 上对我有用
@Mathyou 很高兴知道。在 Rails 6 中,新表可以包含具有默认值的列吗?还是仍然是单独的迁移?
@sambecker 您绝对可以在新表迁移中设置默认值。我在此类迁移中的一个专栏如下所示:t.boolean :is_active, :null => false, :default => false
a
axeltaglia

执行:

rails generate migration add_column_to_table column:boolean

它将生成此迁移:

class AddColumnToTable < ActiveRecord::Migration
  def change
    add_column :table, :column, :boolean
  end
end

设置默认值添加 :default => 1

add_column :table, :column, :boolean, :default => 1

跑:

耙分贝:迁移


现在默认值 1 不完全是布尔值;)此外,此示例添加了一个新列,而不是更改现有列,这是 OP 想要实现的
@radiospiel 实际上, 1 也是一个布尔值:)
您还需要在外键表中创建一条 ID 为 1 的记录,以使其正常工作,以避免 Key is not present in table error
r
rmcsharry

这是你可以做的:

class Profile < ActiveRecord::Base
  before_save :set_default_val

  def set_default_val
    self.send_updates = 'val' unless self.send_updates
  end
end

编辑:......但显然这是一个新秀错误!


最好将架构中的默认值设置为 before_save
多么糟糕的建议
同意,真的太可怕了
哎呀,您在模型级别而不是数据库级别上做某事会受到很多关注。 -38 是一个传奇的分数。
多么菜鸟的错误... ;-)