将 :default => true 添加到现有 Rails 列中的布尔值

Posted

技术标签:

【中文标题】将 :default => true 添加到现有 Rails 列中的布尔值【英文标题】:Adding :default => true to boolean in existing Rails column 【发布时间】: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

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

【问题讨论】:

【参考方案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))  

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

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

【讨论】:

以上是关于将 :default => true 添加到现有 Rails 列中的布尔值的主要内容,如果未能解决你的问题,请参考以下文章

js实际运用

grafana 网页嵌入

为啥 TypeScript 将 .default 添加到全局定义的导入中?

如何将mysql添加到服务里

将 QName 作为字符串添加到 @XmlMixed@XmlAnyElement(lax = true) 列表

如何将 reftex-default-bibliography 作为局部变量添加到 Latex 中?