Many to Many Error
frankdugan3:
Given these relationships:
# Capability
relationships do
many_to_many :steps, Hsm.Ash.MCP.Step do
through Hsm.Ash.MCP.StepCapability
source_attribute_on_join_resource :capability_id
destination_attribute_on_join_resource :step_id
end
end
# Step
relationships do
many_to_many :capabilities, Hsm.Ash.Workcenters.Capability do
through Hsm.Ash.MCP.StepCapability
source_attribute_on_join_resource :step_id
destination_attribute_on_join_resource :capability_id
end
end
# StepCapability
relationships do
belongs_to :capability, Hsm.Ash.Workcenters.Capability,
allow_nil?: false,
api: Hsm.Ash.Workcenters
belongs_to :step, Hsm.Ash.MCP.Step, allow_nil?: false, api: Hsm.Ash.MCP
endAll of them are in the same API and Registry.
I’m getting an error that I don’t quite understand (join_relationship_name???):
** (EXIT from #PID<0.96.0>) an exception was raised:
** (RuntimeError) Resource `Hsm.Ash.MCP.StepCapability` is not in registry `Hsm.Ash.Workcenters.Registry` for autogenerated join relationship: `:steps_join_assoc`
Relationship was generated by the `many_to_many` relationship `:steps`
If the `through` resource `Hsm.Ash.MCP.StepCapability` is not accepted by the same
api as the destination resource `Hsm.Ash.MCP.Step`,
then you must define that relationship manually. To define it manually, add the following to your
relationships:
has_many :steps_join_assoc, Hsm.Ash.MCP.StepCapability do
# configure the relationship attributes
...
end
You can use a name other than `:steps_join_assoc`, but if you do, make sure to
add that to `:steps`, i.e
many_to_many :steps_join_assoc, Hsm.Ash.MCP.StepCapability do
...
join_relationship_name :your_new_name
end
(ash 2.9.5) lib/ash/registry/extensions/resource_validations/verifiers/validate_related_resource_inclusion.ex:43: anonymous fn/5 in Ash.Registry.ResourceValidations.Verifiers.ValidateRelatedResourceInclusion.verify/1
(elixir 1.14.4) lib/enum.ex:2468: Enum."-reduce/3-lists^foldl/2-0-"/3
(ash 2.9.5) lib/ash/registry/extensions/resource_validations/verifiers/validate_related_resource_inclusion.ex:16: anonymous fn/4 in Ash.Registry.ResourceValidations.Verifiers.ValidateRelatedResourceInclusion.verify/1
(elixir 1.14.4) lib/enum.ex:2468: Enum."-reduce/3-lists^foldl/2-0-"/3
(ash 2.9.5) lib/ash/registry/extensions/resource_validations/verifiers/validate_related_resource_inclusion.ex:15: Ash.Registry.ResourceValidations.Verifiers.ValidateRelatedResourceInclusion.verify/1
lib/hsm/ash/workcenters/registry.ex:1: anonymous fn/1 in Hsm.Ash.Workcenters.Registry.__verify_ash_dsl__/1
(elixir 1.14.4) lib/enum.ex:975: Enum."-each/2-lists^foreach/1-0-"/2
lib/hsm/ash/workcenters/registry.ex:1: Hsm.Ash.Workcenters.Registry.__verify_ash_dsl__/1I’m probably missing something obvious, but I can’t spot it.
TechnoMage:
I have not gotten many to many to work quite yet, but mine at lest compile. I suggest looking for references or imports or aliases of Hsm.Ash.MCP.StepCapability given it is in the error and not appearly what you are expecting to be involved.
frankdugan3:
Yeah, pasted the wrong defs. I don’t use aliases to avoid those kinds of problems. Post edited w/ correct definitions. ^
frankdugan3:
Oh, is this as simple as needing to add it to both registries? <:thinkies:915154230078222336>
TechnoMage:
It is making up the resource name ‘steps_join_assoc’ for some reason. It looks like you have through specified, I would double check that the join resource is in the same API and registry as the others.
frankdugan3:
The join resource is in the
MCP registry/api, not
Workcenters . I’m just not clear on how to deal with that, as specifying the api on either/both
many_to_many still produces the same error. It’s also not clear in the docs if the api option in a
many_to_many is supposed to point to the API of t he destination resource or the join resource.
TechnoMage:
The docs state that the API option is for the destination resource. Looks like it is a missing option. I would file an issue, and in the mean time add the join resource to both API and Registries.
frankdugan3:
The docs say “related entity” for the api on a many_to_many, which to me is not clearly indicating “destination”, which is the term it consistently uses. I mean, that’s probably what it means, but it’s unclear IMO.
frankdugan3:
Yeah, I’m consistently doing something wrong w/ my cross-api many-to-many relationships because they all have this problem. <@197905764424089601> When you get a chance, could use some guidance. (no rush) 😵💫
frankdugan3:
OK, I
think
the solution was a few steps: 1) add the
api options to all the many-to-many relationships, 2) add the join resource to
both
api/registries and 3) make sure the join resource specifies the API for each relationship. Need to do this to the rest of them to make sure.
zachdaniel:
You shouldn’t need to add the join resource to both apis
zachdaniel:
*registries
zachdaniel:
The idea of the warning is that if you set the api of a many to many relationship, and we generate a has_many for it, we assume that the through resource is in the destination api.
zachdaniel:
If it’s not, then you need to define the underlying has_many yourself and not set an api (or set it to the correct api)
zachdaniel:
And then use that with
join_relationship
zachdaniel:
And the api in a many to many should point to the destination resource api.
frankdugan3:
Might be a bug then, because given this:
# Step (MCP API)
many_to_many :capabilities, Hsm.Ash.Workcenters.Capability do
through Hsm.Ash.MCP.StepCapability
source_attribute_on_join_resource :step_id
destination_attribute_on_join_resource :capability_id
api Hsm.Ash.Workcenters
end
# Capability (Workcenters API)
many_to_many :mcp_steps, Hsm.Ash.MCP.Step do
through Hsm.Ash.MCP.StepCapability
source_attribute_on_join_resource :capability_id
destination_attribute_on_join_resource :step_id
api Hsm.Ash.MCP
end
# StepCapability (MCP API)
relationships do
belongs_to :capability, Hsm.Ash.Workcenters.Capability,
allow_nil?: false,
api: Hsm.Ash.Workcenters
belongs_to :step, Hsm.Ash.MCP.Step, allow_nil?: false, api: Hsm.Ash.MCP
end
Hsm.Ash.MCP.StepCapability is added to the
MCP registry, but will still give the compile error unless I
also
add it to the
Workcenters registry. <:thinkies:915154230078222336>
zachdaniel:
Well, the through resource is only in one of them
zachdaniel:
So you will always get an error unless you manually define the underlying
has_many relationship for one of them
zachdaniel:
not specifying the api for that one (I.e the through resource is in my api not theirs)
zachdaniel:
If you define two many to many relationships across an api boundary without doing that, one of them will always error unless the through resource is in both.
frankdugan3:
Ahh… OK. Is there any harm to just including the through relationship in both registries to avoid the manual
has_many ? Just trying to figure out best practice, will PR some of these details in the guides/docs.
zachdaniel:
No harm really, no.
zachdaniel:
But I’d suggest just picking which api it belongs in and on one end define the has_many for the many_to_many
hanrelan:
came up against this now, it doesn’t seem to be documented in the relationship docs anywhere
hanrelan:
actually I’m really confused by what I’m supposed to do here. I’m getting:
an exception was raised:
** (RuntimeError) Resource `Scribble.Scribe.UserMedicalTerm` is not accepted by api `Scribble.EmailHandler` for autogenerated join relationship: `:users_join_assoc`
Relationship was generated by the `many_to_many` relationship `:users`
If the `through` resource `Scribble.Scribe.UserMedicalTerm` is not accepted by the same
api as the destination resource `Scribble.EmailHandler.User`,
then you must define that relationship manually. To define it manually, add the following to your
relationships:
has_many :users_join_assoc, Scribble.Scribe.UserMedicalTerm do
# configure the relationship attributes
...
end
You can use a name other than `:users_join_assoc`, but if you do, make sure to
add that to `:users`, i.e
many_to_many :users_join_assoc, Scribble.Scribe.UserMedicalTerm do
...
join_relationship_name :your_new_name
end
am I supposed to literally call it
:users_join_assoc ?
hanrelan:
I think having an example of this in the docs would be really helpful, right now the docs only says that the
api must be defined if
many_to_many is crossing api boundaries
zachdaniel:
You can call it whatever you want, but then you need to say
join_relationship :relationship_name in your many to many.
zachdaniel:
Agreed an example would be helpful
tjaco:
I have a question related to the many_to_many. I have a pretty basic many to many in one Api. Currently I’m seeding some data, but it fails to write the join table when I add the associated data directly in the params. Is this not supported (yet)? In Ecto this would mean adding the cast_assoc for the related items
tjaco:
checking out the managing relationships guide as it seems that’s where I can configure this
zachdaniel:
Yep 🙂 managing relationships (or custom changes w/ after action hooks) is what you’d want there