Currently, voting down after voting up (or the opposite) just removes the old vote and replaces it with the new one, recording only one UserAction for the new vote. To make sure we register things properly with the reputation, we should record a revert_vote action before recording the new one.
```elixir
defmodule :"Elixir.DB.Repo.Migrations.Add-missing-revert-vote-actions" do
use Ecto.Migration
def up do
Ecto.Adapters.SQL.query!(DB.Repo, """
WITH vote_actions AS (
SELECT user_id, entity, entity_id
FROM users_actions
WHERE entity IN (4,5) -- comments + sourced comments
AND "type" IN (9,10,12,13) -- Votes up/down AND their revert actions
AND entity_id IS NOT NULL -- TODO: See what TO DO WITH deleted comments
GROUP BY user_id, entity, entity_id
HAVING COUNT(*) > 1
) SELECT ua.*
FROM users_actions ua
INNER JOIN vote_actions va
ON va.user_id = ua.user_id
AND va.entity = ua.entity
AND va.entity_id = ua.entity_id
ORDER BY user_id ASC, entity ASC, entity_id ASC, inserted_at ASC, id ASC
""")
|> Map.get(:rows)
|> Enum.group_by(fn action -> "#{action.user_id}-#{action.entity}-#{action.entity_id}" end)
|> Enum.each(fn {_key, actions} -> analyze_actions(actions) end)
# TODO: Need to test with real data (local dev doesn't have occurences)
raise "abort"
end
def down do
# No rollack
end
defp analyze_actions([action | next_actions], prev_action = nil) do
check_action(action, prev_action)
analyze_actions(next_actions, action)
end
defp analyze_actions([], _prev_action = nil) do
nil
end
# Triggered when a vote up is found right after a vote down
defp check_action(action, prev_action)
when not is_nil(prev_action) and prev_action.type == 10 and action.type == 9 do
action.user_id
|> CF.Actions.ActionCreator.action_revert_vote(action.video_id, :revert_vote_down, comment)
|> Ecto.Changeset.change(inserted_at: DateTime.add(prev_action.inserted_at, 1, :microsecond))
|> DB.Repo.insert()
end
defp check_action(_action, _prev_action) do
nil
end
end
```
Currently, voting down after voting up (or the opposite) just removes the old vote and replaces it with the new one, recording only one
UserAction
for the new vote. To make sure we register things properly with the reputation, we should record arevert_vote
action before recording the new one.