module Concern
  module Positionable
    extend ActiveSupport::Concern

    included do
      before_save do
        self.position ||= self.class.count
      end
    end

    def move_to(position)
      self.exec_sql "
      UPDATE #{self.class.table_name}
      SET position = :position
      WHERE id = :id", {id: id, position: position}

      self.exec_sql "
      UPDATE #{self.class.table_name} t
      SET position = x.position - 1
      FROM (
        SELECT i.id, row_number()
          OVER(ORDER BY i.position asc,
                        CASE WHEN i.id = :id THEN 0 ELSE 1 END ASC) AS position
        FROM #{self.class.table_name} i
        WHERE i.position IS NOT NULL
      ) x
      WHERE x.id = t.id AND t.position <> x.position - 1
      ", {id: id}
    end
  end
end
