How to do parameterized relationships in Ash?

Hi,

I have a User resource that has many Organizations. Organizations in turn have many Workgroups. A user can only be part of exactly one workgroup, per organization.

I would like to make it easy to get the workgroup for a specific organization_id for a user.

So I can fetch the user and workgroup easily if I have user_id and organization_id.

I know I can use filter on the relationship, e.g.

user.workgroups |> Ash.Query.filter(organization_id = ^organization_id) |> Ash.read_one!(...)

But I would like to be able to do something like:

User.get_by_id(user_id, load: [ workgroup_for_org:[organization_id: org_id ] ])

I know the answer is probably “Calculations”, but i can’t find any examples of returning Resources from calculations (if that is even possible).

So what I am looking for is something like a parameterized relationship.

You cannot parameterize relationships, but you can use calculations for this. However, if you use calculations for this, they have to be elixir-backed calculations, and so will not be filterable or sortable.

defmodule YourCalculation do
  use Ash.Resource.Calculation

  def load(calculations, _, context) do
    [workgroups: Ash.Query.filter(WorkGroup, organization_id == ^context.arguments.organization_id)]
  end

  def calculate(records, _, _) do
    Enum.map(records, &List.first(&1.workgroups)
  end
end
calculate :workgroup_for_org, :struct, YourCalculation do
  constraints instance_of: WorkGroup
  argument :organization_id, :uuid, allow_nil?: false
end

I’d like to expand these options, either with parameterized relationships or supporting returning records from calculation expressions directly in the future.