AE
Ash Elixir•3y ago
moxley

AshGraphql: Updating a managed has_many relationship

I'm getting "In field \"id\": Unknown field." in the GraphQL response error. It's referring to the id provided in the has_many related record .
# This is the updateWebSite input argument. It's a UpdateWebSiteInput type.
input = %{
# The has_many relationship
components: [
%{
# This is the primary key of the associated record (UpdateWebSiteComponentsInput)
id: "38f61258-0e8f-4a99-8bae-0cb892e6ccaa",
value: "new value",
key: "test-component",
}
]
}
# This is the updateWebSite input argument. It's a UpdateWebSiteInput type.
input = %{
# The has_many relationship
components: [
%{
# This is the primary key of the associated record (UpdateWebSiteComponentsInput)
id: "38f61258-0e8f-4a99-8bae-0cb892e6ccaa",
value: "new value",
key: "test-component",
}
]
}
Here are the relevant parts of my WebSite resource:
actions do
# Add a set of simple actions. You'll customize these later.
defaults [:read, :destroy]

update :update do
argument :components, {:array, :map}

# I'm not sure what options to pass here.
# These current options I got from looking at the AshGraphql tests
change manage_relationship(
:components,
type: :direct_control,
on_lookup: :relate,
on_no_match: :create
)
end
end

managed_relationships do
managed_relationship :create, :components

# I'm not sure what options to pass here
managed_relationship :update, :components
# managed_relationship :update, :components, lookup_with_primary_key?: true
end
actions do
# Add a set of simple actions. You'll customize these later.
defaults [:read, :destroy]

update :update do
argument :components, {:array, :map}

# I'm not sure what options to pass here.
# These current options I got from looking at the AshGraphql tests
change manage_relationship(
:components,
type: :direct_control,
on_lookup: :relate,
on_no_match: :create
)
end
end

managed_relationships do
managed_relationship :create, :components

# I'm not sure what options to pass here
managed_relationship :update, :components
# managed_relationship :update, :components, lookup_with_primary_key?: true
end
I tried playing with the options both for change manage_relationship() and managed_relationship(). I got different errors. I'm not quite understanding the documentation yet.
34 Replies
ZachDaniel
ZachDaniel•3y ago
Have you had a look at the generated types for those managed_relationship fields? like in the graphql playground?
ZachDaniel
ZachDaniel•3y ago
The options for manage_relationship are discussed here There are a lot of considerations to be made on that front. What exactly should happen with the values provided in the components key? You likely want lookup_with_primary_key?: true in your managed_relationship to cause it to add the :id field if you're doing something that should lookup/update existing records. What exactly ought to happen with the input you provide to components? What if something is left out of the list? Should it be removed?
moxley
moxleyOP•3y ago
The options for manage_relationship are discussed here
Yep, I read that. There's a lot of read. I'm having difficulty understanding it.
There are a lot of considerations to be made on that front. What exactly should happen with the values provided in the components key?
The list of values in the components key are the attributes for each component under a WebSite. These should be used as the attributes to insert or update each component with. The id field in each item is the component's ID. It should be used to look up the component record in the database for updating. If no ID is given, a new record should be inserted. If the WebSite has a component whose ID is not in the list of component items, that record should be deleted. This is the behavior I'm used to working with when using Ecto's cast_assoc for has_many relationships. When adding lookup_with_primary_key?: true to the managed_relationship call, there's a compiler error: ** (Protocol.UndefinedError) protocol Enumerable not implemented for %Absinthe.Blueprint.Schema.FieldDefinition{name: "id", identifier: :id...
ZachDaniel
ZachDaniel•3y ago
you're having a time of it Got it, so you want type: :direct_control whats the stack trace for that error?
moxley
moxleyOP•3y ago
I'm using :direct_control
== Compilation error in file lib/gf_web/graphql/absinthe_schema.ex ==
** (Protocol.UndefinedError) protocol Enumerable not implemented for %Absinthe.Blueprint.Schema.FieldDefinition{name: "id", identifier: :id, type: :id, module: GfWeb.GraphQL.AbsintheSchema, description: nil, deprecation: nil, config: nil, triggers: [], default_value: nil, arguments: [], directives: [], complexity: nil, source_location: nil, middleware: [], function_ref: nil, flags: %{}, errors: [], __reference__: %{location: %{file: "/Users/mstratto/work/moxley/gf-core/deps/ash_graphql/lib/resource/resource.ex", line: 2847}, module: AshGraphql.Resource}, __private__: []} of type Absinthe.Blueprint.Schema.FieldDefinition (a struct)
(elixir 1.14.3) lib/enum.ex:1: Enumerable.impl_for!/1
(elixir 1.14.3) lib/enum.ex:166: Enumerable.reduce/3
(elixir 1.14.3) lib/enum.ex:4307: Enum.map/2
(ash_graphql 0.22.11) lib/resource/resource.ex:1638: AshGraphql.Resource.manage_pkey_fields/4
(ash_graphql 0.22.11) lib/resource/resource.ex:1319: AshGraphql.Resource.managed_relationship_input/6
(elixir 1.14.3) lib/enum.ex:1658: Enum."-map/2-lists^map/1-0-"/2
(elixir 1.14.3) lib/enum.ex:4249: Enum.flat_map_list/2
(elixir 1.14.3) lib/enum.ex:4250: Enum.flat_map_list/2
== Compilation error in file lib/gf_web/graphql/absinthe_schema.ex ==
** (Protocol.UndefinedError) protocol Enumerable not implemented for %Absinthe.Blueprint.Schema.FieldDefinition{name: "id", identifier: :id, type: :id, module: GfWeb.GraphQL.AbsintheSchema, description: nil, deprecation: nil, config: nil, triggers: [], default_value: nil, arguments: [], directives: [], complexity: nil, source_location: nil, middleware: [], function_ref: nil, flags: %{}, errors: [], __reference__: %{location: %{file: "/Users/mstratto/work/moxley/gf-core/deps/ash_graphql/lib/resource/resource.ex", line: 2847}, module: AshGraphql.Resource}, __private__: []} of type Absinthe.Blueprint.Schema.FieldDefinition (a struct)
(elixir 1.14.3) lib/enum.ex:1: Enumerable.impl_for!/1
(elixir 1.14.3) lib/enum.ex:166: Enumerable.reduce/3
(elixir 1.14.3) lib/enum.ex:4307: Enum.map/2
(ash_graphql 0.22.11) lib/resource/resource.ex:1638: AshGraphql.Resource.manage_pkey_fields/4
(ash_graphql 0.22.11) lib/resource/resource.ex:1319: AshGraphql.Resource.managed_relationship_input/6
(elixir 1.14.3) lib/enum.ex:1658: Enum."-map/2-lists^map/1-0-"/2
(elixir 1.14.3) lib/enum.ex:4249: Enum.flat_map_list/2
(elixir 1.14.3) lib/enum.ex:4250: Enum.flat_map_list/2
ZachDaniel
ZachDaniel•3y ago
Yeah, I was meaning you wouldn't need the additional options
moxley
moxleyOP•3y ago
Do you mean these options:
on_lookup: :relate,
on_no_match: :create
on_lookup: :relate,
on_no_match: :create
ZachDaniel
ZachDaniel•3y ago
yes Is that stacktrace from the latest ash_graphql release?
moxley
moxleyOP•3y ago
No. I'll update it and report back.
ZachDaniel
ZachDaniel•3y ago
awesome, thanks 😄
moxley
moxleyOP•3y ago
I just upgraded to ash_graphql 0.23.0, ash 2.6.26, and ash_postgres 1.3.17. So far I'm getting this:
mix test test/gf_web/graphql/absinthe_schema/web_component_test.exs:153
Compiling 117 files (.ex)

== Compilation error in file lib/gf_web/graphql/absinthe_schema.ex ==
** (Absinthe.Schema.Error) Compilation failed:
---------------------------------------
## Locations
/Users/mstratto/work/moxley/gf-core/deps/ash_graphql/lib/resource/resource.ex:3083

In Web_site, nil is not defined in your schema.

Types must exist if referenced.
---------------------------------------
## Locations
/Users/mstratto/work/moxley/gf-core/deps/ash_graphql/lib/resource/resource.ex:2246

In Web_site, :_filter_input is not defined in your schema.

Types must exist if referenced.


(absinthe 1.7.0) lib/absinthe/schema.ex:366: Absinthe.Schema.__after_compile__/2
(stdlib 4.2) lists.erl:1350: :lists.foldl/3
mix test test/gf_web/graphql/absinthe_schema/web_component_test.exs:153
Compiling 117 files (.ex)

== Compilation error in file lib/gf_web/graphql/absinthe_schema.ex ==
** (Absinthe.Schema.Error) Compilation failed:
---------------------------------------
## Locations
/Users/mstratto/work/moxley/gf-core/deps/ash_graphql/lib/resource/resource.ex:3083

In Web_site, nil is not defined in your schema.

Types must exist if referenced.
---------------------------------------
## Locations
/Users/mstratto/work/moxley/gf-core/deps/ash_graphql/lib/resource/resource.ex:2246

In Web_site, :_filter_input is not defined in your schema.

Types must exist if referenced.


(absinthe 1.7.0) lib/absinthe/schema.ex:366: Absinthe.Schema.__after_compile__/2
(stdlib 4.2) lists.erl:1350: :lists.foldl/3
ZachDaniel
ZachDaniel•3y ago
🤔 do you have any resources that have the AshGraphql.Resource extension but not a type :type configuration?
moxley
moxleyOP•3y ago
Um, I'm not sure. I don't know what a AshGraphql.Resource extension is.
ZachDaniel
ZachDaniel•3y ago
when you add it to your resource you do extensions: [AshGraphql.Resource] in the resource So we're looking for resources where you've done that but not defined a type
moxley
moxleyOP•3y ago
Oh wait. I commented out a bunch of code, and that's probably what caused that. One moment...
ZachDaniel
ZachDaniel•3y ago
I'm adding a check for that now (we should be ignoring resources that don't have a configured type
moxley
moxleyOP•3y ago
Okay, I'm seeing the new warnings you were mentioning before. I'll address those first.
ZachDaniel
ZachDaniel•3y ago
You should just be able to add the config, don't need to worry about step 1 🙂
moxley
moxleyOP•3y ago
Okay, got through all of that, and no more warnings. The GraphQL response is the same:
[warning] GQL result errors for operation UpdateWebSite: [%{locations: [%{column: 26, line: 2}], message: "Argument \"input\" has invalid value $input.\nIn field \"components\": Expected type \"[UpdateComponentsInput!]\", found [{attrs: [{key: \"class\", value: \"test\"}], id: \"722ea0b1-ad77-452b-ba2d-724cc94c7c9d\", key: \"test-component\", type: \"HTML\", value: \"new value\"}].\nIn element #1: Expected type \"UpdateComponentsInput\", found {attrs: [{key: \"class\", value: \"test\"}], id: \"722ea0b1-ad77-452b-ba2d-724cc94c7c9d\", key: \"test-component\", type: \"HTML\", value: \"new value\"}.\nIn field \"id\": Unknown field."}]
[warning] GQL result errors for operation UpdateWebSite: [%{locations: [%{column: 26, line: 2}], message: "Argument \"input\" has invalid value $input.\nIn field \"components\": Expected type \"[UpdateComponentsInput!]\", found [{attrs: [{key: \"class\", value: \"test\"}], id: \"722ea0b1-ad77-452b-ba2d-724cc94c7c9d\", key: \"test-component\", type: \"HTML\", value: \"new value\"}].\nIn element #1: Expected type \"UpdateComponentsInput\", found {attrs: [{key: \"class\", value: \"test\"}], id: \"722ea0b1-ad77-452b-ba2d-724cc94c7c9d\", key: \"test-component\", type: \"HTML\", value: \"new value\"}.\nIn field \"id\": Unknown field."}]
This time, I can add the lookup_with_primary_key?: true option to managed_relationship(), and there's no compiler error, but the GraphQL response is the same. "In field \"id\": Unknown field."
ZachDaniel
ZachDaniel•3y ago
Okay, so we're compiling, its just not including the primary key field which you naturally need for the "or update" component of all of this. lemme take a look
moxley
moxleyOP•3y ago
Thanks!
ZachDaniel
ZachDaniel•3y ago
fun fact, looks like we just aren't adding primary key for updates lemme confirm/try something out
moxley
moxleyOP•3y ago
Oh! Hmm.
ZachDaniel
ZachDaniel•3y ago
oh, nvm, just getting my brain back in this code okay, do me a favor and try out the main branch?
moxley
moxleyOP•3y ago
Yep, one moment... Sorry, I got lost watching the Erlang Movie.
ZachDaniel
ZachDaniel•3y ago
😆 no worries lol
moxley
moxleyOP•3y ago
It works!
ZachDaniel
ZachDaniel•3y ago
🥳 I'm adding an automated test as well for this case in the future I'll cut a release once the test is in
moxley
moxleyOP•3y ago
Sweet! I'll add some more tests on my end to verify all the cases for managing the association. The three cases are covered in my tests: items can be added, updated, or deleted.
ZachDaniel
ZachDaniel•3y ago
Just wait til you get to nested managed relationships 😆 okay, made some small tweaks, added some tests and released it. LMK if the update works for you, when you get a chance 🙂
moxley
moxleyOP•3y ago
I updated to the new patch version, and my tests are still passing. It's looking good.
ZachDaniel
ZachDaniel•3y ago
Thanks for bearing with me on that 😅
moxley
moxleyOP•3y ago
Thanks for being quick to respond!

Did you find this page helpful?