Move Rails table from owner_to to has_and_belongs_to_many

I currently have a table userscontaining client_id(so, a User belongs_to :client).

We need to support several customer-related clients, so we have implemented the association User has_and_belongs_to_many :clients. To do this, we:

  • created a new table clients_userswith columns user_idand client_id;
  • removed client_idfrom users.

Now, how can we automatically create HABTM entries for each client_idthat we originally had in the table users? We do not want to lose data.

I’m not sure where to start, because I db:migratedon’t have to include models or associations between them, and running raw queries can be difficult in my case.

+4
source share
1 answer

Just add a new association has_and_belongs_to_manyto the model Userand Clientrun the following migration.

This is a solution from 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
+6
source

Source: https://habr.com/ru/post/1629134/


All Articles