Skip to content

Commit

Permalink
messages
Browse files Browse the repository at this point in the history
  • Loading branch information
ryuzaki committed Aug 1, 2021
1 parent b506efa commit 3004bd8
Show file tree
Hide file tree
Showing 10 changed files with 301 additions and 0 deletions.
2 changes: 2 additions & 0 deletions lib/felixir/auth/user.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ defmodule Felixir.Auth.User do

alias Felixir.Auth.User
alias Felixir.Chat.Room
alias Felixir.Chat.Message.Message

schema "users" do
field(:email, :string)
Expand All @@ -12,6 +13,7 @@ defmodule Felixir.Auth.User do
field(:username, :string)

has_many :rooms, Room
has_many :messages, Message

timestamps()
end
Expand Down
109 changes: 109 additions & 0 deletions lib/felixir/chat/message.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
defmodule Felixir.Chat.Message do
@moduledoc """
The Chat.Message context.
"""

import Ecto.Query, warn: false
alias Felixir.Repo

alias Felixir.Chat.Message.Message

@doc """
Returns the list of messages.
## Examples
iex> list_messages()
[%Message{}, ...]
"""
def list_messages(room_id) do
Repo.all(from(m in Message, where: m.room_id == ^room_id, preload: [:user, :room]))
end

@doc """
Gets a single message.
Raises `Ecto.NoResultsError` if the Message does not exist.
## Examples
iex> get_message!(123)
%Message{}
iex> get_message!(456)
** (Ecto.NoResultsError)
"""
def get_message!(id), do: Repo.get!(Message, id)

@doc """
Creates a message.
## Examples
iex> create_message(%{field: value})
{:ok, %Message{}}
iex> create_message(%{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
def create_message(attrs \\ %{}) do
%Message{}
|> Message.changeset(attrs)
|> Repo.insert()
end

@doc """
Updates a message.
## Examples
iex> update_message(message, %{field: new_value})
{:ok, %Message{}}
iex> update_message(message, %{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
def update_message(%Message{} = message, attrs) do
message
|> Message.changeset(attrs)
|> Repo.update()
end

@doc """
Deletes a message.
## Examples
iex> delete_message(message)
{:ok, %Message{}}
iex> delete_message(message)
{:error, %Ecto.Changeset{}}
"""
def delete_message(%Message{} = message) do
Repo.delete(message)
end

@doc """
Returns an `%Ecto.Changeset{}` for tracking message changes.
## Examples
iex> change_message(message)
%Ecto.Changeset{data: %Message{}}
"""
def change_message(%Message{} = message, attrs \\ %{}) do
Message.changeset(message, attrs)
end

def delete_message_by_id(message_id, user_id) do
from(m in Message, where: m.id == ^message_id and m.user_id == ^user_id)
|> Repo.delete_all()
end
end
24 changes: 24 additions & 0 deletions lib/felixir/chat/message/message.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
defmodule Felixir.Chat.Message.Message do
use Ecto.Schema
import Ecto.Changeset

alias Felixir.Auth.User
alias Felixir.Chat.Room

schema "messages" do
field :content, :string

belongs_to :user, User
belongs_to :room, Room

timestamps()
end

@doc false
def changeset(message, attrs) do
message
|> cast(attrs, [:content, :user_id, :room_id])
|> validate_required([:content, :user_id, :room_id])
|> validate_length(:content, min: 1)
end
end
3 changes: 3 additions & 0 deletions lib/felixir/chat/room.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,16 @@ defmodule Felixir.Chat.Room do
import Ecto.Changeset

alias Felixir.Auth.User
alias Felixir.Chat.Message.Message

schema "rooms" do
field :description, :string
field :name, :string

belongs_to :user, User

has_many :messages, Message

timestamps()
end

Expand Down
38 changes: 38 additions & 0 deletions lib/felixir_web/schema/resolvers/message_resolver.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
defmodule FelixirWeb.Schema.Resolvers.MessageResolver do
alias Felixir.Chat.Message
alias FelixirWeb.Utils
alias FelixirWeb.Constants

def delete_message(_, %{input: input}, %{context: context}) do
case Message.delete_message_by_id(input.message_id, context.current_user.id) do
{1, _} ->
{:ok, true}

{0, _} ->
{:error, Constants.not_found()}

_ ->
{:error, Constants.internal_server_error()}
end
end

def get_all_messages(_, %{input: input}, %{context: _context}) do
messages = Message.list_messages(input.room_id)
{:ok, messages}
end

def create_message(_, %{input: input}, %{context: context}) do
input_with_ids = Map.merge(input, %{user_id: context.current_user.id, room_id: input.room_id})

case Message.create_message(input_with_ids) do
{:ok, _message} ->
{:ok, true}

{:error, %Ecto.Changeset{} = changeset} ->
{:error, Utils.format_changeset_errors(changeset)}

_ ->
{:error, Constants.internal_server_error()}
end
end
end
18 changes: 18 additions & 0 deletions lib/felixir_web/schema/schema.ex
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ defmodule FelixirWeb.Schema do
field :rooms, list_of(:room_type) do
resolve(&Resolvers.RoomResolver.get_all_rooms/3)
end

@desc "Get all Message"
field :messages, list_of(:message_type) do
arg(:input, non_null(:list_messages_type))
resolve(&Resolvers.MessageResolver.get_all_messages/3)
end
end

mutation do
Expand All @@ -34,5 +40,17 @@ defmodule FelixirWeb.Schema do
arg(:input, non_null(:delete_room_input))
resolve(&Resolvers.RoomResolver.delete_room/3)
end

@desc "Create Message"
field :create_message, :boolean do
arg(:input, non_null(:message_input_type))
resolve(&Resolvers.MessageResolver.create_message/3)
end

@desc "Delete Message"
field :delete_message, :boolean do
arg(:input, non_null(:delete_message_input))
resolve(&Resolvers.MessageResolver.delete_message/3)
end
end
end
26 changes: 26 additions & 0 deletions lib/felixir_web/schema/types/message_type.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
defmodule FelixirWeb.Schema.Types.MessageType do
use Absinthe.Schema.Notation

object :message_type do
field :id, :id
field :user_id, :id
field :room_id, :id
field :user, :user_type
field :room, :room_type
field :content, :string
field :inserted_at, :string
end

input_object :list_messages_type do
field :room_id, non_null(:id)
end

input_object :message_input_type do
field :content, non_null(:string)
field :room_id, non_null(:id)
end

input_object :delete_message_input do
field :message_id, non_null(:id)
end
end
1 change: 1 addition & 0 deletions lib/felixir_web/schema/types/types.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ defmodule FelixirWeb.Schema.Types do

import_types(FelixirWeb.Schema.Types.UserType)
import_types(FelixirWeb.Schema.Types.RoomType)
import_types(FelixirWeb.Schema.Types.MessageType)
end
16 changes: 16 additions & 0 deletions priv/repo/migrations/20210801062011_create_messages.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
defmodule Felixir.Repo.Migrations.CreateMessages do
use Ecto.Migration

def change do
create table(:messages) do
add :content, :string, null: false
add :user_id, references(:users, on_delete: :delete_all), null: false
add :room_id, references(:rooms, on_delete: :delete_all), null: false

timestamps()
end

create index(:messages, [:user_id])
create index(:messages, [:room_id])
end
end
64 changes: 64 additions & 0 deletions test/felixir/chat/message_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
defmodule Felixir.Chat.MessageTest do
use Felixir.DataCase

alias Felixir.Chat.Message

describe "messages" do
alias Felixir.Chat.Message.Message

@valid_attrs %{content: "some content"}
@update_attrs %{content: "some updated content"}
@invalid_attrs %{content: nil}

def message_fixture(attrs \\ %{}) do
{:ok, message} =
attrs
|> Enum.into(@valid_attrs)
|> Message.create_message()

message
end

test "list_messages/0 returns all messages" do
message = message_fixture()
assert Message.list_messages() == [message]
end

test "get_message!/1 returns the message with given id" do
message = message_fixture()
assert Message.get_message!(message.id) == message
end

test "create_message/1 with valid data creates a message" do
assert {:ok, %Message{} = message} = Message.create_message(@valid_attrs)
assert message.content == "some content"
end

test "create_message/1 with invalid data returns error changeset" do
assert {:error, %Ecto.Changeset{}} = Message.create_message(@invalid_attrs)
end

test "update_message/2 with valid data updates the message" do
message = message_fixture()
assert {:ok, %Message{} = message} = Message.update_message(message, @update_attrs)
assert message.content == "some updated content"
end

test "update_message/2 with invalid data returns error changeset" do
message = message_fixture()
assert {:error, %Ecto.Changeset{}} = Message.update_message(message, @invalid_attrs)
assert message == Message.get_message!(message.id)
end

test "delete_message/1 deletes the message" do
message = message_fixture()
assert {:ok, %Message{}} = Message.delete_message(message)
assert_raise Ecto.NoResultsError, fn -> Message.get_message!(message.id) end
end

test "change_message/1 returns a message changeset" do
message = message_fixture()
assert %Ecto.Changeset{} = Message.change_message(message)
end
end
end

0 comments on commit 3004bd8

Please sign in to comment.