ruby-on-railsdatabase-migrationacts-as-list

How to add position column to acts_as_list on existing database records in Rails migration?


I have seen How to change a nullable column to not nullable in a Rails migration? for the problem of adding a non-nullable column to an existing database table with existing records. As such, I am thinking of doing this to add position sortability to the model using acts_as_list:

class AddPositionToArticles < ActiveRecord::Migration[6.1]
  def change
    add_column :articles, :position, :integer
    Article.where(position: nil).each do |article|
      article.position = 0
      article.save!
    end
    change_column :articles, :position, :integer, null: false
  end
end

However, that is incorrect, because the position needs to be incremental based on relative positioning to the user record, so user.articles are sorted based on a predefined position.

How can I do this in the migration? Will it happen automatically when I add acts_as_list in the article? And so simply, all I need to do is resave the record in the migration (and not set the position)?

How do I make sure they are put in the same order they started at?


Solution

  • class AddPositionToArticles < ActiveRecord::Migration[6.1]
      def change
        add_column :articles, :position, :integer
        User.find_each do |user|
          user.articles.order(created_at: :asc).find_each.with_index do |article, index|
            article.update_columns(position: index)
          end
        end
        change_column :articles, :position, :integer, null: false
      end
    end