Packages

phoenix_kit

1.7.39
1.7.209 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 connections follow.ex
Raw

lib/modules/connections/follow.ex

defmodule PhoenixKit.Modules.Connections.Follow do
@moduledoc """
Schema for one-way follow relationships.
Represents a unidirectional relationship where one user follows another.
No consent is required from the followed user.
## Fields
- `follower_uuid` - UUID of the user who is doing the following
- `followed_uuid` - UUID of the user being followed
- `follower_id` - Integer ID (deprecated, dual-write only)
- `followed_id` - Integer ID (deprecated, dual-write only)
- `inserted_at` - When the follow was created
## Examples
# User A follows User B
%Follow{
uuid: "018e3c4a-9f6b-7890-abcd-ef1234567890",
follower_uuid: "019abc12-3456-7890-abcd-ef1234567890",
followed_uuid: "019abc12-9876-5432-abcd-ef1234567890",
inserted_at: ~N[2025-01-15 10:30:00]
}
## Business Rules
- Cannot follow yourself
- Cannot follow if blocked (either direction)
- Duplicate follows are prevented by unique constraint
"""
use Ecto.Schema
import Ecto.Changeset
@primary_key {:uuid, UUIDv7, autogenerate: true, source: :id}
@type t :: %__MODULE__{
uuid: UUIDv7.t() | nil,
follower_uuid: UUIDv7.t(),
followed_uuid: UUIDv7.t(),
follower_id: integer() | nil,
followed_id: integer() | nil,
follower: PhoenixKit.Users.Auth.User.t() | Ecto.Association.NotLoaded.t(),
followed: PhoenixKit.Users.Auth.User.t() | Ecto.Association.NotLoaded.t(),
inserted_at: NaiveDateTime.t() | nil
}
schema "phoenix_kit_user_follows" do
belongs_to :follower, PhoenixKit.Users.Auth.User,
foreign_key: :follower_uuid,
references: :uuid,
type: UUIDv7
belongs_to :followed, PhoenixKit.Users.Auth.User,
foreign_key: :followed_uuid,
references: :uuid,
type: UUIDv7
field :follower_id, :integer
field :followed_id, :integer
field :inserted_at, :naive_datetime
end
@doc """
Changeset for creating a follow relationship.
## Required Fields
- `follower_uuid` - UUID of the user who is following
- `followed_uuid` - UUID of the user being followed
## Optional Fields (dual-write)
- `follower_id` - Integer ID (deprecated)
- `followed_id` - Integer ID (deprecated)
## Validation Rules
- Both user UUIDs are required
- Cannot follow yourself (follower_uuid != followed_uuid)
- Unique constraint on (follower_uuid, followed_uuid) pair
"""
def changeset(follow, attrs) do
follow
|> cast(attrs, [:follower_uuid, :followed_uuid, :follower_id, :followed_id])
|> validate_required([:follower_uuid, :followed_uuid])
|> validate_not_self_follow()
|> put_inserted_at()
|> foreign_key_constraint(:follower_uuid)
|> foreign_key_constraint(:followed_uuid)
|> unique_constraint([:follower_uuid, :followed_uuid],
name: :phoenix_kit_user_follows_unique_idx,
message: "already following this user"
)
end
defp validate_not_self_follow(changeset) do
follower_uuid = get_field(changeset, :follower_uuid)
followed_uuid = get_field(changeset, :followed_uuid)
if follower_uuid && followed_uuid && follower_uuid == followed_uuid do
add_error(changeset, :followed_uuid, "cannot follow yourself")
else
changeset
end
end
defp put_inserted_at(changeset) do
if get_field(changeset, :inserted_at) do
changeset
else
put_change(
changeset,
:inserted_at,
NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second)
)
end
end
end