2016-02-17 5 views
4

В настоящее время у меня есть таблица users, содержащая client_id (так, a User belongs_to :client).Migrate Rails table from принадлежит_to to has_and_belongs_to_many

Нам необходимо поддерживать несколько клиентов, связанных с пользователем, поэтому мы внедрили ассоциацию User has_and_belongs_to_many :clients. Для этого мы:

  • создал новую clients_users таблицу, с user_id и client_id колонн;
  • удалено client_id из users.

Теперь, как мы можем автоматически создавать HABTM записи для каждого client_id мы первоначально имели в users таблице? Мы не хотим потерять данные.

Я не уверен, с чего начать с db:migrate не должен включать в себя модели или ассоциации между ними, а выполнение необработанных запросов может оказаться сложным в моем случае.

+0

Я не понимаю, как вы можете иметь откат центр. Вы делаете изменение, тогда «Пользователь» имеет 2 «Клиент» с идентификаторами 2 и 4. Как вы собираетесь перевернуть это обратно в own_to на пользователя? –

+0

Изначально все пользователи, имеющие что-то в 'client_id', будут иметь только один связанный клиент HABTM. Почему у них есть 2 клиента? – linkyndy

+0

Поскольку кто-то использовал систему и дал им 2, скажите через неделю, что вы хотите откат. Вы потеряете данные. –

ответ

6

Просто добавьте новые ассоциации has_and_belongs_to_many в категории User и Client и выполните следующую миграцию.

Это решения от http://manuelvanrijn.nl/blog/2013/03/04/rails-belongs-to-to-has-many/

class MultipleClientsForUser < ActiveRecord::Migration 
    def up 
    create_table :clients_users, id: false do |t| 
     t.references :client, :user 
    end 

    # define the old belongs_to client associate 
    User.class_eval do 
     belongs_to :single_client, class_name: "Client", foreign_key: "client_id" 
    end 

    # add the belongs_to client to the has_and_belongs_to_many client 
    User.find_each do |user| 
     unless user.single_client.nil? 
     user.clients << user.single_client 
     user.save 
     end 
    end 

    # remove the old client_id column for the belongs_to associate 
    remove_column :users, :client_id 
    end 

    def down 
    add_column :users, :client_id, :integer 

    User.class_eval do 
     belongs_to :single_client, class_name: "Client", foreign_key: "client_id" 
    end 

    #Note that only one client may be restored in rollback 
    User.find_each do |user| 
     user.single_client = user.clients.first unless user.clients.empty? 
     user.save 
    end 

    drop_table :clients_users 
    end 
end 
+0

Безопасно ли использовать модели внутри миграций? Должно ли все храниться в одной миграции? Что происходит, когда что-то не удается? Является ли материал откатанным, а столбцы изменены снова? – linkyndy

+1

Безопасно ли использовать модели внутри миграций? - Это обычная практика. Должно ли все храниться в одной миграции? Я думаю, что это нужно сделать за один шаг и отступить в один шаг. Что происходит, когда что-то не удается? Миграции завернуты в транзакцию, поэтому все изменения откатываются, если что-то не удается. – yurko

+1

@AndreiHorak, чтобы быть в безопасности при использовании моделей внутри миграции, вы можете попробовать этот подход http://blog.makandra.com/2010/03/how-to-use-models-in-your-migrations-without-killing-kittens/ – yurko

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