Ash FrameworkAF
Ash Framework3y ago
34 replies
Blibs

How to have a "virtual field" in a resource based from another resource?

I have a
Organization
resource that has a many to many relationship with my
User
resource.

That relationship is defined by this field in the
Organization
resource:

    many_to_many :users, User do
      through UserOrganization

      source_attribute_on_join_resource :organization_id
      destination_attribute_on_join_resource :user_id
    end


The UserOrganization resource has a special attribute inside of which defined if the user is an admin inside that organization:

defmodule UserOrganization do
  use Ash.Resource, data_layer: AshPostgres.DataLayer

  attributes do
    attribute :admin?, :boolean, allow_nil?: false, default: false
  end

  relationships do
    ...
  end

  postgres do
    table "users_organizations"
    ...
  end

  ...
end


What I want to do is to create a virtual attribute in the
Organization
resource that will tell if that user (the actor) is an admin.

My first approach was to add this new relationship to the resource:

    has_many :users_organizations, UserOrganization


So I can get access to the UserOrganization resource directly from
Organization
.

After that, I tried creating a calculation that would join that relationship and "extract" the admin? field:

  calculations do
    calculate :admin?, :boolean, expr(users_organizations.admin?)
  end


That don't work, and I'm not sure how exactly I would filter that calculation to only get the user_organization from the actor.

My second approach was to try an aggregate:

  aggregates do
    first :admin?, :users_organizations, :admin? do

      filter expr(user_id == ^actor(:id))
    end
  end


This also doesn't work, and aggregates also will generate a more complex query instead of simply doing the join by organization_id and
user_id
.

Any suggestion on how I can acchieve that?
Was this page helpful?