From 744af64afb2bcaba130636f615f2dd48a3d5120b Mon Sep 17 00:00:00 2001 From: Riccardo Binetti Date: Thu, 25 Jan 2024 10:37:35 +0100 Subject: [PATCH] improvement: return a map from decode_relay_id/1 Slight API improvement over #106. This makes it more ergonomic to partially match on the return value (and it also makes it more explicit by explicitly labeling the two parts). Also add tests for relay id encoding/decoding. --- lib/graphql/resolver.ex | 2 +- lib/resource/resource.ex | 4 ++-- test/relay_ids_test.exs | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 35 insertions(+), 3 deletions(-) diff --git a/lib/graphql/resolver.ex b/lib/graphql/resolver.ex index 8bcdfd4e..786a84a0 100644 --- a/lib/graphql/resolver.ex +++ b/lib/graphql/resolver.ex @@ -2588,7 +2588,7 @@ defmodule AshGraphql.Graphql.Resolver do def resolve_node(%{arguments: %{id: id}} = resolution, type_to_api_and_resource_map) do case AshGraphql.Resource.decode_relay_id(id) do - {:ok, {type, primary_key}} -> + {:ok, %{type: type, id: primary_key}} -> {api, resource} = Map.fetch!(type_to_api_and_resource_map, type) # We can be sure this returns something since we check this at compile time query = AshGraphql.Resource.primary_key_get_query(resource) diff --git a/lib/resource/resource.ex b/lib/resource/resource.ex index 06a35ba2..10f6b65a 100644 --- a/lib/resource/resource.ex +++ b/lib/resource/resource.ex @@ -438,7 +438,7 @@ defmodule AshGraphql.Resource do if relay_ids? do case decode_relay_id(id) do - {:ok, {^type, primary_key}} -> + {:ok, %{type: ^type, id: primary_key}} -> decode_primary_key(resource, primary_key) _ -> @@ -474,7 +474,7 @@ defmodule AshGraphql.Resource do type = String.to_existing_atom(type_string) - {:ok, {type, primary_key}} + {:ok, %{type: type, id: primary_key}} rescue _ -> {:error, Ash.Error.Invalid.InvalidPrimaryKey.exception(resource: nil, value: id)} diff --git a/test/relay_ids_test.exs b/test/relay_ids_test.exs index c6650228..757fe14c 100644 --- a/test/relay_ids_test.exs +++ b/test/relay_ids_test.exs @@ -225,4 +225,36 @@ defmodule AshGraphql.RelayIdsTest do assert result[:errors] != nil end end + + describe "relay ID decoding" do + test "round trips" do + user = + User + |> Ash.Changeset.for_create(:create, %{name: "Fred"}) + |> Api.create!() + + user_id = user.id + user_type = AshGraphql.Resource.Info.type(User) + + user_relay_id = AshGraphql.Resource.encode_relay_id(user) + + assert {:ok, %{type: ^user_type, id: ^user_id}} = + AshGraphql.Resource.decode_relay_id(user_relay_id) + end + + test "fails for invalid ids" do + assert {:error, %Ash.Error.Invalid.InvalidPrimaryKey{}} = + AshGraphql.Resource.decode_relay_id("notbase64") + + assert {:error, %Ash.Error.Invalid.InvalidPrimaryKey{}} = + "non-existing-type:1234" + |> Base.encode64() + |> AshGraphql.Resource.decode_relay_id() + + assert {:error, %Ash.Error.Invalid.InvalidPrimaryKey{}} = + "user" + |> Base.encode64() + |> AshGraphql.Resource.decode_relay_id() + end + end end