Calculations: Add `field?: false` option to exclude from Resource struct fields
Code of Conduct
- [x] I agree to follow this project's Code of Conduct
AI Policy
- [x] I agree to follow this project's AI Policy, or I agree that AI was not used while creating this issue.
Is your feature request related to a problem? Please describe.
Currently, all calculations defined on a resource become struct fields. Sometimes you want to create calculation that are only meant to be composed with other calculations within the resource and don't need to be included in the struct as fields.
Describe the solution you'd like
Introduce a field?: false option (defaulting to true) that:
- Excludes the calculation from the resource struct fields. Reducing struct field clutter.
- Prevents the calculation from being directly loadable via queries
- Still allows the calculation to be referenced in expressions within the resource
- Maintains all existing calculation functionality
Example
calculate :average_things, :float, expr(sum_of_things / count_of_things)
calculate :count_of_things, :integer, expr(count(things)) do
field? false
end
calculate :sum_of_things, :integer, expr(sum(things, field: :value)) do
field? false
end
In this example:
- Only :average_things would be loadable and appear in the struct
- :count_of_things and :sum_of_things remain available for internal composition
Describe alternatives you've considered
No response
Additional context
Suggested by Zach in Discord as a neat feature to support
I'm taking this one
Adding some thoughts on the solution.
Adding the DSL and excluding the calculation from the schema generation is straightforward.
Making it non-loadable but usable in expressions is going to be tricky for a couple reasons.
- The internals are using the public 'Ash.load', so there's not a good way to validate without affecting the internal usages. May have to move the 'Ash.load' logic into a separate module so validation logic can be put on the public interface.
- Accessing the calculations currently expect it to be on the struct, so have to figure out how allow it in the map for internal logic and strip it before it's returned to the caller.
I think it's achievable, but the PR will be large. I need to figure out how to break this into multiple PRs so it can be merged incrementally before we "release" the feature. Meaning it can be "dark-released" but not visible to users until it is fully ready. I don't want to have a massive PR that will take forever to review and cause unnecessary risk.
That makes sense to me, thank you for looking into it 🔥