【问题标题】:Add a default value to a column through a migration通过迁移为列添加默认值
【发布时间】:2011-10-29 05:47:58
【问题描述】:

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

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

【问题讨论】:

    标签: ruby-on-rails ruby migration


    【解决方案1】:

    这是你可以做的:

    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 是一个传奇的分数。
    • 什么菜鸟的错误... ;-)
    【解决方案2】:

    对于 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 — 但它也不起作用。
    • 不能使用那个回滚?
    • 通常是这样,对于几乎所有“更改”子句,因为所有先前的状态通常都是显式的,例如列的存在、它的类型等。更改可以回滚,如图所示当且仅当先前存在有效的显式默认值时。由于默认值未定义很常见,因此您可能会遇到问题。
    【解决方案3】:
    change_column_default :employees, :foreign, false
    

    【讨论】:

    • @DenisLins 我同意你的看法,所以我做了一些研究以找出它可能不支持的原因,结果表明特定的数据库适配器可能不支持它,因为它已实现在那个级别。在抽象模型中实现之前,接受的答案仍然是最安全的选择。 apidock.com/rails/ActiveRecord/ConnectionAdapters/…
    • 除此之外,如果您希望它是可逆的,您需要指定 from:to: :)
    • 使用 fromto 被添加到 Rails 5+ 的这个提交中:github.com/rails/rails/pull/20018/files
    【解决方案4】:

    **Rails 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 =&gt; false, :default =&gt; false
    【解决方案5】:

    使用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
    

    【讨论】:

      【解决方案6】:

      你应该这样做:

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

      但某些数据库,如 PostgreSQL,不会更新之前创建的行的字段,因此请确保在迁移时也手动更新字段。

      【讨论】:

      • 如果您需要可逆迁移,请将其放在 up 块中,而不是 change 块中。您可以将 down 块留空。它不会将表恢复到原始状态,但可以回滚迁移。
      • 这会保持数据完整吗?
      • 在PostgreSQL上,是的,我不知道在其他数据库上会发生什么。
      • 您说“确保在迁移时手动更新字段”是什么意思?如何做到这一点?
      • 我在 PostgreSQL 上试了一下,它更新了之前创建的字段。
      【解决方案7】:

      执行:

      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

      运行:

      rake db:迁移

      【讨论】:

      • 现在默认值 1 不完全是布尔值;)此外,此示例 添加 一个新列,而不是更改现有列,这是 OP 想要的实现
      • @radiospiel 实际上,1 也是一个布尔值 :)
      • 您还需要在外键表中创建一条 ID 为 1 的记录才能正常工作,以避免出现 Key is not present in table error
      猜你喜欢
      • 1970-01-01
      • 2016-01-07
      • 1970-01-01
      • 2016-09-08
      • 2019-12-31
      • 1970-01-01
      • 1970-01-01
      • 2021-12-10
      • 1970-01-01
      相关资源
      最近更新 更多