Packages
phoenix_kit
1.7.80
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
Current section
Files
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
- `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
alias PhoenixKit.Utils.Date, as: UtilsDate
@primary_key {:uuid, UUIDv7, autogenerate: true}
@type t :: %__MODULE__{
uuid: UUIDv7.t() | nil,
follower_uuid: UUIDv7.t(),
followed_uuid: UUIDv7.t(),
follower: PhoenixKit.Users.Auth.User.t() | Ecto.Association.NotLoaded.t(),
followed: PhoenixKit.Users.Auth.User.t() | Ecto.Association.NotLoaded.t(),
inserted_at: DateTime.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 :inserted_at, :utc_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
## 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])
|> 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,
UtilsDate.utc_now()
)
end
end
end