Creating an Elixir library for Spell Checking
Published: 2024-01-07 19:48:24

Instead of directly incorporating my [simple spell checking code](https://dev.to/byronsalty/creating-an-efficient-spellchecker-in-elixir-5a8d) into my project, why not turn this into a library that I could more easily use in other places as well as share publicly.

I know that some other libraries exist but none appear to be a standard, and since I'm really doing this as an experiment forgive me for re-inventing the wheel a bit.

I'm following this [official guide for creating a library](https://hexdocs.pm/elixir/main/library-guidelines.html#content).

---

# Create a Project

Let's start with simply creating a new library.

```
$ mix new spell_chex
```

I prefer an evolutionary and iterative style of development so before I worry about the complexity of a `GenServer` in my final spell checker build, I'll create the project with the naive implementation ([discussed previously](https://dev.to/byronsalty/creating-an-efficient-spellchecker-in-elixir-5a8d)) and make sure I can create the library and then use the library in my host application.

Let's be good citizens and add some docs too:

```
defmodule SpellChex do
  @moduledoc """
  Module used to invoke SpellChex.
  """
  @moduledoc since: "1.0.0"

  @sample_words ["hello", "world", "elixir", "phoenix", "spell", "check", "dog", "cat"]


  @doc """
  Determines if a given `word` is in the list of known words.

  Returns `true` or `false`.

  ## Examples

      iex> SpellChex.exists?("dog")
      true

      iex> SpellChex.exists?("asdfas")
      false

  """
  @doc since: "1.3.0"
  def exists?(word) do
    # GenServer.call(__MODULE__, {:check_exists, word})
    word in @sample_words
  end
end
```

In order to get our docs to create we need at add the `ex_doc` dependency to our `mix.exs`.

```
  defp deps do
    [
      {:ex_doc, "~> 0.31", only: :dev, runtime: false}
    ]
```

And let's test out those docs. (More on running [docs locally here](https://dev.to/byronsalty/use-hexdocs-locally-19m3).)
```
mix deps.get
mix docs
cd doc
caddy file-server --browse --listen :5051
```

That should be it for the naive implementation. Now let's figure out how to build it locally and use it in our host project.

---

# Consume the library locally

Eventually we will want to push our local code to github and publish on Hex, but why worry about publishing every time you want to test something out locally?

First thing to do is to update your host project to reference your new library with the `path` option:
```
  defp deps do
    [
      ...
      {:spell_chex, path: "../spell_chex"},
```

Grab your deps again (`mix deps.get`) and now you can start using the library:
```
iex(1)> SpellChex.exists?("dog")
true
```

![That was almost too easy](https://y.yarn.co/d99f3420-18c7-4673-9680-290a62124e2d_text.gif)

---

# Configure the Library

Since the library relies on a `GenServer` to create a dictionary of words we need to add our dictionary to the host application's start-up.

Update `children` in `lib/<host>/application.ex`:
```
 def start(_type, _args) do

    children = [
      ...
      SpellChex.Dictionary,
      ...
    ]
```

Now you should be able to start your host mix app and test it out:
```
iex -S mix
...

iex(1)> SpellChex.exists?("dog")
true
iex(2)> SpellChex.exists?("blahblah")
false
iex(3)> SpellChex.exists?("bonsai")  
true
```

---

# Publish via Github

You could simply push your latest to main and then reference your library from the host app's `mix.exs` like this

```
      {:spell_chex, git: "https://github.com/byronsalty/spell_chex"},
```

But you may want to still utilize versioning. If so you'd tag in get like this:

```
git tag -a "0.0.1"
git push origin 0.0.1
# or
git push origin --tags
```

Then you can use the version in the `mix.exs`:
```
      {:spell_chex, git: "https://github.com/byronsalty/spell_chex", tag: "0.0.1"},
```

---

# Publish to Hex

But maybe you want to make your library truly global...

Following this guide to publishing to Hex:
https://hex.pm/docs/publish

Highlights: 
1. Setup your [hex account](https://hex.pm/docs/publish#registering-a-hex-user).
1. Add all of the [required metadata](https://hex.pm/docs/publish#adding-metadata-to-code-classinlinemixexscode).
1. Make sure your docs build.
1. Publish! `mix hex.publish`

Now you can use the standard `mix.exs` dependency style:
```
      {:spell_chex, "~> 0.0.1"},
```


Happy Coding!

---

If you found this article helpful, show your support with a Like, Comment, or Follow.

Read more of Byron’s articles about [Leadership](https://byronsalty.medium.com/list/leadership-37d7992c55ba) and [AI](https://byronsalty.medium.com/list/my-ai-dc4873d307bf).

Development articles [here](https://dev.to/byronsalty).

Follow on [Medium](https://byronsalty.medium.com/), [Dev.to](https://dev.to/byronsalty), [Twitter](https://twitter.com/byronsalty), or [LinkedIn](https://www.linkedin.com/in/byronsalty/).