From 1a1f2a7008bc0a9d3783d51c24a69cacad0c7712 Mon Sep 17 00:00:00 2001 From: Sloane Date: Fri, 7 Jul 2023 14:38:26 -0400 Subject: [PATCH] `Jason.Encoder` impl (#18) --- CHANGELOG.md | 5 +++++ README.md | 2 +- lib/type_id.ex | 14 +++++++++++--- mix.exs | 6 ++++-- mix.lock | 1 + test/type_id/jason_encoder_test.exs | 19 +++++++++++++++++++ test/type_id/phoenix_html_safe_test.exs | 2 +- test/type_id/spec_test.exs | 2 +- test/type_id/string_char_test.exs | 2 +- test/type_id_test.exs | 2 +- 10 files changed, 45 insertions(+), 10 deletions(-) create mode 100644 test/type_id/jason_encoder_test.exs diff --git a/CHANGELOG.md b/CHANGELOG.md index f13e939..09947f0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## 0.4.0 + +- Implements `Jason.Encoder` protocol +- **BREAKING:** The `_` seperator is no longer encoded as a binary when returned by `TypeID.to_iodata/1` or protocols that use that function. This is unlikely to matter unless you are pattern matching on the shape of the returned iodata. + ## 0.3.1 - Implements `String.Chars` protocol diff --git a/README.md b/README.md index ebf068f..1edf43e 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ The package can be installed from [hex](https://hex.pm/packages/typeid_elixir) b ```elixir def deps do [ - {:typeid_elixir, "~> 0.3.1"} + {:typeid_elixir, "~> 0.4.0"} ] end ``` diff --git a/lib/type_id.ex b/lib/type_id.ex index c454478..cece53c 100644 --- a/lib/type_id.ex +++ b/lib/type_id.ex @@ -15,6 +15,8 @@ defmodule TypeID do suffix: String.t() } + @seperator ?_ + @doc """ Generates a new `t:t/0` with the given prefix. @@ -74,7 +76,7 @@ defmodule TypeID do iex> tid = TypeID.from_string!("player_01h4rn40ybeqws3gfp073jt81b") iex> TypeID.to_iodata(tid) - ["player", "_", "01h4rn40ybeqws3gfp073jt81b"] + ["player", ?_, "01h4rn40ybeqws3gfp073jt81b"] iex> tid = TypeID.from_string!("01h4rn40ybeqws3gfp073jt81b") @@ -88,7 +90,7 @@ defmodule TypeID do end def to_iodata(%__MODULE__{prefix: prefix, suffix: suffix}) do - [prefix, "_", suffix] + [prefix, @seperator, suffix] end @doc """ @@ -173,7 +175,7 @@ defmodule TypeID do """ @spec from_string!(String.t()) :: t() | no_return() def from_string!(str) do - case String.split(str, "_") do + case String.split(str, <<@seperator>>) do [prefix, suffix] when prefix != "" -> from!(prefix, suffix) @@ -374,3 +376,9 @@ if Code.ensure_loaded?(Phoenix.Param) do defdelegate to_param(tid), to: TypeID, as: :to_string end end + +if Code.ensure_loaded?(Jason.Encoder) do + defimpl Jason.Encoder, for: TypeID do + def encode(tid, _opts), do: [?", TypeID.to_iodata(tid), ?"] + end +end diff --git a/mix.exs b/mix.exs index 43c367b..31c818e 100644 --- a/mix.exs +++ b/mix.exs @@ -1,7 +1,7 @@ defmodule TypeID.MixProject do use Mix.Project - @version "0.3.1" + @version "0.4.0" def project do [ @@ -14,7 +14,8 @@ defmodule TypeID.MixProject do deps: deps(), name: "TypeID Elixir", source_url: "https://github.com/sloanelybutsurely/typeid-elixir", - docs: docs() + docs: docs(), + consolidate_protocols: Mix.env() != :test ] end @@ -45,6 +46,7 @@ defmodule TypeID.MixProject do {:ecto, "~> 3.10", only: [:dev, :test], optional: true}, {:phoenix_html, "~> 3.3", only: [:dev, :test], optional: true}, {:phoenix, "~> 1.7", only: [:dev, :test], optional: true}, + {:jason, "~> 1.4", only: [:dev, :test], optional: true}, {:ex_doc, "~> 0.27", only: :dev, runtime: false}, {:yaml_elixir, "~> 2.9", only: [:dev, :test], runtime: false} ] diff --git a/mix.lock b/mix.lock index 009b2be..e449106 100644 --- a/mix.lock +++ b/mix.lock @@ -4,6 +4,7 @@ "earmark_parser": {:hex, :earmark_parser, "1.4.32", "fa739a0ecfa34493de19426681b23f6814573faee95dfd4b4aafe15a7b5b32c6", [:mix], [], "hexpm", "b8b0dd77d60373e77a3d7e8afa598f325e49e8663a51bcc2b88ef41838cca755"}, "ecto": {:hex, :ecto, "3.10.2", "6b887160281a61aa16843e47735b8a266caa437f80588c3ab80a8a960e6abe37", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "6a895778f0d7648a4b34b486af59a1c8009041fbdf2b17f1ac215eb829c60235"}, "ex_doc": {:hex, :ex_doc, "0.29.4", "6257ecbb20c7396b1fe5accd55b7b0d23f44b6aa18017b415cb4c2b91d997729", [:mix], [{:earmark_parser, "~> 1.4.31", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "2c6699a737ae46cb61e4ed012af931b57b699643b24dabe2400a8168414bc4f5"}, + "jason": {:hex, :jason, "1.4.1", "af1504e35f629ddcdd6addb3513c3853991f694921b1b9368b0bd32beb9f1b63", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fbb01ecdfd565b56261302f7e1fcc27c4fb8f32d56eab74db621fc154604a7a1"}, "makeup": {:hex, :makeup, "1.1.0", "6b67c8bc2882a6b6a445859952a602afc1a41c2e08379ca057c0f525366fc3ca", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "0a45ed501f4a8897f580eabf99a2e5234ea3e75a4373c8a52824f6e873be57a6"}, "makeup_elixir": {:hex, :makeup_elixir, "0.16.1", "cc9e3ca312f1cfeccc572b37a09980287e243648108384b97ff2b76e505c3555", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "e127a341ad1b209bd80f7bd1620a15693a9908ed780c3b763bccf7d200c767c6"}, "makeup_erlang": {:hex, :makeup_erlang, "0.1.2", "ad87296a092a46e03b7e9b0be7631ddcf64c790fa68a9ef5323b6cbb36affc72", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "f3f5a1ca93ce6e092d92b6d9c049bcda58a3b617a8d888f8e7231c85630e8108"}, diff --git a/test/type_id/jason_encoder_test.exs b/test/type_id/jason_encoder_test.exs new file mode 100644 index 0000000..fd191b8 --- /dev/null +++ b/test/type_id/jason_encoder_test.exs @@ -0,0 +1,19 @@ +defmodule TypeID.JasonEncoderTest do + use ExUnit.Case, async: true + + defmodule User do + @derive Jason.Encoder + defstruct [:id, :name] + end + + alias __MODULE__.User + + test "structs with TypeID values can be encoded to JSON" do + assert {:ok, id} = TypeID.from_string("user_01h4rse40gf60a3kz9tkmsws17") + + user = %User{id: id, name: "Sloane"} + + assert {:ok, ~S|{"id":"user_01h4rse40gf60a3kz9tkmsws17","name":"Sloane"}|} = + Jason.encode(user) + end +end diff --git a/test/type_id/phoenix_html_safe_test.exs b/test/type_id/phoenix_html_safe_test.exs index fc34621..ce9f71b 100644 --- a/test/type_id/phoenix_html_safe_test.exs +++ b/test/type_id/phoenix_html_safe_test.exs @@ -1,5 +1,5 @@ defmodule TypeID.PhoenixHTMLSafeTest do - use ExUnit.Case + use ExUnit.Case, async: true test "to_iodata/1" do assert {:ok, tid} = TypeID.from_string("test_01h4rm6n03esc96rwqtnq2fr5a") diff --git a/test/type_id/spec_test.exs b/test/type_id/spec_test.exs index e1eeeb7..0afd28a 100644 --- a/test/type_id/spec_test.exs +++ b/test/type_id/spec_test.exs @@ -1,5 +1,5 @@ defmodule TypeID.SpecTest do - use ExUnit.Case + use ExUnit.Case, async: true specs_path = :code.priv_dir(:typeid_elixir) diff --git a/test/type_id/string_char_test.exs b/test/type_id/string_char_test.exs index a0c217d..534f170 100644 --- a/test/type_id/string_char_test.exs +++ b/test/type_id/string_char_test.exs @@ -1,5 +1,5 @@ defmodule TypeID.StringCharTest do - use ExUnit.Case + use ExUnit.Case, async: true test "implicit cast to string" do assert {:ok, tid} = TypeID.from_string("test_01h4rm6n03esc96rwqtnq2fr5a") diff --git a/test/type_id_test.exs b/test/type_id_test.exs index 980d63f..f65aa34 100644 --- a/test/type_id_test.exs +++ b/test/type_id_test.exs @@ -1,5 +1,5 @@ defmodule TypeIDTest do - use ExUnit.Case + use ExUnit.Case, async: true doctest TypeID, except: [new: 2] describe "new/1" do