before_action hooks cannot add loads or calculations during read actions
- Dominant language
- Elixir
- Stars
- 2.5k
- Forks
- 422
- Avg merge
- 23h 26m
- Merged PRs (30d)
- 46
Description
### Versions
Ash: master
Elixir: 1.18.3
Erlang/OTP 27
### Operating system
Mac
### Current Behavior
When using before_action hooks in read actions, attempting to add new loads (relationships) or calculations to the query does not work as expected. The loads and calculations added during before_action
are not properly processed in the read flow.
- Relationships loaded via Ash.Query.load/2 in a before_action callback are ignored
- Calculations added via Ash.Query.calculate/4 in a before_action callback are not executed
### Reproduction
Examples
1. Loading relationships in before_action:
```elixir
read :read_with_authors_before_action do
prepare(
before_action(fn query, _context ->
Ash.Query.load(query, [:author1, :author2])
end)
)
end
```
2. Adding calculations in before_action:
```elixir
read :read_with_calculation_before_action do
prepare(
before_action(fn query, _context ->
Ash.Query.calculate(
query,
:title_and_contents,
:string,
expr(title <> " - " <> contents)
)
end)
)
end
```
Here is a patch to `test/actions/read_test.exs` that showcases the bug.
```elixir
diff --git a/test/actions/read_test.exs b/test/actions/read_test.exs
index 9d450f33..42f1137b 100644
--- a/test/actions/read_test.exs
+++ b/test/actions/read_test.exs
@@ -76,6 +76,27 @@ defmodule Ash.Test.Actions.ReadTest do
prepare(build(load: [:author1, :author2]))
end
+ read :read_with_authors_before_action do
+ prepare(
+ before_action(fn query, _context ->
+ Ash.Query.load(query, [:author1, :author2])
+ end)
+ )
+ end
+
+ read :read_with_calculation_before_action do
+ prepare(
+ before_action(fn query, _context ->
+ Ash.Query.calculate(
+ query,
+ :title_and_contents,
+ :string,
+ expr(title <> " - " <> contents)
+ )
+ end)
+ )
+ end
+
read :read_with_unknown_intpus do
skip_unknown_inputs :*
end
@@ -212,6 +233,16 @@ defmodule Ash.Test.Actions.ReadTest do
fetched_post = Ash.get!(Post, post.id, action: :read_with_authors)
assert ^author1 = strip_metadata(fetched_post.author1)
end
+
+ test "before_action should be able to load relationships", %{post: post, author1: author1} do
+ fetched_post = Ash.get!(Post, post.id, action: :read_with_authors_before_action)
+ assert ^author1 = strip_metadata(fetched_post.author1)
+ end
+
+ test "before_action should be able to add calculations", %{post: post} do
+ fetched_post = Ash.get!(Post, post.id, action: :read_with_calculation_before_action)
+ assert "test - yeet" = fetched_post.calculations.title_and_contents
+ end
end
describe "Ash.get!/3" do
```
### Expected Behavior
- before_action hooks should be able to dynamically add loads and calculations to queries
- These dynamically added loads/calculations should be properly processed in the read pipeline
- The dynamically added loads/calculation should be authorized properly
Contributor guide
Research direction
Start with the reproduction and regression cases in test/actions/read_test.exs, then run the read-action tests to observe the failures. Trace how before_action updates are processed in the read flow; done means relationship loads and calculations added there are executed and authorized, with the new assertions passing.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- elixir
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 72/100