# AshSqids
[![Module Version](https://img.shields.io/hexpm/v/ash_sqids)](https://hex.pm/packages/ash_sqids)
[![Hex Docs](https://img.shields.io/badge/hex-docs-lightgreen)](https://hexdocs.pm/ash_sqids/)
[![License](https://img.shields.io/hexpm/l/ash_sqids)](https://github.com/vonagam/ash_sqids/blob/master/LICENSE.md)
[Sqids](https://sqids.org/) type for [Ash](https://ash-hq.org/) framework.
For what are Sqids and why would you want to use them I recommend looking at the linked website. But basically it is a pretty presentation for integer type. You might prefer having url like `/rooms/DcHPs` over `/rooms/151` or `/rooms/48922bf6-c418-4023-a478-0cca4dd04e68`.
The library consists of a single module `AshSqids.Type` that provides `Ash.Type` implementation.
## Installation
Add to the deps, get deps (`mix deps.get`), compile them (`mix deps.compile`).
```elixir
def deps do
[
{:ash_sqids, "~> 0.0.1"},
]
end
```
## Usage
Define a module that will represent a Sqid type and `use AshSqids.Type` in it. Provide configuration for it in `config :ash_sqids, :opts`. And then use it as type in attributes and arguments.
```elixir
# lib/example/posts/resources/comment.ex
defmodule Example.Posts.Comment do
use Ash.Resource, data_layer: AshPostgres.DataLayer
# 1) define a type module
defmodule Id, do: use(AshSqids.Type)
attributes do
# 2) use it as an attribute type
integer_primary_key :id, type: Id
# ...
end
relationships do
# 3) use as `attribute_type` in `belongs_to` like this
belongs_to :post, Example.Posts.Post, attribute_type: Example.Posts.Post.Id
end
end
```
### Primary key
As shown if you want to use it as a primary key (main use case) then add `integer_primary_key` with `type` option.
And don't forget `attribute_type` in `belongs_to` for references to a resource with sqids.
### Config
Here is how mentioned config is supposed to look:
```elixir
# config/config.exs
import Config
config :ash_sqids, :opts, [
{Example.Posts.Comment.Id, []}, # use default options
{Example.Posts.Post.Id, min_length: 7} # some custom values
]
```
Options are passed into `Sqids.new!` and at the time of writing there are three options there -
`alphabet`, `min_length` and `blocklist`.
It is better to provide alphabet. It can be a default one - `abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789` - but just shuffled.
`use AshSqids.Type` accepts optional `config` option that allows you to reuse configurations.
So if in the example we wanted for comments ids and posts ids to be in the same style then we could do it like this:
```elixir
# `config` is an atom (defaulting to a module name) that will be used as a key
# to look up Sqids options from `config :ash_sqids, :opts`
defmodule Id, do: use(AshSqids.Type, config: Example.Posts.Post.Id)
```
### Protocols
`AshSqids.Type` provides implementation for following protocols:
- `String.Chars` - so `"#{id}"` results in a sqid string.
- `Jason.Encoder` - same, returns a sqid string.
- `Inspect` - with the format of `#Example.Posts.Comment.Id<1, "Uk">`.
## References
Sqids - [website](https://sqids.org/), [github](https://github.com/sqids), [elixir library](https://github.com/sqids/sqids-elixir).
Ash - [website](https://ash-hq.org/), [github](https://github.com/ash-project), [`Ash.Type` docs](https://hexdocs.pm/ash/Ash.Type.html).