Skip to content

Instantly share code, notes, and snippets.

@rstacruz
Created July 14, 2016 08:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rstacruz/3cb2f806c6325fc7be75e420a7e70030 to your computer and use it in GitHub Desktop.
Save rstacruz/3cb2f806c6325fc7be75e420a7e70030 to your computer and use it in GitHub Desktop.
defmodule SlugGenerator do
@moduledoc """
Generates random slugs.
def changeset(model, params \\ %{}) do
model
|> cast(params, @fields)
|> SlugGenerator.generate_slug(Article, :slug, to_slug(changeset))
end
@doc "Returns the slug candidate."
def to_slug(changeset) do
changeset |> get_field(:name)
end
"""
@doc """
Generates a slug.
* `:scope` - the scope to look for slug collisions. Usually just the model.
* `:field` - the field te put the slug into.
* `:slug` - the string to be slugified.
"""
def generate_slug(changeset, scope, field, slug) do
slug = slugify(slug)
case Repo.get_by(scope, [{field, slug}]) do
nil ->
changeset
|> Ecto.Changeset.put_change(field, slug)
_ ->
changeset
|> generate_random_slug(scope, field, slug)
end
end
@doc """
Generates a slug with a random number.
"""
def generate_random_slug(changeset, scope, field, slug) do
new_slug = "#{slug}-#{random_number}"
case Repo.get_by(scope, [{field, new_slug}]) do
nil ->
changeset
|> Ecto.Changeset.put_change(field, new_slug)
_ ->
changeset
|> generate_random_slug(scope, field, slug)
end
end
@doc """
Turns a string into a slug.
iex> SlugGenerator.slugify("Hello, world!")
"hello-world"
"""
def slugify(string) do
string
|> String.downcase
|> String.replace(~r/[^A-Za-z0-9]+/, " ")
|> String.trim
|> String.replace(" ", "-")
end
@doc """
Generates a random number.
"""
def random_number do
:erlang.phash2(make_ref, 10_000)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment