Access calculation from relation caluclation.

I got a resource A the defines
calculate :access_count, :integer, Accounts.User.Calculations.AccessCount do
public? true
end
calculate :access_count, :integer, Accounts.User.Calculations.AccessCount do
public? true
end
And I got resource B that want to expose the same field through the association
calculate :access_count, :integer, expr(b.access_count) do
public? true
sortable? true
end
calculate :access_count, :integer, expr(b.access_count) do
public? true
sortable? true
end
Looks like I cannot do this, should I just define the original calculation in B instead?
18 Replies
Marco Dell'Olio
Marco Dell'OlioOP•3mo ago
The reason I need to expose the same attribute is to being able to sort B by that specific field
ZachDaniel
ZachDaniel•3mo ago
You can do it but only if they are all expression calculations
Marco Dell'Olio
Marco Dell'OlioOP•3mo ago
no that source calcualtion is a module
ZachDaniel
ZachDaniel•3mo ago
It can still be an expression calculation Just has to define expression/2
Marco Dell'Olio
Marco Dell'OlioOP•3mo ago
ok so has to be exclusively at the database level
ZachDaniel
ZachDaniel•3mo ago
Yep
Marco Dell'Olio
Marco Dell'OlioOP•3mo ago
Thanks i'm not sure if a bug but setting the share context in the parent resource
prepare fn query, context ->
query
|> Ash.Query.set_context(%{
shared: %{time_range: query.arguments[:time_range]}
})
end
prepare fn query, context ->
query
|> Ash.Query.set_context(%{
shared: %{time_range: query.arguments[:time_range]}
})
end
this context is available in def calculate(records, _opts, context) do but not in def expression(opts, context) do
ZachDaniel
ZachDaniel•3mo ago
in the source_context key? May be a bug yes
Marco Dell'Olio
Marco Dell'OlioOP•3mo ago
one more thing I thought that implementing def expression(_opts, context) do would automatically run it but is still asking to implement calculate I can take care of that bug
ZachDaniel
ZachDaniel•3mo ago
You shouldn't have to implement calculate
Marco Dell'Olio
Marco Dell'OlioOP•3mo ago

** (UndefinedFunctionError) function OrganizationMembership.Calculations.AccessCount.calculate/3 is undefined or private

** (UndefinedFunctionError) function OrganizationMembership.Calculations.AccessCount.calculate/3 is undefined or private
calculate :access_count,
:integer,
OrganizationMembership.Calculations.AccessCount do
public? true
sortable? true
end
calculate :access_count,
:integer,
OrganizationMembership.Calculations.AccessCount do
public? true
sortable? true
end
fwiw this is loaded from. graphql query
ZachDaniel
ZachDaniel•3mo ago
🤔 question what if you do mix compile --force? Can I see the calculation?
Marco Dell'Olio
Marco Dell'OlioOP•3mo ago
def expression(_opts, context) do
time_range = context.source_context.time_range

expr(
count(
user.access_logs,
cond do
^time_range == :today ->
expr(
user.access_logs.last_accessed_at >= start_of_day(today()) and
user.access_logs.last_accessed_at <= date_add(start_of_day(today()), 1, :day)
)

^time_range == :week ->
expr(
user.access_logs.last_accessed_at >= start_of_week(today()) and
user.access_logs.last_accessed_at <= date_add(start_of_week(today()), 1, :week)
)

^time_range == :month ->
expr(
user.access_logs.last_accessed_at >= start_of_month(today()) and
user.access_logs.last_accessed_at <= date_add(start_of_month(today()), 1, :month)
)
end
)
)
end
def expression(_opts, context) do
time_range = context.source_context.time_range

expr(
count(
user.access_logs,
cond do
^time_range == :today ->
expr(
user.access_logs.last_accessed_at >= start_of_day(today()) and
user.access_logs.last_accessed_at <= date_add(start_of_day(today()), 1, :day)
)

^time_range == :week ->
expr(
user.access_logs.last_accessed_at >= start_of_week(today()) and
user.access_logs.last_accessed_at <= date_add(start_of_week(today()), 1, :week)
)

^time_range == :month ->
expr(
user.access_logs.last_accessed_at >= start_of_month(today()) and
user.access_logs.last_accessed_at <= date_add(start_of_month(today()), 1, :month)
)
end
)
)
end
ZachDaniel
ZachDaniel•3mo ago
do you have use Ash.Resource.Calculation in your module?
Marco Dell'Olio
Marco Dell'OlioOP•3mo ago
yes mix compile --force didn't help i'm trying to change the implementation ok expr(count(user.access_logs)) works just fine so is an error with the expression not being raised?
ZachDaniel
ZachDaniel•3mo ago
🤔 I'm not sure, I've never seen it complain about that having expression/2 should be all you need
Marco Dell'Olio
Marco Dell'OlioOP•3mo ago
so removing the cond block allows to raise this error
* ** (Postgrex.Error) ERROR 42725 (ambiguous_function) function date_trunc(unknown, unknown) is not unique
* ** (Postgrex.Error) ERROR 42725 (ambiguous_function) function date_trunc(unknown, unknown) is not unique
was the block not allowing the compilation of expression/2, (?) ok so I was able to resolve it remove the date builtins functions, so I assume for some reason the cond do was preventing the error to pop out
ZachDaniel
ZachDaniel•3mo ago
strange Can you open an error w/ a stacktrace where it was trying to access \.calculate?

Did you find this page helpful?