开发者

Adding STI to Existing Table

I want to add STI to an existing table using a custom type column. Let's call this taste_type whose corresponding model is Fruit.

In the Fruit model I have:

set_inheritance_column :taste_type

In my migration to add STI I have:

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

When I run the migration, I 开发者_JS百科get the following error:

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

Any idea what's going? I can get the migration to run if I comment the set_inheritance_column in the Fruit model, then uncomment it after I run the migration. Obviously, I don't want to do this, however.


The taste_type column can't be null. The DB throws an error because you are adding a new column(that can't be null) to a table with existing rows.

One way to work around this problem is to add a default value to the column and subsequently reset the default value.

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'})

Other way is to run the migration after truncating the fruits table.


For those who find this using Rails 4, you can:

  1. add the column, allowing null initially
  2. Migrate your data, ensuring all pre-existing records have a type value
  3. Use change_column_null to make the column null false after migrating the data.

    # 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?

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜