         |> assign(:annotation, annotation)
     end
   end
+
+  # Insert annotation and tags
+  defp insert_annotation_and_tags(changeset) do
+    tags = Ecto.Changeset.get_field(changeset, :tags)
+
+    Repo.transaction(fn ->
+      result = Repo.insert(changeset)
+      |> add_tags(tags)
+
+      case result do
+        {:error, changeset} ->
+          Repo.rollback(changeset)
+
+        {:ok, annotation, tags} ->
+          Map.merge(annotation, %{tags: tags})
+      end
+    end)
+  end
+
+  # Add tags to an annotation
+  #
+  # Returns a {:ok, tags} or {:error, changeset} tuple
+  defp add_tags({:error, changeset}, _), do: {:error, changeset}
+  defp add_tags({:ok, annotation}, tags) do
+    tags
+    |> Enum.map(fn tag ->
+      AnnotationTag.changeset(%AnnotationTag{}, %{tag_id: tag,
+                                                  annotation_id: annotation.id})
+    end)
+    |> Enum.reduce({:ok, annotation, []}, &add_tag/2)
+  end
+
+  # Add a tag into a question
+  defp add_tag(_, {:error, changeset}), do: {:error, changeset}
+  defp add_tag(changeset = %{valid?: valid}, {:ok, _, _}) when not valid do
+    {:error, changeset}
+  end
+  defp add_tag(changeset, {:ok, annotation, tags}) do
+    case Repo.insert(changeset) do
+      {:ok, tag} ->
+        {:ok, annotation, [tag|tags]}
+
+      {:error, changeset} ->
+        {:error, changeset}
+    end
+  end
 end

  """
  use Core.Web, :controller
  alias Core.Annotation

  plug :find when action in [:update, :delete, :show]
  plug Core.Auth, %{key: :annotation,

    |> build_assoc(:annotations)
    |> Annotation.changeset(annotation_params)

    case insert_annotation_and_tags(changeset) do
      {:ok, annotation} ->
        annotation = Repo.preload(annotation, :annotation_tags)

