将 :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_column
是ActiveRecord::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.up
和 def 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: false
和 default: :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 列中的布尔值的主要内容,如果未能解决你的问题,请参考以下文章
为啥 TypeScript 将 .default 添加到全局定义的导入中?