【问题标题】:Adding :default => true to boolean in existing Rails column将 :default => true 添加到现有 Rails 列中的布尔值
【发布时间】:2012-01-27 11:15:03
【问题描述】:

我在这里看到了一些关于向现有列添加默认布尔值的问题(即this one)。所以我尝试了change_column 的建议,但我一定做得不对。

我试过了:

$ change_column :profiles, :show_attribute, :boolean, :default => true

返回-bash: change_column: command not found

然后我跑了:

$ rails g change_column :profiles, :show_attribute, :boolean, :default => true

...和

$ rails change_column :profiles, :show_attribute, :boolean, :default => true

然后运行rake db:migrate,但:show_attribute 的值仍然是nil。在我上面提到的问题中,它在 PostgreSQL 中说您需要手动更新它。由于我使用的是 PostgreSQL,因此我在 create_profiles 迁移中添加了以下内容:

t.boolean :show_attribute, :default => true

谁能告诉我我在这里做错了什么?

【问题讨论】:

    标签: ruby-on-rails-3 migration


    【解决方案1】:

    change_columnActiveRecord::Migration的方法,所以不能在控制台这样调用。

    如果要为此列添加默认值,请创建一个新的迁移:

    rails g migration add_default_value_to_show_attribute

    然后在迁移中创建:

    # That's the more generic way to change a column
    def up
      change_column :profiles, :show_attribute, :boolean, default: true
    end
    
    def down
      change_column :profiles, :show_attribute, :boolean, default: nil
    end
    

    或者更具体的选项:

    def up
        change_column_default :profiles, :show_attribute, true
    end
    
    def down
        change_column_default :profiles, :show_attribute, nil
    end
    

    然后运行rake db:migrate

    它不会对已创建的记录进行任何更改。为此,您必须创建一个 rake task 或直接进入 rails console 并更新所有记录(我不建议在生产环境中这样做)。

    当您将 t.boolean :show_attribute, :default => true 添加到 create_profiles 迁移时,预计它没有做任何事情。仅执行尚未运行的迁移。如果你从一个新的数据库开始,那么它会将默认设置为 true。

    【讨论】:

    • 那个change_column调用应该在迁移的up方法中,这是一个新的类,会在db/migrate/中生成。 (应该编写down 方法来撤消up 所做的事情。)进行更改,然后rake db:migrate
    • 啊,这更有意义 rkb。谢谢!
    • 直到我写了 def self.updef self.down 之后它才对我有用
    • 那么您可能使用的是旧版本的 Rails。我认为这种语法从 3.1 开始就存在了。
    • 而在 Rails 5 中,您省略了 _attribute,因此它应该只显示 show 或任何列名。
    【解决方案2】:

    作为已接受答案的变体,您还可以在迁移中使用 change_column_default 方法:

    def up
      change_column_default :profiles, :show_attribute, true
    end
    
    def down
      change_column_default :profiles, :show_attribute, nil
    end
    

    Rails API-docs

    【讨论】:

    • 这可确保您不会意外更改任何其他列属性
    • 而在 Rails 5 中你省略了 _attribute 所以它应该只写 show 或任何列名。
    • @labyrinth 你是什么意思? show_attribute专栏的名字,我觉得rails 5跟这个没什么关系吧?
    【解决方案3】:

    我不确定这是什么时候写的,但目前要在迁移的列中添加或删除默认值,您可以使用以下内容:

    change_column_null :products, :name, false
    

    轨道 5:

    change_column_default :products, :approved, from: true, to: false
    

    http://edgeguides.rubyonrails.org/active_record_migrations.html#changing-columns

    Rails 4.2:

    change_column_default :products, :approved, false
    

    http://guides.rubyonrails.org/v4.2/active_record_migrations.html#changing-columns

    这是避免查看迁移或架构以获取列规范的一种巧妙方法。

    【讨论】:

    • 注意,它来自 Rails 5 文档。 Rails 4.2 版本不接受哈希,而是完全新的默认值作为第三个参数。 guides.rubyonrails.org/v4.2/…
    • 关于 Rails 5,两者都做似乎是最正确的方法,例如null: falsedefault: :something 基本上
    【解决方案4】:

    如果您刚刚进行了迁移,您可以回滚然后再次进行迁移。

    要回滚,您可以执行任意多个步骤:

    rake db:rollback STEP=1
    

    或者,如果您使用的是 Rails 5.2 或更新版本:

    rails db:rollback STEP=1
    

    然后,您可以再次进行迁移:

    def change
      add_column :profiles, :show_attribute, :boolean, default: true
    end
    

    别忘了rake db:migrate,如果你正在使用heroku heroku run rake db:migrate

    【讨论】:

      【解决方案5】:

      另外,根据文档:

      不能通过命令行指定默认值

      https://guides.rubyonrails.org/active_record_migrations.html

      所以没有现成的轨道生成器。如上述答案所述,您必须使用 change_column_default 方法手动填写迁移文件。

      您可以创建自己的生成器:https://guides.rubyonrails.org/generators.html

      【讨论】:

        【解决方案6】:
        change_column :things, :price_1, :integer, default: 123, null: false
        

        似乎是将默认值添加到没有null: false 的现有列的​​最佳方法。

        否则:

        change_column :things, :price_1, :integer, default: 123
        

        我对此做了一些研究:

        https://gist.github.com/Dorian/417b9a0e1a4e09a558c39345d50c8c3b

        【讨论】:

          【解决方案7】:

          如果您不想为最近的小改动创建另一个迁移文件 - 从 Rails 控制台:

          ActiveRecord::Migration.change_column :profiles, :show_attribute, :boolean, :default => true
          

          然后退出并重新进入 rails 控制台,这样 DB-Changes 就会生效。那么,如果你这样做......

          Profile.new()
          

          您应该会看到“show_attribute”默认值为 true。

          对于现有记录,如果您想保留现有的“false”设置并且只将“nil”值更新为新的默认值:

          Profile.all.each{|profile| profile.update_attributes(:show_attribute => (profile.show_attribute == nil ? true : false))  }
          

          更新创建此表的迁移,因此任何未来的数据库构建都将从一开始就得到它。还在数据库的任何已部署实例上运行相同的过程。

          如果使用“新数据库迁移”方法,您可以在该迁移中更新现有的零值。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2015-10-07
            • 2012-08-09
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-06-22
            相关资源
            最近更新 更多