sezaru

sezaru

In my system, I have the following resources:

defmodule Core.Feedbacks.Student do
  relationships do
    alias Core.Feedbacks

    has_many :feedbacks, Feedbacks.Feedback

    many_to_many :classes, Feedbacks.Class do
      through Feedbacks.StudentClass
      join_relationship :student_classes

      source_attribute_on_join_resource :student_id
      destination_attribute_on_join_resource :class_id
    end
  end
end

defmodule Core.Feedbacks.Class do
  relationships do
    alias Core.Feedbacks

    has_many :feedbacks, Feedbacks.Feedback

    many_to_many :students, Feedbacks.Student do
      through Feedbacks.StudentClass

      source_attribute_on_join_resource :class_id
      destination_attribute_on_join_resource :student_id
    end
  end
end

defmodule Core.Feedbacks.StudentClass do
  relationships do
    alias Core.Feedbacks.{Student, Class}

    belongs_to :student, Student do
      primary_key? true
      allow_nil? false
      attribute_writable? true
    end

    belongs_to :class, Class do
      primary_key? true
      allow_nil? false
      attribute_writable? true
    end
  end
end

defmodule Core.Feedbacks.Feedback do
  relationships do
    alias Core.Feedbacks

    belongs_to :student, Feedbacks.Student do
      allow_nil? false
      attribute_writable? true
    end

    belongs_to :class, Feedbacks.Class do
      allow_nil? false
      attribute_writable? true
    end
  end
end

As you can see, the Student resource has a many_to_many relationship with the Class resource and both resources have a has_many relationship with the Feedback resource.

I wan´t to create an aggregate that will tell me how many feedbacks a student has inside a class.

If I just wanted all the student feedbacks, an aggregate like this in my Student resource would work just fine:

count :total_feedbacks, :feedbacks

But I want to count all the feedbacks that are from that student and from an specific class, meaning that I would to, somehow, pass an :class_id argument to inside that count aggregate filter expression.

I’m not sure how to solve that using aggregates

Showing Posts 1 to 5

zachdaniel

zachdaniel

Creator of Ash

You can’t do that with standard aggregates, but you can do that with the new(-ish) inline aggregates syntax.

calculate :total_feedbacks, :integer, expr(
  count(feedbacks, query: [filter: expr(class_id == ^arg(:class_id))])
) do
  argument :class_id, :uuid, allow_nil?: false
end
sezaru

sezaru OP

As always, worked like a charm! :smile:

sezaru

sezaru OP

Hey @zachdaniel, I have another case where I’m not 100% sure how to solve it.

The calculations with inline aggregates worked great, but what if I want to aggregate something from one of the relationships?

For example.

Let’s say that the Class resource has a has_many relationship with another resource called Lessons.

I want to have a calculation in my Student resource that would give me number of lessons inside that class that a student is in.

What I tried to do was to first create an aggregate in the Class resource like this:

  aggregates do
    count :total_lessons, :lessons
  end

And then, inside the Student resource, I tried to create a calculation using that:

    calculate :total_lessons_in_class,
              :integer,
              expr(first(classes, query: [filter: expr(class_id == ^arg(:class_id))]).total_lessons) do
      argument :class_id, :string, allow_nil?: false
    end

But that doesn’t work.

I also tried adding a calculation that would return the current class and then I would be able to get the total_lessons field directly from it:

  calculate :current_class, :struct, expr(first(classes, query: [filter: expr(id == ^arg(:class_id))])) do
      constraints [instance_of: Core.Feedbacks.Class]

      argument :class_id, :string, allow_nil?: false
    end

But using the first aggregate doesn´t seem to be working, not sure if I’m doing something wrong with it.

zachdaniel

zachdaniel

Creator of Ash

So, what I’m about to show you wont’ work, but what you would want is this:

    calculate :total_lessons_in_class,
              :integer,
              expr(first(classes, query: [filter: expr(class_id == ^arg(:class_id))], field: :total_lessons)) do
      argument :class_id, :string, allow_nil?: false
    end

However, you can’t use an aggregate as the field of another aggregate. However, you can do this:

    calculate :total_lessons_in_class,
              :integer,
              expr(count(classes.lessons, query: [filter: expr(class_id == ^arg(:class_id))])) do
      argument :class_id, :string, allow_nil?: false
    end

Assuming that lesson has class_id on it.

sezaru

sezaru OP

Yep, this worked great, thanks again!

— All posts loaded —

Where Next? Top

Trending in Questions Top

stjefim
Hello! Suppose you are building workflow (order / task / payment) processing system with the following requirements: Each workflow con...
New
water
I’m aware of 2 such projects, are there others? git: GitHub - team-alembic/realworld: A fullstack Phoenix LiveView application with back...
New
itzmidinesh
Hi all, I’m working on a Phoenix project where I need to make external HTTP requests and I’m trying to choose between Req and HTTPoison....
New
pragdave
How do I tell Hologram not to escape HTML when substituting into templates? {Textile.render(@product.long_description)} escapes the HTM...
New
rlipscombe
I’d like to create a file with 600 permissions (rw-------), but there’s a race condition if I create it and then change the permissions. ...
New
leoschweizer
Hi, we run different LLM models across a cluster, with each node loading a configurable subset. Model-specific queues let nodes consume ...
New
rlipscombe
When I use Mix.install with a git dependency, using git@github.com:... how do I change the SSH identity used? I’ve got two Github accoun...
New

Other Trending Topics Top

dominicletz
Hey there, I haven’t seen a list of useful Elixir specific skills for the popular AI tools yet so I’m starting one here with my first. ...
New
raa-ziq
Hi everyone :waving_hand: I wanted to share something I’ve been building — NowBlind, a random chat app designed to help people discover ...
New
mudasobwa
I fully migrated to my own harness from Anthropic/Gemini and I think it’s time to share it. Welcome DSH, the DeepSeek Harness, fully writ...
New
KristerV
Hey. Is there anyone here who creates agents in their apps? Not talking about using agents, but creating them. I’m finding it pretty diff...
New
OndrejValenta
(I just needed to vent somewhere and LinkedIn is full of hope, or hype, I’m not sure which exactly) AI dream has many faces, but general...
New
kip
Localize is the next generation localisation library for Elixir. Think of it as ex_cldr version 3.0. The first version will be released ...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews