Skip to content

Commit ff5f664

Browse files
committed
add follow relationships
1 parent cbb0b61 commit ff5f664

File tree

7 files changed

+93
-0
lines changed

7 files changed

+93
-0
lines changed
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
defmodule Algora.Accounts.Follow do
2+
@moduledoc false
3+
use Algora.Schema
4+
5+
alias Algora.Accounts.User
6+
7+
typed_schema "follows" do
8+
belongs_to :follower, User, foreign_key: :follower_id, type: :string
9+
belongs_to :followed, User, foreign_key: :followed_id, type: :string
10+
11+
field :provider, :string, default: "github"
12+
field :provider_created_at, :utc_datetime_usec
13+
14+
timestamps()
15+
end
16+
17+
def changeset(follow, attrs) do
18+
follow
19+
|> cast(attrs, [:follower_id, :followed_id, :provider, :provider_created_at])
20+
|> validate_required([:follower_id, :followed_id, :provider])
21+
|> generate_id()
22+
|> unique_constraint([:follower_id, :followed_id], name: :follows_follower_id_followed_id_index)
23+
|> foreign_key_constraint(:follower_id)
24+
|> foreign_key_constraint(:followed_id)
25+
|> validate_not_self_follow()
26+
end
27+
28+
defp validate_not_self_follow(changeset) do
29+
follower_id = get_field(changeset, :follower_id)
30+
followed_id = get_field(changeset, :followed_id)
31+
32+
if follower_id && followed_id && follower_id == followed_id do
33+
add_error(changeset, :followed_id, "cannot follow yourself")
34+
else
35+
changeset
36+
end
37+
end
38+
end

lib/algora/accounts/schemas/user.ex

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ defmodule Algora.Accounts.User do
22
@moduledoc false
33
use Algora.Schema
44

5+
alias Algora.Accounts.Follow
56
alias Algora.Accounts.Identity
67
alias Algora.Accounts.User
78
alias Algora.Accounts.UserMedia
@@ -37,6 +38,8 @@ defmodule Algora.Accounts.User do
3738
field :country, :string
3839
field :timezone, :string
3940
field :stargazers_count, :integer, default: 0
41+
field :followers_count, :integer, default: 0
42+
field :following_count, :integer, default: 0
4043
field :domain, :string
4144
field :tech_stack, {:array, :string}, default: []
4245
field :discovery_tech_stack, {:array, :string}, default: []
@@ -170,6 +173,11 @@ defmodule Algora.Accounts.User do
170173
has_many :media, UserMedia
171174
has_many :job_matches, Algora.Matches.JobMatch, foreign_key: :user_id
172175

176+
has_many :following_relationships, Follow, foreign_key: :follower_id
177+
has_many :following, through: [:following_relationships, :followed]
178+
has_many :follower_relationships, Follow, foreign_key: :followed_id
179+
has_many :followers, through: [:follower_relationships, :follower]
180+
173181
timestamps()
174182
end
175183

lib/algora/integrations/github/behaviour.ex

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,6 @@ defmodule Algora.Github.Behaviour do
3838
@callback remove_label(token(), String.t(), String.t(), String.t()) :: {:ok, map()} | {:error, String.t()}
3939
@callback remove_label_from_issue(token(), String.t(), String.t(), integer(), String.t()) ::
4040
{:ok, map()} | {:error, String.t()}
41+
@callback list_user_followers(token(), String.t(), keyword()) :: {:ok, [map()]} | {:error, String.t()}
42+
@callback list_user_following(token(), String.t(), keyword()) :: {:ok, [map()]} | {:error, String.t()}
4143
end

lib/algora/integrations/github/client.ex

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,4 +329,14 @@ defmodule Algora.Github.Client do
329329
res
330330
end
331331
end
332+
333+
@impl true
334+
def list_user_followers(access_token, username, opts \\ []) do
335+
fetch(access_token, "/users/#{username}/followers#{build_query(opts)}")
336+
end
337+
338+
@impl true
339+
def list_user_following(access_token, username, opts \\ []) do
340+
fetch(access_token, "/users/#{username}/following#{build_query(opts)}")
341+
end
332342
end

lib/algora/integrations/github/github.ex

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,4 +164,10 @@ defmodule Algora.Github do
164164
@impl true
165165
def remove_label_from_issue(token, owner, repo, number, label),
166166
do: client().remove_label_from_issue(token, owner, repo, number, label)
167+
168+
@impl true
169+
def list_user_followers(token, username, opts \\ []), do: client().list_user_followers(token, username, opts)
170+
171+
@impl true
172+
def list_user_following(token, username, opts \\ []), do: client().list_user_following(token, username, opts)
167173
end
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
defmodule Algora.Repo.Migrations.CreateFollows do
2+
use Ecto.Migration
3+
4+
def change do
5+
create table(:follows, primary_key: false) do
6+
add :id, :string, primary_key: true
7+
add :follower_id, references(:users, on_delete: :delete_all, type: :string), null: false
8+
add :followed_id, references(:users, on_delete: :delete_all, type: :string), null: false
9+
add :provider, :string, null: false, default: "github"
10+
add :provider_created_at, :utc_datetime_usec
11+
12+
timestamps()
13+
end
14+
15+
create unique_index(:follows, [:follower_id, :followed_id])
16+
create index(:follows, [:follower_id])
17+
create index(:follows, [:followed_id])
18+
end
19+
end
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
defmodule Algora.Repo.Migrations.AddFollowersFollowingToUsers do
2+
use Ecto.Migration
3+
4+
def change do
5+
alter table(:users) do
6+
add :followers_count, :integer, default: 0
7+
add :following_count, :integer, default: 0
8+
end
9+
end
10+
end

0 commit comments

Comments
 (0)