2010-04-11 44 views
0

我想使用自定义类型列将STI添加到现有表。我们称之为taste_type,其对应的模型是Fruit。将STI添加到现有表

在水果模型我有:

set_inheritance_column :taste_type 

在我的移民加入STI我:

class AddSTI < ActiveRecord::Migration 
    def self.up 
    add_column :fruits, :taste_type, :string, :limit => 100, :null => false 
    Fruit.reset_column_information 
    Fruit.find_by_id(1).update_attributes({:taste_type => 'Sour'}) 
    end 

    def self.down 
    remove_column :fruits, :taste_type 
    end 

end 

当我运行迁移,我收到以下错误:

Mysql::Error: Column 'taste_type' cannot be null: ... 

任何想法是怎么回事?如果我在Fruit模型中评论set_inheritance_column,则可以运行迁移,然后在运行迁移后取消注释。显然,我不想这样做,但是。

回答

1

taste_type列不能为空。数据库将引发错误,因为您正在向具有现有行的表添加新列(不能为空)。

解决此问题的一种方法是向该列添加默认值,然后重置默认值。

add_column :fruits, :taste_type, :string, :limit => 100, :null => false, 
     :default => "Sour" 
change_column :fruits, :taste_type, :string, :limit => 100, :null => false 

Fruit.reset_column_information 
Fruit.find_by_id(1).update_attributes({:taste_type => 'Sour'}) 

其他方法是在截断fruits表后运行迁移。

+0

或者,如果可能的话,重新播种的非空字段中的数据。 – 2010-04-12 02:44:55

+0

用户正在向包含数据的表添加新的非空列。如果新列不能为空,他将无法越过'add_column'。 – 2010-04-12 03:17:38

+0

在add_column和change_column之间,我不得不这样做来删除默认值:change_column_default(table_name,column_name,nil) – kstevens715 2015-01-14 17:25:57

0

对于那些谁发现这个使用Rails 4,你可以:

  1. 添加列,使空最初
  2. 迁移数据,确保所有预先存在的记录有type
  3. 在迁移数据后,使用change_column_null使列的空值为false。

    # my_migration.rb 
    
    class MyMigration < ActiveRecord::Migration 
        class Fruit < ActiveRecord::Base; end 
    
        def up 
        add_column :fruits, :taste_type, :string, limit: 100, default: "Sour" 
    
        Fruit.reset_column_information 
        Fruit.find_each do |fruit| 
         fruit.update_attributes!(taste_type: 'Sour') 
        end 
    
        change_column_null :fruits, :taste_type, false 
        end 
    end 
    

http://apidock.com/rails/ActiveRecord/ConnectionAdapters/SchemaStatements/change_column_null

How to change a nullable column to not nullable in a Rails migration?