skander
skander
AEAsh Elixir
Created by skander on 9/17/2023 in #support
AshGraphql erroring with key :run not found
Success!
6 replies
AEAsh Elixir
Created by skander on 9/17/2023 in #support
AshGraphql erroring with key :run not found
I'd also upgraded from Ash 2.14.141 to 2.14.17. But trying now
6 replies
AEAsh Elixir
Created by skander on 8/22/2023 in #support
GraphQL NewType Non-null?
Just tried it, works perfectly. Thanks again!
6 replies
AEAsh Elixir
Created by skander on 8/22/2023 in #support
GraphQL NewType Non-null?
Thank you!
6 replies
AEAsh Elixir
Created by Jan Ulbrich on 8/12/2023 in #support
JSON-API And Calculations
That way expensive calculations aren't run if you didn't intend to load them in a generic /resource call
18 replies
AEAsh Elixir
Created by Jan Ulbrich on 8/12/2023 in #support
JSON-API And Calculations
18 replies
AEAsh Elixir
Created by Jan Ulbrich on 8/12/2023 in #support
JSON-API And Calculations
If you don't provide a fields key in your request and you load the calculation via e.g. build(load: [:calculation]) it should show up too
18 replies
AEAsh Elixir
Created by Jan Ulbrich on 8/12/2023 in #support
JSON-API And Calculations
They should be available if you pull from main! Either load the calculation in your action or access it via the fields param
18 replies
AEAsh Elixir
Created by skander on 7/31/2023 in #support
Calculations in AshJsonApi?
Sure, done! No rush of course. I might try fixing it myself in the same PR. I need to also show public calculated fields in the OpenAPI schema too
24 replies
AEAsh Elixir
Created by skander on 7/31/2023 in #support
Calculations in AshJsonApi?
1) test attributes calculated fields are rendered properly (Test.Acceptance.GetTest)
test/acceptance/get_test.exs:152
match (=) failed
code: assert %{"data" => %{"attributes" => %{^attribute => ^expected_value}}} = conn.resp_body
left: %{"data" => %{"attributes" => %{^attribute => ^expected_value}}}
right: %{
"errors" => [%{"code" => "InvalidField", "detail" => "Invalid field for type post:", "id" => "9ad15d14-d5bf-434b-ae0b-16b0a1038785", "source" => %{"parameter" => "fields[post]"}, "status" => "400", "title" => "Invalid Field"}],
"jsonapi" => %{"version" => "1.0"}
}
stacktrace:
test/acceptance/get_test.exs:155: (test)
1) test attributes calculated fields are rendered properly (Test.Acceptance.GetTest)
test/acceptance/get_test.exs:152
match (=) failed
code: assert %{"data" => %{"attributes" => %{^attribute => ^expected_value}}} = conn.resp_body
left: %{"data" => %{"attributes" => %{^attribute => ^expected_value}}}
right: %{
"errors" => [%{"code" => "InvalidField", "detail" => "Invalid field for type post:", "id" => "9ad15d14-d5bf-434b-ae0b-16b0a1038785", "source" => %{"parameter" => "fields[post]"}, "status" => "400", "title" => "Invalid Field"}],
"jsonapi" => %{"version" => "1.0"}
}
stacktrace:
test/acceptance/get_test.exs:155: (test)
24 replies
AEAsh Elixir
Created by skander on 7/31/2023 in #support
Calculations in AshJsonApi?
24 replies
AEAsh Elixir
Created by skander on 7/31/2023 in #support
Calculations in AshJsonApi?
Ah got it. Still coming up with an InvalidField code with field[type]=attr1,calculated format. Even tried with a simple concat-based calculation with the same result. I can try reproing in a simplified test later.
24 replies
AEAsh Elixir
Created by skander on 7/31/2023 in #support
Calculations in AshJsonApi?
Sadly getting an error with the fields= param
curl -s -H "Content-Type: application/vnd.api+json" -H "Accept: application/vnd.api+json" 'http://localhost:4000/api/json/locations?term=bar&fields=name,address_1,grouped_weekly_schedule'
#=> {"errors":[{"code":"InvalidField","detail":"Invalid field for type locations:","id":"31401fd8-ff94-4067-9aa4-4ef7a6c697f7","source":{"parameter":"fields"},"status":"400","title":"Invalid Field"}],"jsonapi":{"version":"1.0"}}
curl -s -H "Content-Type: application/vnd.api+json" -H "Accept: application/vnd.api+json" 'http://localhost:4000/api/json/locations?term=bar&fields=name,address_1,grouped_weekly_schedule'
#=> {"errors":[{"code":"InvalidField","detail":"Invalid field for type locations:","id":"31401fd8-ff94-4067-9aa4-4ef7a6c697f7","source":{"parameter":"fields"},"status":"400","title":"Invalid Field"}],"jsonapi":{"version":"1.0"}}
I can make an issue after finishing up some things I need to get out
24 replies
AEAsh Elixir
Created by skander on 7/31/2023 in #support
Calculations in AshJsonApi?
Ok, seems to just work if the default read on the relationship also loads the calculation in a preparation.
24 replies
AEAsh Elixir
Created by skander on 7/31/2023 in #support
Calculations in AshJsonApi?
Oh! Looks like it works when adding it to default_fields. Though I also need to somehow include a calculation from a relationship. Please let me know if anyone has any insights there.
24 replies
AEAsh Elixir
Created by rohan on 7/11/2023 in #support
How not to select fields when loading a resource
TIL about deselect!
6 replies
AEAsh Elixir
Created by skander on 7/8/2023 in #support
Manual relationship with recursive CTE
Appreciate the help!
11 replies
AEAsh Elixir
Created by skander on 7/8/2023 in #support
Manual relationship with recursive CTE
The rest is the same. The key for me here was not knowing you could pass a tuple into select and recursive_ctes
11 replies
AEAsh Elixir
Created by skander on 7/8/2023 in #support
Manual relationship with recursive CTE
That worked! Thank you so much. I made a couple modifications so that the query would load all relationships in a batch, then group by the original resource's ID
@impl true
def load(records, _opts, %{query: _query, actor: _actor, authorize?: _authorize?}) do
tag_ids = Enum.map(records, & &1.id)

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

results =
Tag
|> where([t], t.id in ^tag_ids)
|> select_merge([t], %{original_tag_id: t.id})
|> recursive_cte_query(
"parent_tags",
Tag,
:dont_hack
)
|> select(^select_fields)
|> Repo.all()

{
:ok,
# Group by the original tag_id. Final order is highest parent tag first
results
|> Enum.reduce(%{}, fn row, acc ->
{:ok, id} = Ash.Type.cast_input(Ash.Type.UUID, row.original_tag_id)
Map.put(acc, id, [Map.drop(row, [:original_tag_id]) | Map.get(acc, id, [])])
end)
}
end

# ...

def recursive_cte_query(immediate_parents, cte_name, query, _) do
recursion_query =
query
|> join(:inner, [t], pt in ^cte_name, on: t.id == pt.parent_tag_id)
|> select_merge([t, pt], %{original_tag_id: pt.original_tag_id})

ancestors_query =
immediate_parents
|> union(^recursion_query)

{cte_name, query}
|> recursive_ctes(true)
|> with_cte(^cte_name, as: ^ancestors_query)
end
@impl true
def load(records, _opts, %{query: _query, actor: _actor, authorize?: _authorize?}) do
tag_ids = Enum.map(records, & &1.id)

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

results =
Tag
|> where([t], t.id in ^tag_ids)
|> select_merge([t], %{original_tag_id: t.id})
|> recursive_cte_query(
"parent_tags",
Tag,
:dont_hack
)
|> select(^select_fields)
|> Repo.all()

{
:ok,
# Group by the original tag_id. Final order is highest parent tag first
results
|> Enum.reduce(%{}, fn row, acc ->
{:ok, id} = Ash.Type.cast_input(Ash.Type.UUID, row.original_tag_id)
Map.put(acc, id, [Map.drop(row, [:original_tag_id]) | Map.get(acc, id, [])])
end)
}
end

# ...

def recursive_cte_query(immediate_parents, cte_name, query, _) do
recursion_query =
query
|> join(:inner, [t], pt in ^cte_name, on: t.id == pt.parent_tag_id)
|> select_merge([t, pt], %{original_tag_id: pt.original_tag_id})

ancestors_query =
immediate_parents
|> union(^recursion_query)

{cte_name, query}
|> recursive_ctes(true)
|> with_cte(^cte_name, as: ^ancestors_query)
end
11 replies
AEAsh Elixir
Created by skander on 7/8/2023 in #support
Manual relationship with recursive CTE
Thank you so much! It’s still Sunday night here so I’ll be checking this tomorrow. Appreciate it!
11 replies