diff --git a/lib/blog/accounts/accounts.ex b/lib/blog/accounts/accounts.ex index 69e5c52..5b4b529 100644 --- a/lib/blog/accounts/accounts.ex +++ b/lib/blog/accounts/accounts.ex @@ -13,6 +13,9 @@ defmodule Blog.Accounts do with {:ok, contact} <- create_contact(contact_attrs), {:ok, user} <- do_create_user(user_attrs, contact) do %{user | contacts: [contact]} + else + {:error, changeset} -> + Repo.rollback(changeset) end end @@ -21,14 +24,14 @@ defmodule Blog.Accounts do def create_contact(attrs) do attrs |> Accounts.Contact.changeset - |> Blog.Repo.insert + |> Repo.insert end defp do_create_user(attrs, contact) do attrs |> Map.put(:contact_id, contact.id) |> Accounts.User.changeset - |> Blog.Repo.insert + |> Repo.insert end end diff --git a/lib/blog/accounts/contact.ex b/lib/blog/accounts/contact.ex index 9779055..c598b9f 100644 --- a/lib/blog/accounts/contact.ex +++ b/lib/blog/accounts/contact.ex @@ -24,6 +24,7 @@ defmodule Blog.Accounts.Contact do contact |> cast(attrs, [:type, :value]) |> validate_required([:type, :value]) + |> unique_constraint(:value, name: :contacts_type_value_index) end end diff --git a/test/blog/accounts/accounts_test.exs b/test/blog/accounts/accounts_test.exs new file mode 100644 index 0000000..b677efb --- /dev/null +++ b/test/blog/accounts/accounts_test.exs @@ -0,0 +1,27 @@ +defmodule Blog.AccountsTest do + use Blog.DataCase + + alias Blog.Accounts + + test "create_user/1 returns {:error, changeset} and rolles back transaction on error" do + attrs = %{ + contact: %{type: "phone", value: "+1 000 000 0000"}, + name: "", + password: "password" + } + + contact_count = Repo.aggregate(Accounts.Contact, :count, :id) + + assert {:error, %Ecto.Changeset{}} = Accounts.create_user(attrs) + assert ^contact_count = Repo.aggregate(Accounts.Contact, :count, :id) + end + + test "create_user/1 discards duplicate contacts" do + contact = %{type: "phone", value: "+1 000 000 0000"} + + assert {:ok, _} = Accounts.create_user(%{contact: contact, name: "name", password: "password"}) + + assert {:error, changeset} = Accounts.create_user(%{contact: contact, name: "other", password: "password"}) + assert "has already been taken" in errors_on(changeset).value + end +end