2014-08-29 2 views
2

У моей модели (Bar) уже есть ссылочный столбец, назовем его foo_id, и теперь мне нужно изменить foo_id на fooable_id и сделать его полиморфным.Как изменить ссылочный столбец, который будет полиморфным?

Я полагаю, что у меня есть два варианта:

  • Создать новый эталонный столбец fooable который является полиморфным и перенастройками идентификаторов из foo_id (Что было бы лучшим способом перенести эти Могу ли я просто сделать Bar.each { |b| b.fooable_id = b.foo_id }?
  • Переименовать foo_id в fooable_id и добавить polymorphic к fooable_id. Как добавить polymorpic в существующую колонку?
+0

Ой, вау, ты все еще пользуешься Rails 2? Это настоящая или опечатка? –

ответ

9

1. Изменить имя foo_id к fooable_id, переименовав его в миграции, как:

rename_column :bars, :foo_id, :fooable_id 

2. и добавить полиморфизм к нему путем добавления необходимого foo_type столбца в миграции :

add_column :bars, :fooable_type, :string 

3. и в модели:

class Bar < ActiveRecord::Base 
    belongs_to :fooable, 
    polymorphic: true 
end 

4. Наконец семя типа вас уже соответствующий типа, как:

Bar.update_all(fooable_type: 'Foo') 

Read Define polymorphic ActiveRecord model association!

+1

Последний шаг можно переписать как 'Bar.update_all (fooable_type: 'Foo')', правильно? –

+0

Несомненно. Это способ, который можно прочитать в mroe .. :) Я отредактирую это. –

0

ссылки на ваш вопрос конкретно, вот что я хотел бы сделать:

Все данные в вашей модели Bar будут сохранены в соответствии с моделью Bar.Это означает, что если вы измените атрибут foo_id в своей модели, вы сможете просто заполнить атрибут bar_type, который необходимо добавить (поскольку все они смогут ссылаться на ту же модель)

Способ сделать это выглядит следующим образом:

  1. Создание миграции для foo_id>fooable_id
  2. Вставьте fooable_type колонку
  3. в рельсах консоли, проходное всех существующих записей Bar, заполняя fooable_type столбец

Первые вещи первое:

$ рельсам г миграции ChangeFooID

#db/migrate/latest.rb 
class Latest 
    def change 
     rename_column :bars, :foo_id, :fooable_id 
     add_column :bars, :fooable_type, :string, after: :id 
    end 
end 

Это позволит создать различные столбцы для вас. Тогда вам просто необходимо, чтобы иметь возможность перебрать записи & изменения type колонки:

рельсы гр

Bar.find_each do |bar| 
    bar.update(barable_type: "Foo") 
end 

Это позволит вам изменить тип ваших колонок, что дает вам способность связывать все текущие записи с соответствующими записями.


полиморфизм

Вы сможете use the Rails docs as a reference о том, как связать ваши модели:

#app/models/foo.rb 
class Foo < ActiveRecord::Base 
    has_many :bars, as: :barable 
end 

#app/models/bar.rb 
class Bar < ActiveRecord::Base 
    belongs_to :foo, polymorphic: true 
end 

enter image description here

+0

** bar.update (barable_type: «Foo») ** не будет работать, поскольку обновление является закрытым. Думаю, вы имели в виду ActiveRecord # update_attribute. –

2

Одно небольшое изменение, которое я сделал бы это в миграция:

#db/migrate/latest.rb 
class Latest 
    def change 
    rename_column :bars, :foo_id, :fooable_id 
    add_column :bars, :fooable_type, :string, after: :id, default: 'Foo' 
    end 
end 

Это устранит необходимость переноса данных.

Обновление: это будет работать на рельсах 3 и выше. Согласно вопросу, исходный базовый класс подразумевается как Foo.

+0

Умм, это неверно в Rails 2.3, а также исключает возможность использования нетипизированного базового слоя – deiga

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