defmodule Mix.Tasks.MigrateContactDetails do
use Mix.Task
import Ecto.Query, only: [from: 2]
@shortdoc "Migrate ContactDetails data into NewContactDetails"
def run(), do: run(0)
def run(_args) do
Mix.Task.run "app.start", []
Mix.shell.info """
Converting data from ContactDetails into the NewContactDetails format
"""
transaction =
DB.Repo.all(from u in DB.Session, select: u.id)
|> Enum.map(&convert_record/1)
|> Enum.reduce(Ecto.Multi.new, &Ecto.Multi.append/2)
|> DB.Repo.transaction
case transaction do
{:ok, _} ->
Mix.shell.info "All done! The transaction has been applied."
{:error, failed_operation, failed_value, changes_so_far} ->
Mix.shell.error "One of the operations failed.:"
Mix.shell.error "Operation: #{inspect(failed_operation)}"
Mix.shell.error "Value: #{inspect(failed_value)}"
Mix.shell.error "The transaction has been rolled back."
end
end
def convert_record(user_id) do
# Retrieve all the old records associated with the user
old_records =
DB.Repo.all(from cd in DB.ContactDetail,
where: cd.session_id == ^user_id)
# Reduce them down into a single record in the new
# format.
new_record = Enum.reduce(
old_records,
%DB.NewContactDetail{session_id: user_id},
&build_new_record/2
)
Ecto.Multi.insert(
Ecto.Multi.new,
String.to_atom("user_#{user_id}"),
new_record
)
end
def build_new_record(old, new) do
case old.key do
"email" ->
%{new | email: old.value}
"phone_number" ->
%{new | phone_number: old.value}
"mailchimp_unique_email_id" ->
%{new | mailchimp_unique_email_id: old.value}
other ->
Mix.shell.warn """
Don't know what #{inspect(other)} is - not adding it to the new record.
"""
new
end
end
end