2016-10-08 5 views
0

Я изменяю значение базовой модели, расширенной с использованием STI, в существующем приложении. Как написать миграцию, чтобы существующие столбцы соответствовали новым inheritance_column?Rails inheritance_column migration

Вот моя первая попытка:

class MigrateStoryTypes < ActiveRecord::Migration 

    def self.up 
    Story.all.each { |story| 
     new_story_type = story.story_type.camelize + 'Story' 
     puts "changing #{story.id}'s story_type from #{story.story_type} to #{new_story_type}" 
     story.update_column :story_type, new_story_type 
    } 
    end 

    def self.down 
    Story.all.each { |story| 
     new_story_type = story.story_type.underscore.gsub /_story/, '' 
     puts "changing #{story.id}'s story_type from #{story.story_type} to #{new_story_type}" 
     story.update_column :story_type, new_story_type 
    } 
    end 

end 

Однако это не удается с:

ActiveRecord :: SubclassNotFound: Механизм наследование одной таблицы не удалось найти подкласс: 'clean_slate'. Эта ошибка возникает , потому что столбец «story_type» зарезервирован для хранения класса в случае наследования. Переименуйте этот столбец, если вы не намеревались его использовать , который будет использоваться для хранения класса наследования или перезаписать Story.inheritance_column, чтобы использовать другой столбец для этой информации.

Есть ли прямой способ сделать это через ActiveRecord или мне нужно использовать временный столбец, SQL и т. Д.?

+1

Итак, у вас уже есть столбец 'story_type', который содержит подчеркнутые версии имени класса (т.е.' 'clean_slate''), и теперь вы хотите перенести это в STI, используйте« story_type »в качестве столбца STI и преобразуйте Значения 'story_type' для имен классов? Сколько у вас значений story_type? –

+0

@muistooshort Точно. В настоящее время у меня есть два значения history_type. – pdoherty926

ответ

1

Использование моделей внутри миграций - это, как правило, плохая идея, поскольку классы моделей предполагают, что они знают, что такое структура базы данных, но миграции предназначены для управления структурой базы данных. Ваше сообщение об ошибке - это всего лишь один случай, когда классы моделей не синхронизируются с базой данных. Как только Story.all пытается создать экземпляр модели, вы получаете исключение STI ActiveRecord::SubclassNotFound, потому что ActiveRecord ожидает найти имя класса в story_type, но у вас все еще есть свои старые типы строк в story_type: вы не можете исправить свою базу данных с помощью моделей, пока ваша база данных не будет исправлено.

Я бы рекомендовал вам притвориться, что ваши модели вообще не существуют при миграции, вам будет лучше, если вы будете работать с базой данных напрямую. У вас есть только два story_type значения, так что SQL довольно просто:

def up 
    connection.execute(%q{ 
    update stories 
    set story_type = case story_type 
     when 'whatever1' then 'Whatever1Story' 
     when 'whatever2' then 'Whatever2Story' 
    end 
    }) 
end 

Там только два значения, и вы знаете, что они так что не тратьте время, пытаясь быть умным.

+0

Много хороших советов здесь. Благодаря! – pdoherty926

Смежные вопросы