protocol Enumerable not implemented for #Ash.Changeset

I apologize if I abuse the support channel, please tell me if I should take this to #general or #archive-debugging I've ran into this issue on two different resources, and I'll detail both below. The tl;dr is: I define a code_interface for a resource, but when I call the function it fails with protocol Enumerable not implemented for #Ash.Changeset<action_type: :create... at (ash 2.6.27) lib/ash/changeset/changeset.ex:998: Ash.Changeset.cast_params/3 Resource the first I want to generate an "external id" on creation, so I expose a new acton via code_interface.
defmodule Telepai.App.Session do
attributes do
integer_primary_key(:id)
attribute :external_id, :string
attribute :settings, :string
end

actions do
defaults([:create, :read, :update, :destroy])

create :new do
accept([:settings])

change(fn changeset, _ ->
now = NaiveDateTime.utc_now() |> NaiveDateTime.to_string()
external_id = now |> HumanReadableIdentifierGenerator.fetch_human_readable_id!()

changeset |> Ash.Changeset.change_attribute(:external_id, external_id)
end)
end
end

code_interface do
define_for(__MODULE__)
define(:new)

# Note: if I don't define :create, compiler complains that
# `create/2` and `create!/2` are private or not defined
define(:create)
end
end
defmodule Telepai.App.Session do
attributes do
integer_primary_key(:id)
attribute :external_id, :string
attribute :settings, :string
end

actions do
defaults([:create, :read, :update, :destroy])

create :new do
accept([:settings])

change(fn changeset, _ ->
now = NaiveDateTime.utc_now() |> NaiveDateTime.to_string()
external_id = now |> HumanReadableIdentifierGenerator.fetch_human_readable_id!()

changeset |> Ash.Changeset.change_attribute(:external_id, external_id)
end)
end
end

code_interface do
define_for(__MODULE__)
define(:new)

# Note: if I don't define :create, compiler complains that
# `create/2` and `create!/2` are private or not defined
define(:create)
end
end
Then calling it:
> Telepai.App.Session.new!(%{settings: "aaa"})
protocol Enumerable not implemented for #Ash.Changeset<action_type: :create, action: :new, attributes: %{external_id: "pingo-frangimini-51", settings: "aaa"}, relationships: %{}...
...
(ash 2.6.27) lib/ash/changeset/changeset.ex:998: Ash.Changeset.cast_params/3
(ash 2.6.27) lib/ash/changeset/changeset.ex:747: Ash.Changeset.do_for_action/4
(telepai 0.1.0) lib/ash/code_interface.ex:533: Telepai.App.Session.create!/2
> Telepai.App.Session.new!(%{settings: "aaa"})
protocol Enumerable not implemented for #Ash.Changeset<action_type: :create, action: :new, attributes: %{external_id: "pingo-frangimini-51", settings: "aaa"}, relationships: %{}...
...
(ash 2.6.27) lib/ash/changeset/changeset.ex:998: Ash.Changeset.cast_params/3
(ash 2.6.27) lib/ash/changeset/changeset.ex:747: Ash.Changeset.do_for_action/4
(telepai 0.1.0) lib/ash/code_interface.ex:533: Telepai.App.Session.create!/2
I'll continue with the second resource in the comments
3 Replies
ZachDaniel
ZachDaniel3y ago
The support forum is exactly where all questions like this should go 🙂 👍 define_for should point at the api module that needs to be called define_for Telepai.App (if that is what your API module is called) Thats also why it was yelling at you about defining create, because it tries to call Api.create(....)
dmitriid
dmitriidOP3y ago
Resource the second This one is somewhat trickier as it only contains relationships to other resources:
defmodule Telepai.Users.Bookmark do
actions do
defaults([:create, :read, :update, :destroy])
end

attributes do
integer_primary_key(:id)
end

relationships do
belongs_to :user, Telepai.Users.User do
allow_nil?(false)
end

belongs_to :history, Telepai.App.History do
api(Telepai.App)
allow_nil?(false)
end
end

code_interface do
define_for(__MODULE__)

# I tried both deifnitions, but with the same result :)
define(:new, action: :create, args: [:user, :history])
define(:create)
end
end
defmodule Telepai.Users.Bookmark do
actions do
defaults([:create, :read, :update, :destroy])
end

attributes do
integer_primary_key(:id)
end

relationships do
belongs_to :user, Telepai.Users.User do
allow_nil?(false)
end

belongs_to :history, Telepai.App.History do
api(Telepai.App)
allow_nil?(false)
end
end

code_interface do
define_for(__MODULE__)

# I tried both deifnitions, but with the same result :)
define(:new, action: :create, args: [:user, :history])
define(:create)
end
end
Using it:
> Telepai.Users.Bookmark.new(1, 1)
** (Protocol.UndefinedError) protocol Enumerable not implemented for #Ash.Changeset<action_type: :create, action: :create, attributes: %{}...
...
(ash 2.6.27) lib/ash/changeset/changeset.ex:998: Ash.Changeset.cast_params/3
(ash 2.6.27) lib/ash/changeset/changeset.ex:747: Ash.Changeset.do_for_action/4
(telepai 0.1.0) lib/ash/code_interface.ex:496: Telepai.Users.Bookmark.create/2
> Telepai.Users.Bookmark.new(1, 1)
** (Protocol.UndefinedError) protocol Enumerable not implemented for #Ash.Changeset<action_type: :create, action: :create, attributes: %{}...
...
(ash 2.6.27) lib/ash/changeset/changeset.ex:998: Ash.Changeset.cast_params/3
(ash 2.6.27) lib/ash/changeset/changeset.ex:747: Ash.Changeset.do_for_action/4
(telepai 0.1.0) lib/ash/code_interface.ex:496: Telepai.Users.Bookmark.create/2
Oh my 😄 That's probably the reason 🙂 Ahahaha. YES. I should read the docs more carefully @Zach Daniel thank you!
ZachDaniel
ZachDaniel3y ago
My pleasure 😄

Did you find this page helpful?