51 lines
1.2 KiB
Elixir
51 lines
1.2 KiB
Elixir
|
|
defmodule Zoeyscomputer.IdGenerator do
|
||
|
|
@moduledoc """
|
||
|
|
Generates URL-friendly unique IDs
|
||
|
|
"""
|
||
|
|
|
||
|
|
@alphabet "_-0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||
|
|
@size 7
|
||
|
|
|
||
|
|
@doc """
|
||
|
|
Generates a random ID with default length of 7 characters using URL-friendly characters.
|
||
|
|
|
||
|
|
## Examples
|
||
|
|
iex> IdGenerator.generate()
|
||
|
|
"f3k9m4z"
|
||
|
|
"""
|
||
|
|
def generate(size \\ @size) do
|
||
|
|
alphabet_length = String.length(@alphabet)
|
||
|
|
|
||
|
|
1..size
|
||
|
|
|> Enum.reduce([], fn _, acc ->
|
||
|
|
position = :rand.uniform(alphabet_length) - 1
|
||
|
|
char = String.at(@alphabet, position)
|
||
|
|
[char | acc]
|
||
|
|
end)
|
||
|
|
|> Enum.join("")
|
||
|
|
end
|
||
|
|
|
||
|
|
@doc """
|
||
|
|
Generates a random ID and ensures it's unique by checking against a provided function.
|
||
|
|
|
||
|
|
## Examples
|
||
|
|
iex> IdGenerator.generate_unique(&MyApp.id_exists?/1)
|
||
|
|
"x7k9m4z"
|
||
|
|
"""
|
||
|
|
def generate_unique(exists_fn, attempts \\ 0)
|
||
|
|
|
||
|
|
def generate_unique(exists_fn, attempts) when attempts < 5 do
|
||
|
|
id = generate()
|
||
|
|
|
||
|
|
if exists_fn.(id) do
|
||
|
|
generate_unique(exists_fn, attempts + 1)
|
||
|
|
else
|
||
|
|
id
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
def generate_unique(_exists_fn, _attempts) do
|
||
|
|
raise "Failed to generate unique ID after 5 attempts"
|
||
|
|
end
|
||
|
|
end
|