Postgres извлечение полиморфа c колонка - PullRequest
1 голос
/ 11 апреля 2020

У меня есть следующая таблица с именем feeds:

 from_type | from_id 
-----------+---------
 user      |       1
 project   |       1
 user      |       2
 program   |       1
 program   |       2
 project   |       1
 challenge |       1
 project   |       3
 community |       1

, и я хотел бы преобразовать ее в это:

 from_type | user_id | project_id | program_id | challenge_id | community_id
-----------+---------+------------+------------+--------------+-------------
 user      |       1 |            |            |              |         
 project   |         |          1 |            |              |         
 user      |       2 |            |            |              |         
 program   |         |            |          1 |              |         
 program   |         |            |          2 |              |         
 project   |         |          1 |            |              |         
 challenge |         |            |            |            1 |         
 project   |         |          3 |            |              |         
 community |         |            |            |              |           1

Моя причина для этого состоит в том, чтобы обратная миграция, если нам нужно откатиться. Мне удалось преобразовать нижнюю версию в верхнюю версию с coalesce + update statement, но я менее уверен, как выполнить обратную операцию.

Вот миграция вверх, как должна выглядеть миграция вниз?

class PolymorphicFeedTable < ActiveRecord::Migration[5.2]
  def up
    execute <<-SQL
      UPDATE feeds SET
        from_id = coalesce(user_id, project_id, community_id, challenge_id, program_id, need_id);
    SQL
  end

  def down
    execute <<-SQL
      ?
    SQL
  end
end

1 Ответ

2 голосов
/ 11 апреля 2020

Если вы развернете свой метод up:

def up
  %w[challenge community need program project user].each do |type|
    execute("update feeds set from_id = #{type}_id where from_type = '#{type}'")
  end
end

, тогда вы сможете увидеть путь назад, просто отмените присвоение:

def down
  %w[challenge community need program project user].each do |type|
    execute("update feeds set #{type}_id = from_id where from_type = '#{type}'")
    # ------------------------^^^^^^^^^^^^^^^^^^^^
  end
end

Это предполагает, что данные вашей таблицы не не нарушены (т. е. ваши значения from_type соответствуют столбцам X_id).


Вы можете connection.quote(type) вместо простого переноса #{type} в одинарные кавычки вручную, но вы знаете, что типы безопасны заранее, так что в этом нет необходимости. Аналогично для connection.quote_column_name и #{type}_id интерполяций.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...