Working with AshArchival

I'd like to to implement a filter that allows the user to read their archived records. I'm trying this:
Ash.Query.filter_input(query, %{"archived_at" => %{"is_nil" => false}})
Ash.Query.filter_input(query, %{"archived_at" => %{"is_nil" => false}})
But for some reason I get no results I tried the exclude_read_actions option
archive do
attribute :archived_at
exclude_read_actions :list_contacts
end
archive do
attribute :archived_at
exclude_read_actions :list_contacts
end
But still get no results for my action
action :list_contacts, :map do
argument :search, :string
argument :filter, :map
argument :sort, :string
argument :page, :string, default: "1"

run {MyApp.Actions.Listing,
resource: __MODULE__, search_by: [:name], serializer: :serialize_contacts}
end
action :list_contacts, :map do
argument :search, :string
argument :filter, :map
argument :sort, :string
argument :page, :string, default: "1"

run {MyApp.Actions.Listing,
resource: __MODULE__, search_by: [:name], serializer: :serialize_contacts}
end
I do get the results when I try to read unarchived records though Note: I'm not using the base_filter
Solution:
So if you make like an :include_archived action for example, exclude that action in the ash archival DSL, you can then pass action: :include_archived to Ash.read
Jump to solution
5 Replies
ZachDaniel
ZachDaniel3mo ago
That :list_contacts action isn't the one doing the filtering its whatever read action your generic action calls on the inside that is doing the filtering
Joan Gavelán
Joan GavelánOP3mo ago
Mm this is my implementation
def run(input, opts, context) do
resource = opts[:resource]
search_by = opts[:search_by]
serializer = opts[:serializer]

# Base query
query = Ash.Query.new(resource)

# Apply search if provided
query =
if search = input.arguments[:search] do
filter = build_search_filter(search_by, search)
Ash.Query.filter(query, ^filter)
else
query
end

query =
Ash.Query.filter(query, %{"archived_at" => %{"is_nil" => false}}) # Testing the archive filter

# Apply sorting if provided
query =
if input.arguments[:sort] do
Ash.Query.sort_input(query, input.arguments[:sort])
else
Ash.Query.default_sort(query, created_at: :desc)
end

# Calculate pagination
limit = 15
current_page = input.arguments[:page] |> String.to_integer()
offset = (current_page - 1) * limit

# Apply pagination
query = Ash.Query.page(query, limit: limit, offset: offset, count: true)

# Execute the query
with {:ok, page} <- Ash.read(query, actor: context.actor, tenant: context.tenant) do
total_pages = ceil(page.count / page.limit)

result = %{
data: apply(LamashkaWeb.Serializers, serializer, [page.results]),
total_pages: total_pages
}

{:ok, result}
end
end
def run(input, opts, context) do
resource = opts[:resource]
search_by = opts[:search_by]
serializer = opts[:serializer]

# Base query
query = Ash.Query.new(resource)

# Apply search if provided
query =
if search = input.arguments[:search] do
filter = build_search_filter(search_by, search)
Ash.Query.filter(query, ^filter)
else
query
end

query =
Ash.Query.filter(query, %{"archived_at" => %{"is_nil" => false}}) # Testing the archive filter

# Apply sorting if provided
query =
if input.arguments[:sort] do
Ash.Query.sort_input(query, input.arguments[:sort])
else
Ash.Query.default_sort(query, created_at: :desc)
end

# Calculate pagination
limit = 15
current_page = input.arguments[:page] |> String.to_integer()
offset = (current_page - 1) * limit

# Apply pagination
query = Ash.Query.page(query, limit: limit, offset: offset, count: true)

# Execute the query
with {:ok, page} <- Ash.read(query, actor: context.actor, tenant: context.tenant) do
total_pages = ceil(page.count / page.limit)

result = %{
data: apply(LamashkaWeb.Serializers, serializer, [page.results]),
total_pages: total_pages
}

{:ok, result}
end
end
I'm guessing there is an option I need to pass to the Ash.read\2 call there?
ZachDaniel
ZachDaniel3mo ago
By default Ash.read uses the primary read action (if given a query that is not already built for a specific action)
Solution
ZachDaniel
ZachDaniel3mo ago
So if you make like an :include_archived action for example, exclude that action in the ash archival DSL, you can then pass action: :include_archived to Ash.read
Joan Gavelán
Joan GavelánOP3mo ago
Nice, that works, thanks!

Did you find this page helpful?