philomena/lib/philomena/conversations/conversation.ex
2024-07-09 21:20:00 -04:00

81 lines
2 KiB
Elixir

defmodule Philomena.Conversations.Conversation do
use Ecto.Schema
import Ecto.Changeset
alias Philomena.Users.User
alias Philomena.Conversations.Message
alias Philomena.Repo
@derive {Phoenix.Param, key: :slug}
schema "conversations" do
belongs_to :from, User
belongs_to :to, User
has_many :messages, Message
field :title, :string
field :to_read, :boolean, default: false
field :from_read, :boolean, default: true
field :to_hidden, :boolean, default: false
field :from_hidden, :boolean, default: false
field :slug, :string
field :last_message_at, :utc_datetime
field :recipient, :string, virtual: true
timestamps(inserted_at: :created_at, type: :utc_datetime)
end
@doc false
def changeset(conversation, attrs) do
conversation
|> cast(attrs, [])
|> validate_required([])
end
def read_changeset(conversation, attrs) do
conversation
|> cast(attrs, [:from_read, :to_read])
end
def to_read_changeset(conversation) do
change(conversation)
|> put_change(:to_read, true)
end
def hidden_changeset(conversation, attrs) do
conversation
|> cast(attrs, [:from_hidden, :to_hidden])
end
@doc false
def creation_changeset(conversation, from, attrs) do
conversation
|> cast(attrs, [:title, :recipient])
|> validate_required([:title, :recipient])
|> validate_length(:title, max: 300, count: :bytes)
|> put_assoc(:from, from)
|> put_recipient()
|> set_slug()
|> set_last_message()
|> cast_assoc(:messages, with: &Message.creation_changeset(&1, &2, from))
|> validate_length(:messages, is: 1)
end
defp set_slug(changeset) do
changeset
|> change(slug: Ecto.UUID.generate())
end
defp set_last_message(changeset) do
change(changeset, last_message_at: DateTime.utc_now(:second))
end
defp put_recipient(changeset) do
recipient = changeset |> get_field(:recipient)
user = Repo.get_by(User, name: recipient)
changeset
|> put_change(:to, user)
|> validate_required(:to)
end
end