Packages

phoenix_kit

1.7.53
1.7.208 1.7.207 1.7.206 1.7.205 1.7.204 1.7.203 1.7.202 1.7.201 1.7.200 1.7.199 1.7.198 1.7.197 1.7.196 1.7.194 1.7.193 1.7.192 1.7.191 1.7.190 1.7.189 1.7.187 1.7.186 1.7.185 1.7.184 1.7.183 1.7.182 1.7.181 1.7.180 1.7.179 1.7.178 1.7.177 1.7.176 1.7.175 1.7.174 1.7.173 1.7.172 1.7.171 1.7.170 1.7.169 1.7.168 1.7.167 1.7.166 1.7.165 1.7.164 1.7.162 1.7.161 1.7.160 1.7.159 1.7.157 1.7.156 1.7.155 1.7.154 1.7.153 1.7.152 1.7.151 1.7.150 1.7.149 1.7.146 1.7.145 1.7.144 1.7.143 1.7.138 1.7.133 1.7.132 1.7.131 1.7.130 1.7.128 1.7.126 1.7.125 1.7.121 1.7.120 1.7.119 1.7.118 1.7.117 1.7.116 1.7.115 1.7.114 1.7.113 1.7.112 1.7.111 1.7.110 1.7.109 1.7.108 1.7.107 1.7.106 1.7.105 1.7.104 1.7.103 1.7.102 1.7.101 1.7.100 1.7.99 1.7.98 1.7.97 1.7.96 1.7.95 1.7.94 1.7.93 1.7.92 1.7.91 1.7.90 1.7.89 1.7.88 1.7.87 1.7.86 1.7.85 1.7.84 1.7.83 1.7.82 1.7.81 1.7.80 1.7.79 1.7.78 1.7.77 1.7.76 1.7.75 1.7.74 1.7.71 1.7.70 1.7.69 1.7.66 1.7.65 1.7.64 1.7.63 1.7.62 1.7.61 1.7.59 1.7.58 1.7.57 1.7.56 1.7.55 1.7.54 1.7.53 1.7.52 1.7.51 1.7.49 1.7.44 1.7.43 1.7.42 1.7.41 1.7.39 1.7.38 1.7.37 1.7.36 1.7.34 1.7.33 1.7.31 1.7.30 1.7.29 1.7.28 1.7.27 1.7.26 1.7.25 1.7.24 1.7.23 1.7.22 1.7.21 1.7.20 1.7.19 1.7.18 1.7.17 1.7.16 1.7.15 1.7.14 1.7.13 1.7.12 1.7.11 1.7.10 1.7.9 1.7.8 1.7.7 1.7.6 1.7.5 1.7.4 1.7.3 1.7.2 1.7.1 1.7.0 1.6.20 1.6.19 1.6.18 1.6.17 1.6.16 1.6.15 1.6.14 1.6.13 1.6.12 1.6.11 1.6.10 1.6.9 1.6.8 1.6.7 1.6.6 1.6.5 1.6.4 1.6.3 1.5.2 1.5.1 1.5.0 1.4.9 1.4.8 1.4.7 1.4.6 1.4.5 1.4.4 1.4.3 1.4.2 1.4.1 1.4.0 1.3.2 1.3.1 1.3.0 1.2.10 1.2.9 1.2.8 1.2.7 1.2.5 1.2.4 1.2.2 1.2.1 1.2.0 1.1.0 1.0.0

A foundation for building Elixir Phoenix apps — SaaS, social networks, ERP systems, marketplaces, and more

Current section

Files

Jump to
phoenix_kit lib modules comments schemas comment.ex
Raw

lib/modules/comments/schemas/comment.ex

defmodule PhoenixKit.Modules.Comments.Comment do
@moduledoc """
Schema for polymorphic comments with unlimited threading depth.
Supports nested comment threads (Reddit-style) with self-referencing parent/child
relationships. Can be attached to any resource type via `resource_type` + `resource_uuid`.
## Comment Status
- `published` - Comment is visible
- `hidden` - Comment is hidden by moderator
- `deleted` - Comment deleted (soft delete)
- `pending` - Awaiting moderation approval
## Fields
- `resource_type` - Type of resource (e.g., "post", "entity", "ticket")
- `resource_uuid` - UUID of the resource
- `user_uuid` - Reference to the commenter
- `parent_uuid` - Reference to parent comment (nil for top-level)
- `content` - Comment text
- `status` - published/hidden/deleted/pending
- `depth` - Nesting level (0=top, 1=reply, 2=reply-to-reply, etc.)
- `like_count` - Denormalized like counter
- `dislike_count` - Denormalized dislike counter
"""
use Ecto.Schema
import Ecto.Changeset
@primary_key {:uuid, UUIDv7, autogenerate: true, source: :id}
@type t :: %__MODULE__{
uuid: UUIDv7.t() | nil,
resource_type: String.t(),
resource_uuid: Ecto.UUID.t(),
user_uuid: UUIDv7.t() | nil,
parent_uuid: UUIDv7.t() | nil,
content: String.t(),
status: String.t(),
depth: integer(),
like_count: integer(),
dislike_count: integer(),
user: PhoenixKit.Users.Auth.User.t() | Ecto.Association.NotLoaded.t() | nil,
parent: t() | Ecto.Association.NotLoaded.t() | nil,
children: [t()] | Ecto.Association.NotLoaded.t(),
inserted_at: DateTime.t() | nil,
updated_at: DateTime.t() | nil
}
schema "phoenix_kit_comments" do
field :resource_type, :string
field :resource_uuid, Ecto.UUID
field :content, :string
field :status, :string, default: "published"
field :depth, :integer, default: 0
field :like_count, :integer, default: 0
field :dislike_count, :integer, default: 0
belongs_to :user, PhoenixKit.Users.Auth.User,
foreign_key: :user_uuid,
references: :uuid,
type: UUIDv7
belongs_to :parent, __MODULE__,
foreign_key: :parent_uuid,
references: :uuid,
type: UUIDv7
has_many :children, __MODULE__, foreign_key: :parent_uuid
timestamps(type: :utc_datetime)
end
@doc """
Changeset for creating or updating a comment.
## Required Fields
- `resource_type` - Type of resource being commented on
- `resource_uuid` - UUID of the resource
- `user_uuid` - Reference to commenter
- `content` - Comment text
"""
def changeset(comment, attrs) do
comment
|> cast(attrs, [
:resource_type,
:resource_uuid,
:user_uuid,
:parent_uuid,
:content,
:status,
:depth
])
|> validate_required([:resource_type, :resource_uuid, :user_uuid, :content])
|> validate_inclusion(:status, ["published", "hidden", "deleted", "pending"])
|> validate_length(:content, min: 1, max: 10_000)
|> validate_length(:resource_type, max: 50)
|> foreign_key_constraint(:user_uuid)
|> foreign_key_constraint(:parent_uuid)
end
@doc "Check if comment is a reply (has parent)."
def reply?(%__MODULE__{parent_uuid: nil}), do: false
def reply?(%__MODULE__{}), do: true
@doc "Check if comment is top-level (no parent)."
def top_level?(%__MODULE__{parent_uuid: nil}), do: true
def top_level?(%__MODULE__{}), do: false
@doc "Check if comment is published."
def published?(%__MODULE__{status: "published"}), do: true
def published?(_), do: false
@doc "Check if comment is deleted."
def deleted?(%__MODULE__{status: "deleted"}), do: true
def deleted?(_), do: false
end