Resource Key in Form Setup for Nested Union Forms

Hello.

What is the resource key in AshPhoenix.Form.for_create supposed to be for a nested key of a union type? As in:

AshPhoenix.Form.for_create(ParentModule, :create, api: MyDomain.Api, forms: [
      sub_field: [
        type: :list,
        resource: ChildModule,
        create_action: :create,
        ]
      ]
    ]))

I tried using the union type itself and (rightly?) got a ChildModule.__struct__/0 is undefined or private error.

For more context:

  • I’m trying to react to an event with AshPhoenix.Form.add_form so I need the resource key
  • I guessed at using AshPhoenix.Form.WrappedValue and got some other error further down the road
  • I’m not yet on Ash 3.0

Please, help.

1 Like

Could you share the full code.

It seemes to me that you are using the form before passing it to to_form() function.

Union forms are pretty complex beasts TBH. There is typically no one resource that can be used to describe them, and the way that it is implemented when using auto?: true is that an updater function is provided, which will dynamically modify the resource/actions depending on the current parameters.

Is there any specific reason you’re building the form specification manually, as opposed to:

AshPhoenix.Form.for_create(
  ParentModule, 
  :create, 
  api: MyDomain.Api, 
  forms: [auto?: true]
)
1 Like

I’m starting to see that too :laughing:

Yeah, I tried auto?: true too. It returns ** (AshPhoenix.Form.NoFormConfigured) options at path [] must be configured in the form to be used with inputs_for

I’m not sure I understand what you mean

Does your action accept the options input? It is only generated for attributes that are accepted by the action.

The nested resource has an options attribute which is itself an embedded resource.

Since I’m still on 2.x, I believe actions accept all attributes by default. So, yes I guess.

For clarity, here’s a stripped-down copy of the resources involved:

defmodule ParentModule do
  attributes do
    attribute :children, {:array, ChildModule}
  end
end
defmodule ChildModule do
  use Ash.Type.NewType, subtype_of: :union, constraints: [types: [
    {ChildType1, [type: ChildType1, tag: :type, tag_value: "child_type_1"]},
  ]]
end
defmodule ChildType1 do
  attributes do
    attribute :options, {:array, Option}
  end
end
defmodule Option do
  attributes do
    attribute :value, :string
  end
end

For my setup:

socket = assign(socket, :form, AshPhoenix.Form.for_create(ParentModule, :create, api: MyApp.Api, forms: [auto?: true]))

And in my template:

    <.form :let={f} for={@form}>
      <.inputs_for :let={ff} field={f[:children]}>
        ...

        <.inputs_for :let={fff} field={ff[:options]}>
          ...
          <.input field={fff[:value]} placeholder="Option" />
        </.inputs_for>
      </.inputs_for>

      <.button action="action-that-triggers-error"> Click Me! </.button>
    </.form>

Does this help in identifying where my problem is coming from?

Ah, unfortunately a significant portion of the work that’s gone into properly supporting unions has been done in branches that depend on 3.0 and wouldn’t be back ported. Any chance you could upgrade in the near future?

1 Like

Ouch. I was hoping to deliver this to production and then upgrade.

I guess I now have a business reason to get to that right away.

Thanks, Zach!

1 Like

Ignore my response. I misunderstood your request.

Hey, Zach

I’ve upgraded to 3.0 and I still haven’t found a workaround using the response on Discord

Even with cast_tag?: true, on validation, I still get:

 %Ash.Error.Invalid.NoSuchInput{
  calculation: nil,
  resource: OneOfTheUnionTypes,
  action: :update,
  input: "type",
  inputs: MapSet.new([:id, :response, :prompt, "id", "prompt",
   "response"]),
  did_you_mean: [],
  splode: Ash.Error,
  bread_crumbs: [],
  vars: [],
  path: [],
  stacktrace: #Splode.Stacktrace<>,
  class: :invalid
}

The form is an update form, as per AshPhoenix.Form.for_update(resource, :action, domain: Domain, forms: [ auto?: true ])

I’ve been scouring through the Ash and AshPhoenix codebase to find what I’m doing wrong or what the cause might be. I’m still on that but nothing yet.

Any help is really appreciated.

If it would be fixed it would be fixed by cast_tag?: false not true. If that doesn’t help we may need to get a reproduction project going so I can debug properly

Typo. I meant (and did) false

Can I see the resource represented by OneOfTheUnionTypes?

Here’s what it looks like:

defmodule AshUnionIssueWeb.Resources.OneOfTheUnionTypes do
  use Ash.Resource, data_layer: :embedded

  attributes do
    uuid_primary_key :id
    attribute :prompt, :string, allow_nil?: false, public?: true
    attribute :response, :string, public?: true
  end

  actions do
    default_accept [:prompt, :response]
    defaults [:create, :read, :update]
  end
end

But I did one even better - I reproduced the issue in this repo. You can check it out.

Thank you for the reproduction :slight_smile: Please try out main of ash. It will likely be a few days before a proper release can be cut, sorry about that :frowning:

Thanks for all your help, Zach

Once I’m able to clone ash, I’ll test it. It seems to be broken right now:

error: invalid path 'documentation/dsls/DSL:-Ash.DataLayer.Ets.md'
error: invalid path 'documentation/dsls/DSL:-Ash.DataLayer.Mnesia.md'
error: invalid path 'documentation/dsls/DSL:-Ash.Domain.md'
error: invalid path 'documentation/dsls/DSL:-Ash.Notifier.PubSub.md'
error: invalid path 'documentation/dsls/DSL:-Ash.Policy.Authorizer.md'
error: invalid path 'documentation/dsls/DSL:-Ash.Reactor.md'
error: invalid path 'documentation/dsls/DSL:-Ash.Resource.md'

wait you’re also having this problem? That is very strange :thinking: are you using windows? I don’t see how this is something I could fix in Ash. Does windows have a problem with certain characters in file names or something?

Yeah, I ran that from a windows

I was going to check on a Mac yesterday but I got sidetracked.

I might not be able to get to it today either but once I do, I’ll let you know.

Hi, Zach. Apologies for the lag. Work on this had to pause for a bit.

Sadly, even on main of ash, the NoSuchInput error persists in the repo

Not sure how to proceed