skander
skander
AEAsh Elixir
Created by skander on 9/17/2023 in #support
AshGraphql erroring with key :run not found
I think this is related to the new generic actions changes, but I ran into this after upgrading and pointing to the latest commit of ash_graphql:
[error] 0f997ea0-3e42-480e-a425-9d39d18f271f: Exception raised while resolving query.

** (KeyError) key :run not found in: %Ash.Resource.Actions.Read{arguments: [], description: nil, filter: nil, get_by: nil, get?: false, manual: nil, metadata: [], modify_query: nil, name: :read, pagination: false, preparations: [], primary?: true, touches_resources: [], transaction?: false, type: :read}

(ash 2.14.17) lib/ash/actions/action.ex:21: Ash.Actions.Action.run/3
(ash_graphql 0.26.1) lib/graphql/resolver.ex:41: AshGraphql.Graphql.Resolver.resolve/2
(absinthe 1.7.5) lib/absinthe/phase/document/execution/resolution.ex:234: Absinthe.Phase.Document.Execution.Resolution.reduce_resolution/1
...
[error] 0f997ea0-3e42-480e-a425-9d39d18f271f: Exception raised while resolving query.

** (KeyError) key :run not found in: %Ash.Resource.Actions.Read{arguments: [], description: nil, filter: nil, get_by: nil, get?: false, manual: nil, metadata: [], modify_query: nil, name: :read, pagination: false, preparations: [], primary?: true, touches_resources: [], transaction?: false, type: :read}

(ash 2.14.17) lib/ash/actions/action.ex:21: Ash.Actions.Action.run/3
(ash_graphql 0.26.1) lib/graphql/resolver.ex:41: AshGraphql.Graphql.Resolver.resolve/2
(absinthe 1.7.5) lib/absinthe/phase/document/execution/resolution.ex:234: Absinthe.Phase.Document.Execution.Resolution.reduce_resolution/1
...
If this isn't enough to repro, I can come up with a test or example!
6 replies
AEAsh Elixir
Created by skander on 8/22/2023 in #support
GraphQL NewType Non-null?
No description
6 replies
AEAsh Elixir
Created by skander on 7/31/2023 in #support
Calculations in AshJsonApi?
No description
24 replies
AEAsh Elixir
Created by skander on 7/8/2023 in #support
Manual relationship with recursive CTE
I'm trying to implement this comment/thread (https://discord.com/channels/711271361523351632/1110614023881359430/1111297127897890866) and creating a manual relationship with a recursive CTE (for a tag in a graph structure, get all parent tags). I'm able to get it done with Ecto spitting out grouped map lists. I'm getting a bit stuck figuring out how to get them as an Ash Resource in the end. Is there anything major I'm missing?
use Ash.Resource.ManualRelationship
require Ash.Query
require Ecto.Query

def load(records, _opts, %{query: _query, actor: _actor, authorize?: _authorize?}) do
tag_ids = Enum.map(records, & &1.id)

initial_query =
Tag
|> Ecto.Query.select_merge([t], %{original_tag_id: t.id})
|> Ecto.Query.where([t], t.id in ^tag_ids)

recursion_query =
Tag
|> Ecto.Query.join(:inner, [t], pt in "parent_tags", on: pt.parent_tag_id == t.id)
|> Ecto.Query.select_merge([t, pt], %{original_tag_id: pt.original_tag_id})

parent_tags_query = initial_query |> Ecto.Query.union(^recursion_query)

tag_attributes = Tag |> Ash.Resource.Info.attributes() |> Enum.map(& &1.name)
select_fields = [:original_tag_id | tag_attributes]

results =
Ecto.Query.from("parent_tags")
|> Ecto.Query.select(^select_fields)
|> Ecto.Query.recursive_ctes(true)
|> Ecto.Query.with_cte("parent_tags", as: ^parent_tags_query)
|> Repo.all()

{:ok,
results
# Group by original tag id and drop from final value
|> Enum.group_by(& &1.original_tag_id, &Map.drop(&1, [:original_tag_id]))}
end
use Ash.Resource.ManualRelationship
require Ash.Query
require Ecto.Query

def load(records, _opts, %{query: _query, actor: _actor, authorize?: _authorize?}) do
tag_ids = Enum.map(records, & &1.id)

initial_query =
Tag
|> Ecto.Query.select_merge([t], %{original_tag_id: t.id})
|> Ecto.Query.where([t], t.id in ^tag_ids)

recursion_query =
Tag
|> Ecto.Query.join(:inner, [t], pt in "parent_tags", on: pt.parent_tag_id == t.id)
|> Ecto.Query.select_merge([t, pt], %{original_tag_id: pt.original_tag_id})

parent_tags_query = initial_query |> Ecto.Query.union(^recursion_query)

tag_attributes = Tag |> Ash.Resource.Info.attributes() |> Enum.map(& &1.name)
select_fields = [:original_tag_id | tag_attributes]

results =
Ecto.Query.from("parent_tags")
|> Ecto.Query.select(^select_fields)
|> Ecto.Query.recursive_ctes(true)
|> Ecto.Query.with_cte("parent_tags", as: ^parent_tags_query)
|> Repo.all()

{:ok,
results
# Group by original tag id and drop from final value
|> Enum.group_by(& &1.original_tag_id, &Map.drop(&1, [:original_tag_id]))}
end
Results look like:
%{
id: <<115, 49, 103, 214, 71, 206, 68, 225, 173, 194, 151, 80, 189, 122, 121,
237>>,
name: "Bikes",
parent_tag_id: <<35, 126, 25, 129, 171, 216, 76, 141, 185, 212, 147, 171, 74,
59, 48, 174>>,
}
%{
id: <<115, 49, 103, 214, 71, 206, 68, 225, 173, 194, 151, 80, 189, 122, 121,
237>>,
name: "Bikes",
parent_tag_id: <<35, 126, 25, 129, 171, 216, 76, 141, 185, 212, 147, 171, 74,
59, 48, 174>>,
}
11 replies
AEAsh Elixir
Created by skander on 5/26/2023 in #support
Primary key not counting as identity key for magic link auth
I'm trying to add a magic_link with the resource's primary key :id as identity but it doesn't seem to count as an ID unless it's in the identities block.
strategies do
magic_link do
identity_field :id

sender fn subscriber, token, _opts ->
# MyApp.Emails.deliver_magic_link(user, token)
end
end
end
strategies do
magic_link do
identity_field :id

sender fn subscriber, token, _opts ->
# MyApp.Emails.deliver_magic_link(user, token)
end
end
end
** (EXIT from #PID<0.110.0>) an exception was raised:
** (Spark.Error.DslError) [nil]
identities -> identity:
The `:id` attribute on the resource `MyApp.Notifications.Subscriber` should be uniquely constrained
** (EXIT from #PID<0.110.0>) an exception was raised:
** (Spark.Error.DslError) [nil]
identities -> identity:
The `:id` attribute on the resource `MyApp.Notifications.Subscriber` should be uniquely constrained
For now, I'm going to add a unique index to shadow the primary key.
2 replies
AEAsh Elixir
Created by skander on 4/1/2023 in #support
Ash-hq default theme showing wrong colors
No description
9 replies