Ash FrameworkAF
Ash Framework3mo ago
7 replies
Shawn McCool

Can not use Ash Resource action with Ash Admin without Attributes

I have defined an ash resource that represents a remote api. I have an action that makes a specific query to the API and use typed structs for the result. I'd like to be able to interact with this through ash admin. But it is giving me an error that there's no struct. This appears to be because I have no attributes on this resource. Must I declare attributes to the resource? Is there a flaw in my approach?

The moment I add the following to my resource, it works fine:
  attributes do
    attribute :id, :string, allow_nil?: true
  end


I may be going about this completely incorrectly, I would be interested in ANY feedback as this is exploratory work.

Resource
defmodule DataHoard.Ingestion.Gmail do
  use Ash.Resource,
    otp_app: :data_hoard,
    domain: DataHoard.Ingestion

  alias DataHoard.Ingestion.Gmail.MessagesList.Message

  resource do
    require_primary_key? false
  end

  actions do
    action :messages_list, {:array, DataHoard.Ingestion.Gmail.MessagesList.Message} do
      argument :google_oauth_token, :string

      run fn input, _context ->
        with {:ok, messages_list} <-
               DataHoard.Integrations.Google.Gmail.get_messages_list(
                 input.arguments.google_oauth_token
               ) do
          messages = Enum.map(messages_list.messages, &Message.from_messages_list/1)
          {:ok, messages}
        else
          {:error, error} -> {:error, error.message}
        end
      end
    end
  end
end

Domain
defmodule DataHoard.Ingestion do
  use Ash.Domain,
    otp_app: :data_hoard,
    extensions: [AshAdmin.Domain]

  admin do
    show? true
  end

  resources do
    resource DataHoard.Ingestion.Gmail
  end
end

Error
[error] ** (UndefinedFunctionError) function DataHoard.Ingestion.Gmail.__struct__/0 is undefined or private
    (data_hoard 0.1.0) DataHoard.Ingestion.Gmail.__struct__()
    (ash_phoenix 2.3.17) lib/ash_phoenix/form/form.ex:515: AshPhoenix.Form.for_action/3
    (ash_admin 0.13.23) lib/ash_admin/components/resource/generic_action.ex:248: AshAdmin.Components.Resource.GenericAction.update/2
    (phoenix_live_view 1.1.16) lib/phoenix_live_view/utils.ex:492: Phoenix.LiveView.Utils.maybe_call_update!/3
    (elixir 1.19.1) lib/enum.ex:1688: Enum."-map/2-lists^map/1-1-"/2
    (phoenix_live_view 1.1.16) lib/phoenix_live_view/diff.ex:859: anonymous fn/4 in Phoenix.LiveView.Diff.render_pending_components/6
    (telemetry 1.3.0) /home/shawn/src/data-hoard/deps/telemetry/src/telemetry.erl:324: :telemetry.span/3
    (phoenix_live_view 1.1.16) lib/phoenix_live_view/diff.ex:854: anonymous fn/4 in Phoenix.LiveView.Diff.render_pending_components/6
    (stdlib 7.1) maps.erl:894: :maps.fold_1/4
    (phoenix_live_view 1.1.16) lib/phoenix_live_view/diff.ex:813: Phoenix.LiveView.Diff.render_pending_components/6
    (phoenix_live_view 1.1.16) lib/phoenix_live_view/diff.ex:153: Phoenix.LiveView.Diff.render/4
    (phoenix_live_view 1.1.16) lib/phoenix_live_view/static.ex:291: Phoenix.LiveView.Static.to_rendered_content_tag/4
    (phoenix_live_view 1.1.16) lib/phoenix_live_view/static.ex:171: Phoenix.LiveView.Static.do_render/4
    (phoenix_live_view 1.1.16) lib/phoenix_live_view/controller.ex:39: Phoenix.LiveView.Controller.live_render/3
    (phoenix 1.8.1) lib/phoenix/router.ex:416: Phoenix.Router.__call__/5
    (data_hoard 0.1.0) lib/data_hoard_web/endpoint.ex:1: DataHoardWeb.Endpoint.plug_builder_call/2
    (data_hoard 0.1.0) deps/plug/lib/plug/debugger.ex:155: DataHoardWeb.Endpoint."call (overridable 3)"/2
    (data_hoard 0.1.0) lib/data_hoard_web/endpoint.ex:1: DataHoardWeb.Endpoint.call/2
    (phoenix 1.8.1) lib/phoenix/endpoint/sync_code_reload_plug.ex:22: Phoenix.Endpoint.SyncCodeReloadPlug.do_call/4
    (bandit 1.8.0) lib/bandit/pipeline.ex:131: Bandit.Pipeline.call_plug!/2
 request_id=GHfbY0jAql9wLeEAAB9B mfa=Bandit.Pipeline.handle_error/7
Solution
Short version: yes, you need to declare at least one attribute so Ash can generate a struct for your resource
Was this page helpful?