Honestly it just depends on how you’re using it. For instance, if you’ve got a live view somewhere, you can do this:
assign(socket, :published_posts, Post.published!())
But you can also do
assign(socket, :published_posts, Post.read!(query: Ash.Query.filter(published == true))
If you are considering making a module somewhere with functions like:
def published_posts do
Post.read!(query: Ash.Query.filter(published == true)
end
Then at that point I would suggest making it an action, i.e
read :published do
filter expr(published == true)
end
If you need caller-level composition, then calculations are a good choice.
I know it would be nice if there was “one right answer” but in these case it often comes down to what kind of interface you would need. The general rule of thumb though is: when in doubt, put stuff in an action that does specifically what you need.






















