2010-04-11 49 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?