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


160

我在SO上看到了一些关于将默认布尔值添加到现有列的问题(即这个问题)。所以我尝试了这个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

有人可以告诉我我在做什么错吗?

Answers:


314

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 => truecreate_profiles迁移中时,预计它不会做任何事情。仅执行尚未运行的迁移。如果您从一个全新的数据库开始,那么它将默认设置为true。


2
该change_column调用应位于up迁移的方法中,这是将在db / migrate /中生成的新类。(down应该编写该方法以撤消该up操作。)然后进行更改rake db:migrate
rkb 2011年

嗯,rkb更有意义。谢谢!
tvalent2 2011年

它不是为我工作,直到我写def self.updef self.down
卡米尔Szot

那时您可能正在使用旧版本的rails。我认为从3.1开始就有这种语法。
罗宾(Robin)2013年

在Rails 5中,您省去了_attribute,所以它应该只说show或说列名称是什么。
迷宫

95

作为已接受答案的变体,您还可以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文档


1
这样可以确保您不会意外更改其他任何列属性
Brian Low

1
在Rails 5中,您不必使用_attribute,所以它应该只说show或说列名称是什么。
迷宫

1
@labyrinth是什么意思?show_attribute 列的名称,我认为Rails 5与此无关,对吗?
罗宾

34

我不确定这是何时编写的,但是当前要在迁移的列中添加或删除默认值,可以使用以下命令:

change_column_null :products, :name, false

Rails 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/…–
Clamoris

关于Rails 5,两者似乎都是最正确的方法,例如 null: falsedefault: :something基本
多利安


1

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

要回滚,您可以根据需要执行许多步骤:

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



0

如果您不想为最近的小改动创建另一个迁移文件-从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))  }

更新创建此表的迁移,以便将来的任何数据库构建都能从一开始就正确使用它。还可以在数据库的任何已部署实例上运行相同的过程。

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.