Is it possible to pass a map to args instead of a list of attributes in code_interface?
I'd like to pull off something like:
but I get the following error:
Is there a way to dynamically pass in args that you want to update on the resource? Or do you have to hard code the set_attributes?
I'm trying to bypass the need to pass in each attribute in order every time. As their are many attributes and not all of them will be updated each time.
17 Replies
this is what the resource attributes look like:
I think you’re missing a key detail of how ash actions work 🙂
Each action has an
accept
list, which is a set of attributes it accepts as input and will write to the resource.
By default, this is all public, writable attributes.
And there is an optional map argument on all code interfaces that will pass those values through.
So if you took out the args
on your code interface, remove the argument/change from the action, you can then say update_stats(%{attr1: …, attr2: …})
And you can also say args: [:attribute]
to make one attribute a positional argument, and then pass the map of optional stuff after thatha it was that easy...
For some reason that didn't come across to me in the action docs https://ash-hq.org/docs/guides/ash/latest/topics/actions
Do you know where I can do a deep dive?
Hmm... it seems that if I leave an attribute out, all the other attributes are being set to nil. Is that expected?
What do you mean by leave an attribute out?
TBH if this isn’t made clear in the actions guide then we should improve that for sure.
False alarm.
I passed in to update :value, and the returned wallet had every other attribute set to nil. But in the db, the data was correct.
interesting...were you selecting any data?
Yea you can see the logs here:
what is
wallet
that you're originally passing in?Hmm I cleared my console, before this. But that's probably it. I'm passing in the original wallet that I queried from the db.
So basically I queried elixir
iex(39)> Leaderboard.Data.Wallet.update_stats(wallet, stats)
commit []
{:ok,
#Leaderboard.Data.Wallet<
meta: #Ecto.Schema.Metadata<:loaded, "wallets">,
id: "318fd4a8-5a4d-47d5-80c2-613207a3d6fc",
address: "SPAX2SZCDFTVV76SR4JY4RYEPC5PBH2QAHEJXHTF",
chain: :stacks,
bought_usd_volume: 1.0,
bought_volume: 2.0,
holdings_count: 3,
holdings_listed_count: nil,
realized_profit_loss: nil,
realized_usd_profit_loss: nil,
sold_usd_volume: nil,
sold_volume: nil,
unrealized_profit_loss: nil,
unrealized_usd_profit_loss: nil,
usd_value: nil,
value: nil,
timestamp: nil,
block_height: 10,
aggregates: %{},
calculations: %{},
order: nil,
...
>}```
And then the next time I did the update, I passed in the old wallet variable.
So I'm assuming the logs I see here, are not a return of the updated data from the db, but rather just showing what the update will look like?
I might have lost track of the specific issue. It sounds like things are working properly? If you pass in a record to be updated though, and attributes are selected, it should not come back w/
nil
on an update.Yea I guess the order is:
First update of wallet, setting
Second update of wallet:
Just sets usd_value.
As you can see, the previous bought_usd_volume etc... is now nil.
I'm assuming this is because I'm passing in the original wallet before the update. So the logs that I'm seeing are not a return of the wallet object on a round trip from the db. But rather it is just logging what the change will look like
Because when I query the wallet again, I get all the updates:
not sure what the logs are that you're talking about. If you're talking about the SQL logger it just logs the sql statements, nothing more/less. But yeah, you likely want to pass the wallet through each time
you're right that that is the reason for
nil
values in the second updateOk great! Really appreciate the help Zach
my pleasure 😄