andreh

andreh

Using Ash.Reactor with AshPhoenix.Form

Hi! First, I’d like to say that AshPhoenix.Form is really great, it makes dealing with forms so much easier! To implement an e-invoicing pipeline, I’m playing with Reactor and would like to know if it is possible to use it together with AshPhoenix.Form.

The main issue I’m facing is that my Invoice resource handles many items through manage_relationship and I don’t know how to pass that to the Reactor.

Here’s my Invoice resource:

defmodule Sales.Invoice do
  actions do
    defaults [:read]

    create :issue do
      primary? true

      accept [
        :discount_tax_rate,
        :discount_type,
        :discount_value,
        :issue_date,
        :payment_mean,
        :payment_terms_days,
        :payment_terms_days_end_of_month,
        :status,
        :contact_id
      ]

      argument :items, {:array, :map}, allow_nil?: false
      change manage_relationship(:items, type: :direct_control, order_is_key: :number)

      # many more validations and change
    end

    action :complete_issue, :struct do
     # Do I have to repeat alls arguments here?
     # And what about change manage_relationship(:items, type: :direct_control, order_is_key: :number)?
 
      run Reactors.IssueInvoice
    end
  end
end

And here’s the Reactor:

defmodule Reactors.IssueInvoice do
  use Ash.Reactor

  # Do I have to repeat all the inputs here?
  input :discount_tax_rate
  input :discount_type
  input :discount_value
  input :issue_date
  input :payment_mean
  input :payment_terms_days
  input :payment_terms_days_end_of_month
  input :status
  input :contact_id
  input :items

  step :check_access_point, Sales.Invoice.Steps.CheckAccessPoint do
    max_retries 3
  end

  transaction :create_invoice_transaction, [Sales.Invoice, Audit.AuditLog] do
    wait_for :check_access_point

    # Do I have to repeat all the inputs here?
    create :create_invoice, Sales.Invoice, :issue do
      inputs %{
        discount_tax_rate: input(:discount_tax_rate),
        discount_type: input(:discount_type),
        discount_value: input(:discount_value),
        issue_date: input(:issue_date),
        payment_mean: input(:payment_mean),
        payment_terms_days: input(:payment_terms_days),
        payment_terms_days_end_of_month: input(:payment_terms_days_end_of_month),
        status: input(:status),
        contact_id: input(:contact_id),
        items: input(:items)
      }
    end
    
     # Other steps...
    return :create_invoice
  end

  return :create_invoice_transaction
end

And of course, this is the error I get:

[error] ** (AshPhoenix.Form.NoFormConfigured) items at path [] must be configured in the form to be used with `inputs_for`. For example:

There is an argument called `items` on the action `Sales.Invoice.complete_issue`.

Perhaps you are missing a `change manage_relationship` for that argument, or it is not a type that can have forms generated for it?

So I guess the question is: it is possible to benefit from all the goodness of Ash.Changeset and Ash.Phoenix.Form while using Ash.Reactor?

I’ve managed to get a working solution using hooks, but it would be nice to benefit from the compensation and retry/backoff features of Reactor.

Hope I’m clear enough, let me know!

Most Liked

ken-kost

ken-kost

Assuming you’re auto deriving the form; it doesn’t work in this case because it’s going through a generic action which has no manage_relationship that could be picked up. Hence the error, and the solution is to manually configure the nested forms, i.e. manually initialize the form and be explicit in what you want:

AshPhoenix.Form.for_action(Sales.Invoice, :complete_issue,  
  forms: [  
    items: [  
      type: :list,  
      resource: Sales.InvoiceItem,  
      create_action: :create 
    ]  
  ]  
)

More on this here.

When AshPhoenix.Form.params/1 is called on submit, it collects all nested item params and assembles them under the "items" key, which gets passed as the items argument to complete_issue — and from there into your Reactor.

Where Next?

Popular in Questions Top

skosch
To my knowledge, put_in, Map.update etc. all have the one limitation of not automatically creating intermediate keys when needed (for exa...
New
myronmarston
The Elixir Typespec docs show the following syntax for keyword lists in typespecs: # ... | [key: type] # keyword lists...
New
JeremM34
Hello, how can I check the Phoenix version ? Thanks !
New
shahryarjb
Hello, I have map which I want to convert it to string like this: the map: %{last_name: "tavakkoli", name: "shahryar"} the string I ne...
New
jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod – where is this set? Thanks.
New
JorisKok
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
New
stefanchrobot
What’s the safe way to decode a JSON string into a struct? I want to avoid calling String.to_atom. Jason.decode can give me a map with st...
New
baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
stefanluptak
Hello everybody, usually, I use a 29" ultra-wide monitor for VSCode which can easily accomodate explorer (files panel) + file with code ...
New
jason.o
In the code below, if the create action is not set to accept “extra_key” as an input, it errors out with a message shown above. Is there ...
New

Other popular topics Top

New
AstonJ
Posting this to see if we can make things easier for people to get into Neovim. If you use Neovim and have a favourite distro please let ...
New
sorentwo
Hello! tl;dr Announcing Oban, an Ecto based job processing library with a focus on reliability and historical observability. After spen...
985 42920 311
New
chrismccord
As promised, the first release candidate of Phoenix 1.3.0 is out! This release focuses on code generators with improved project structure...
New
jerry
Good day to you all. I have been struggling to get a query involving like and ilike to work. Can anyone assist me on this, please? pro...
New
josevalim
Hi everyone, One of the features added to Elixir early on to help integration with Erlang code was the idea of overridable function defi...
New
jay1
Why is it that the mnesia database isn’t the most preferred database for use in Elixir/Phoenix?
New
Emily
I have VueJS GUIs with the project generated using Webpack. I have Elixir modules that will need to be used by the VueJS GUIs. I forese...
New
aalberti333
As the title describes, I’m trying to run Enum.map() over a list of key/value pairs, where the value is a map. My data looks like this: ...
New
gausby
I asked this very same question on twitter and got some interesting feedback, but I thought it would be a good question to ask here as we...
1207 39297 209
New

Latest on Elixir Forum

We're in Beta

About us Mission Statement