2

У меня есть приложение Rails со следующим соотношением:Rails Преобразование отношений has_many в имеет и принадлежит многим

region.rb

class Region < ActiveRecord::Base 
    has_many :facilities 
end 

facility.rb

class Facility < ActiveRecord::Base 
    belongs_to :region 
end 

Я хочу немного расширить функциональность, чтобы объекты могли принадлежать более чем одному региону за один раз е. Я считаю, что могу сделать это с помощью отношений has_many_through, но мне нужно некоторое руководство по преобразованию существующего has_many в a. Я понимаю, как создавать и подключать таблицу соединений, но как я могу взять существующие данные и перевести их?

Так, например. На объекте объекта есть region_id, так как объекты могут принадлежать более чем одному региону, мне, вероятно, понадобится поле region_ids и выкопайте коллекцию регионов в этот столбец, который затем должен заполнить другую сторону ассоциации через таблицу соединений. У меня есть эта часть, в значительной степени выясненная, как двигаться вперед и подключить ассоциацию. Но я не уверен, как использовать существующие данные и переводить их, чтобы приложение не ломалось, когда я меняю ассоциацию модели.

Любые советы были бы весьма полезными.

ответ

3

I s uggest вы до всегда использовать has_many :through вместо HBTM.

Чтобы установить этот вид связи вам понадобятся следующие настройки:

# region.rb 
class Region 
    has_many :facility_regions 
    has_many :facilities, through: :facility_regions 
end 

# facility.rb 
class Facility 
    has_many :facility_regions 
    has_many :regions, through: :facility_regions 
end 

# facility_region.rb 
class FacilityRegion 
    belongs_to :facility 
    belongs_to :region 
end 

Кроме того, конечно же, вам необходимо создать миграцию:

rails g migration create_facility_regions facility_id:integer region_id:integer 
# in this migration create a uniq index: 
add_index :facility_regions, %I(facility_id region_id), name: :facility_region 
rake db:migrate 

UPD

Что касается миграции из одного состояния базы данных в другое.

Я думаю, что это не должно быть проблемой.

1) Не удаляйте прежние отношения (оставьте has_many :facilities и belongs_to :region в моделях).

2) Когда создается новая таблица и новые ассоциации добавляются к классам (которые я показал) создать новую миграцию:

rails g migration migrate_database_state 

3) Напишите сценарий, который будет создавать новые записи в БД (для отражает текущее положение вещей):

ActiveRecord::Base.transaction do 
    Facility.where.not(region_id: nil).find_each do |facility| 
    next if FacilityRegion.find_by(falicity_id: facility.id, region_id: facility.region_id) 
    FacilityRegion.create!(facility_id: facility.id, region_id: facility.region_id) 
    end 
end 

4) Поместите этот сценарий в последнюю созданной миграцию и запустить его (или в консоли без миграции, эффект будет таким же).

5) После того, как скрипт успешно работать, создавать новую миграцию, в которой вы удалите region_id из facilities таблицы и удалить эти ассоциации определения (has_many :facilities и belongs_to :region) из моделей.

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

+0

Понял, у меня была эта часть и поняла, как подключить среднюю/объединенную таблицу, чтобы сделать работу ассоциации. Мой главный вопрос состоял в том, что после изменения миграции и моделирования модели, как я могу использовать существующие объекты и регионы и перенести все данные/столбцы, чтобы заполнить таблицу соединений? – nulltek

+0

Благодарим за быстрый ответ, я попробую сегодня и отправлю любые вопросы, которые могут возникнуть у меня. – nulltek

+0

Это сработало, однако мне пришлось реорганизовать migrate_database_state, чтобы не использовать find_by, поскольку это приложение Rails 3.2. Извините, я должен был указать. – nulltek

1

Вам нужно добавить еще одну модель, "средний парень" под названием FacilityRegion.rb, как это:

facility.rb

class Facility < ActiveRecord::Base 
    has_many :falicity_regions 
    has_many :regions, through: falicity_regions 
end 

facility_region.rb

class FacilityRegion < ActiveRecord::Base 
    belongs_to :region 
    belongs_to :facility 
end 

область. rb

class Region < ActiveRecord::Base 
    has_many :falicity_regions 
    has_many :facilities, through: falicity_regions 
end 
+0

Получил это, у меня была эта часть и поняла, как подключить таблицу middle/join, чтобы сделать работу ассоциации. Мой главный вопрос состоял в том, что после изменения миграции и моделирования модели, как я могу использовать существующие объекты и регионы и перенести все данные/столбцы, чтобы заполнить таблицу соединений? – nulltek

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