Добавление STI в существующую таблицу

Я хочу добавить STI в существующую таблицу, используя столбец пользовательского типа. Назовем этот тип вкуса, соответствующей моделью которого является Фрукт.

В модели Fruit у меня есть:

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: ...

Есть идеи, что происходит? Я могу запустить миграцию, если прокомментирую set_inheritance_column в модели Fruit, а затем раскомментирую ее после запуска миграции. Однако, очевидно, я не хочу этого делать.


person keruilin    schedule 11.04.2010    source источник


Ответы (2)


Столбец 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.

person Harish Shetty    schedule 11.04.2010
comment
Или, если возможно, повторно заполните ваши данные ненулевыми полями. - person Ryan Bigg; 12.04.2010
comment
Пользователь добавляет новый ненулевой столбец в таблицу с данными. Он не сможет пройти мимо add_column, если новый столбец не допускает значение NULL. - person Harish Shetty; 12.04.2010
comment
Между add_column и change_column мне пришлось сделать это, чтобы удалить значение по умолчанию: change_column_default (table_name, column_name, nil) - person kstevens715; 14.01.2015

Для тех, кто находит это с помощью Rails 4, вы можете:

  1. добавить столбец, изначально разрешающий null
  2. Перенесите данные, убедившись, что все существующие записи имеют значение type.
  3. Используйте change_column_null, чтобы сделать столбец null ложным после переноса данных.

    # 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

Как изменить столбец, допускающий значение NULL не обнуляемый в миграции Rails?

person sp89    schedule 22.07.2016