Calculate only on a read action

Hello everyone. Just starting out with Ash and so far, so good. I'm starting to figure a few things out. What I'm currently struggling with is having a calculate only run on a read action. I have an embedded resource where I'm using a calculate to generate a URL from another field. Here is a snippet from parent resource where the embedded is loaded:
attributes do
...
attribute :myembed, MyEmbed do
constraints [load: [:url]]
allow_nil? false
end
...
end
attributes do
...
attribute :myembed, MyEmbed do
constraints [load: [:url]]
allow_nil? false
end
...
end
That works and I get the calculated :url field injected into the embedded resource when reading items. Yay! My issue is that the :url field is also being written to the embedded field on create. How can I have the calculate run only during the read actions? I tried using a various Ash.Query functions in aprepare in the read action of the embedded resource as well as in the read action of the parent, but couldn't get it load and/or not generate errors.
17 Replies
ZachDaniel
ZachDaniel3y ago
🤔 so when you write, its writing url into the database? But url is a calculation on the embedded resource? That sounds like a bug to me
l00ker
l00kerOP3y ago
Yes. It generates the url field when creating the parent resource.
ZachDaniel
ZachDaniel3y ago
So how does this manifest? Does the url field not get updated properly later on?
l00ker
l00kerOP3y ago
I haven't tried updating yet. I'm just starting out as I mentioned, so I could be doing something wrong.
ZachDaniel
ZachDaniel3y ago
I'm still not quite sure what the behavior we're trying to avoid is. Is it the fact that the url calcualtion is expensive so you don't want it to run on creates?
l00ker
l00kerOP3y ago
I'm generating the url from another field in the embedded with part of the url (scheme, host, etc.) coming from the application and it might change so I don't want it in the DB.
ZachDaniel
ZachDaniel3y ago
Got it. And you've confirmed that its actually in the database?
l00ker
l00kerOP3y ago
I only want the path and I generate the full url to send to the client.
ZachDaniel
ZachDaniel3y ago
I think we might just be loading the calculation when you do the create, not necessarily actually storing the value
l00ker
l00kerOP3y ago
Yes. It's in the DB.
ZachDaniel
ZachDaniel3y ago
Got it, that is a bug calculations should never be stored in the database thats the whole point of them 😆 Can I see your embedded resource/the calculation?
l00ker
l00kerOP3y ago
I tested with data I have in the DB before I tried to create And on reads, it was generating the url field.
defmodule Media.Ash.Objects.Filemeta do
use Ash.Resource,
data_layer: :embedded

attributes do
uuid_primary_key :id

attribute :crtime, :naive_datetime, allow_nil?: false
attribute :file_size, :integer, allow_nil?: false
attribute :full_path, :string, allow_nil?: false
attribute :md5, :string, allow_nil?: false
attribute :mime, :string, allow_nil?: false
attribute :mode, :integer, allow_nil?: false
attribute :mtime, :naive_datetime, allow_nil?: false
end

calculations do
calculate :url, :string, {Media.Ash.Objects.CdnUrl, path: :full_path}
end
end
defmodule Media.Ash.Objects.Filemeta do
use Ash.Resource,
data_layer: :embedded

attributes do
uuid_primary_key :id

attribute :crtime, :naive_datetime, allow_nil?: false
attribute :file_size, :integer, allow_nil?: false
attribute :full_path, :string, allow_nil?: false
attribute :md5, :string, allow_nil?: false
attribute :mime, :string, allow_nil?: false
attribute :mode, :integer, allow_nil?: false
attribute :mtime, :naive_datetime, allow_nil?: false
end

calculations do
calculate :url, :string, {Media.Ash.Objects.CdnUrl, path: :full_path}
end
end
I'm testing Ash in a current project thus the Ash in the module names 🙂 I created the Media.Ash.Objects.CdnUrl calculation because I'm calling into another module that takes the full_path and replaces part of it and returns the url
ZachDaniel
ZachDaniel3y ago
Makes perfect sense 👍 can you try the main branch of ash and see if that resolves your issue?
l00ker
l00kerOP3y ago
Sure. I'll give it a try in a bit and let you know. Thank you Zack! Oops... Zach... sorry 😦
ZachDaniel
ZachDaniel3y ago
not a problem 😆 it happens all the time Hopefully that fixes the issue. I don't know why we were explicitly storing calculations, but I can't think of a good reason that we should be
l00ker
l00kerOP3y ago
Okay. The main branch fixed it. Now I will continue on my Ash journey! Thanks for all your work Zach!
ZachDaniel
ZachDaniel3y ago
🥳

Did you find this page helpful?