diff --git a/lib/code_corps/messages/conversations.ex b/lib/code_corps/messages/conversations.ex new file mode 100644 index 000000000..453ea13d7 --- /dev/null +++ b/lib/code_corps/messages/conversations.ex @@ -0,0 +1,19 @@ +defmodule CodeCorps.Messages.Conversations do + @moduledoc ~S""" + Subcontext aimed at managing `CodeCorps.Conversation` records aimed at a + specific user belonging to a `CodeCorps.Message`. + """ + + alias Ecto.Changeset + + alias CodeCorps.{Conversation} + + @doc false + @spec create_changeset(Conversation.t, map) :: Ecto.Changeset.t + def create_changeset(%Conversation{} = conversation, %{} = attrs) do + conversation + |> Changeset.cast(attrs, [:user_id]) + |> Changeset.validate_required([:user_id]) + |> Changeset.assoc_constraint(:user) + end +end diff --git a/lib/code_corps/messages/messages.ex b/lib/code_corps/messages/messages.ex index 4e6847167..7857c5c94 100644 --- a/lib/code_corps/messages/messages.ex +++ b/lib/code_corps/messages/messages.ex @@ -67,6 +67,11 @@ defmodule CodeCorps.Messages do def create(%{} = params) do %Message{} |> Message.changeset(params) + |> Changeset.cast(params, [:author_id, :project_id]) + |> Changeset.validate_required([:author_id, :project_id]) + |> Changeset.assoc_constraint(:author) + |> Changeset.assoc_constraint(:project) + |> Changeset.cast_assoc(:conversations, with: &Messages.Conversations.create_changeset/2) |> Repo.insert() end diff --git a/lib/code_corps_web/controllers/conversation_controller.ex b/lib/code_corps_web/controllers/conversation_controller.ex index 23b758fa6..bcd0e4615 100644 --- a/lib/code_corps_web/controllers/conversation_controller.ex +++ b/lib/code_corps_web/controllers/conversation_controller.ex @@ -9,7 +9,7 @@ defmodule CodeCorpsWeb.ConversationController do } action_fallback CodeCorpsWeb.FallbackController - plug CodeCorpsWeb.Plug.DataToAttributes + plug CodeCorpsWeb.Plug.DataToAttributes, %{"conversation" => "conversations"} plug CodeCorpsWeb.Plug.IdsToIntegers @spec index(Conn.t, map) :: Conn.t diff --git a/lib/code_corps_web/controllers/message_controller.ex b/lib/code_corps_web/controllers/message_controller.ex index f1747b6c9..f37054ecb 100644 --- a/lib/code_corps_web/controllers/message_controller.ex +++ b/lib/code_corps_web/controllers/message_controller.ex @@ -9,7 +9,7 @@ defmodule CodeCorpsWeb.MessageController do } action_fallback CodeCorpsWeb.FallbackController - plug CodeCorpsWeb.Plug.DataToAttributes + plug CodeCorpsWeb.Plug.DataToAttributes, %{"conversation" => "conversations"} plug CodeCorpsWeb.Plug.IdsToIntegers @spec index(Conn.t, map) :: Conn.t @@ -23,7 +23,7 @@ defmodule CodeCorpsWeb.MessageController do @spec show(Conn.t, map) :: Conn.t def show(%Conn{} = conn, %{"id" => id}) do with %User{} = current_user <- conn |> CodeCorps.Guardian.Plug.current_resource, - %Message{} = message <- Message |> Repo.get(id), + %Message{} = message <- Message |> Repo.get(id) |> preload(), {:ok, :authorized} <- current_user |> Policy.authorize(:show, message, %{}) do conn |> render("show.json-api", data: message) end @@ -40,7 +40,7 @@ defmodule CodeCorpsWeb.MessageController do end end - @preloads [:author, :project] + @preloads [:author, :project, :conversations] def preload(data) do Repo.preload(data, @preloads) diff --git a/lib/code_corps_web/plugs/data_to_attributes.ex b/lib/code_corps_web/plugs/data_to_attributes.ex index c6ca3bb41..3cfdaee86 100644 --- a/lib/code_corps_web/plugs/data_to_attributes.ex +++ b/lib/code_corps_web/plugs/data_to_attributes.ex @@ -12,13 +12,31 @@ defmodule CodeCorpsWeb.Plug.DataToAttributes do def init(opts), do: opts @spec call(Conn.t, Keyword.t) :: Plug.Conn.t - def call(%Conn{params: %{"data" => data} = params} = conn, _opts) do + def call(%Conn{params: %{"data" => data} = params} = conn, many_mappings) do attributes = params |> Map.delete("data") - |> Map.merge(data |> JaSerializer.Params.to_attributes) + |> Map.delete("included") + |> Map.merge(params |> parse_data) + |> Map.merge(params |> parse_included(many_mappings)) + |> IO.inspect conn |> Map.put(:params, attributes) end def call(%Conn{} = conn, _opts), do: conn + + defp parse_data(%{"data" => data}), do: data |> JaSerializer.Params.to_attributes + defp parse_data(%{}), do: %{} + + defp parse_included(%{"included" => included}, many_mappings) do + included |> Enum.reduce(%{}, fn (%{"data" => %{"type" => type}} = params, parsed) -> + attributes = params |> parse_data() + + case many_mappings |> Map.has_key?(type) do + true -> parsed |> Map.update(many_mappings[type], [attributes], &List.push(&1, attributes)) + false -> parsed |> Map.put(type, attributes) + end + end) + end + defp parse_included(%{}, _), do: %{} end diff --git a/lib/code_corps_web/views/message_view.ex b/lib/code_corps_web/views/message_view.ex index ba2aed161..70fb09376 100644 --- a/lib/code_corps_web/views/message_view.ex +++ b/lib/code_corps_web/views/message_view.ex @@ -7,4 +7,6 @@ defmodule CodeCorpsWeb.MessageView do has_one :author, type: "user", field: :author_id has_one :project, type: "project", field: :project_id + + has_many :conversations, serializer: CodeCorpsWeb.ConversationView, identifiers: :always end