legendary-doc-site/apps/content/lib/content/slugs.ex

69 lines
1.7 KiB
Elixir
Raw Normal View History

defmodule Legendary.Content.Slugs do
2020-07-20 22:04:04 +00:00
@moduledoc """
Provides functions for working with post slugs and ensuring that they are unique.
"""
import Ecto.{Changeset, Query}
alias Legendary.Content.{Post, Repo}
2020-07-20 22:04:04 +00:00
def ensure_post_has_slug(changeset) do
cond do
2020-07-28 15:54:24 +00:00
!is_nil(changeset |> get_field(:name)) ->
2020-07-20 22:04:04 +00:00
changeset
2020-07-28 15:54:24 +00:00
is_nil(changeset |> get_field(:title)) ->
2020-07-20 22:04:04 +00:00
changeset
|> put_change(
2020-07-28 15:54:24 +00:00
:name,
2020-07-20 22:04:04 +00:00
changeset
2020-07-28 15:54:24 +00:00
|> get_field(:date)
2020-07-20 22:04:04 +00:00
|> Kernel.||(NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second))
|> Timex.format!("%F", :strftime)
|> Slugger.slugify_downcase()
|> unique_slug(changeset |> get_field(:id))
2020-07-20 22:04:04 +00:00
)
true ->
changeset
|> put_change(
2020-07-28 15:54:24 +00:00
:name,
2020-07-20 22:04:04 +00:00
changeset
2020-07-28 15:54:24 +00:00
|> get_field(:title)
2020-07-20 22:04:04 +00:00
|> Slugger.slugify_downcase()
|> unique_slug(changeset |> get_field(:id))
2020-07-20 22:04:04 +00:00
)
end
end
2020-07-28 15:54:24 +00:00
defp unique_slug(proposed_slug, id, postfix_number \\ 0) do
2020-07-20 22:04:04 +00:00
proposed_slug_with_postfix =
if postfix_number == 0 do
proposed_slug
else
"#{proposed_slug}-#{postfix_number}"
end
competition_count =
Repo.aggregate(
(
Post
2020-07-28 15:54:24 +00:00
|> where([post], post.name == ^proposed_slug_with_postfix)
|> post_id_match(id)
2020-07-20 22:04:04 +00:00
),
:count,
:id
2020-07-20 22:04:04 +00:00
)
if competition_count == 0 do
proposed_slug_with_postfix
else
2020-07-28 15:54:24 +00:00
unique_slug(proposed_slug, id, postfix_number + 1)
2020-07-20 22:04:04 +00:00
end
end
defp post_id_match(query, nil) do
query
end
defp post_id_match(query, id) when is_number(id) do
from p in query, where: p.id != ^id
2020-07-20 22:04:04 +00:00
end
end