amnesia icon indicating copy to clipboard operation
amnesia copied to clipboard

(UndefinedFunctionError) function :erl_eval.match1/4 is undefined or private

Open tomazzlender opened this issue 8 years ago • 7 comments

When I try to use example code in IEx

Amnesia.transaction do
john = %User{name: "John", email: "[email protected]"} |> User.write
end

error is raised.

** (UndefinedFunctionError) function :erl_eval.match1/4 is undefined or private
       (uym) User.write(%User{email: "[email protected]", id: nil, name: "John"})
    (stdlib) erl_eval.erl:670: :erl_eval.do_apply/6
    (stdlib) erl_eval.erl:438: :erl_eval.expr/5
    (mnesia) mnesia_tm.erl:835: :mnesia_tm.apply_fun/3
    (mnesia) mnesia_tm.erl:810: :mnesia_tm.execute_transaction/5

in lib/database.ex is example code from README. Database was created using

mix amnesia.create -db Database --disk

Content of database.ex

use Amnesia
defdatabase Database do
  deftable User

  deftable Message, [:user_id, :content], type: :bag do
    @type t :: %Message{user_id: integer, content: String.t}

    def user(self) do
      User.read(self.user_id)
    end

    def user!(self) do
      User.read!(self.user_id)
    end
  end

  deftable User, [{ :id, autoincrement }, :name, :email], type: :ordered_set, index: [:email] do
    @type t :: %User{id: non_neg_integer, name: String.t, email: String.t}

    def add_message(self, content) do
      %Message{user_id: self.id, content: content} |> Message.write
    end

    def add_message!(self, content) do
      %Message{user_id: self.id, content: content} |> Message.write!
    end

    def messages(self) do
      Message.read(self.id)
    end

    def messages!(self) do
      Message.read!(self.id)
    end
  end
end

defmodule User do
  defstruct id: nil, name: nil, email: nil
end

defmodule Message do
  defstruct user_id: nil, content: nil
end

I use Elixir 1.3.2, {:amnesia, "~> 0.2.4"}.

What could be wrong?

tomazzlender avatar Aug 16 '16 22:08 tomazzlender

What Erlang version? I've never seen this kind of error before.

meh avatar Aug 16 '16 23:08 meh

Is it due to defining User and Message twice with defmodule and deftable?

jmerriweather avatar Aug 17 '16 00:08 jmerriweather

That shouldn't be an issue, the actual module name inside the defdatabase gets prefixed with the database module name, so they don't collide.

But now that you point that out I'm not entirely sure what the User inside the transaction is referring to.

meh avatar Aug 17 '16 00:08 meh

@meh it is Erlang/OTP version 19, more specifically 19.0.2.

Modules User and Message are defined because otherwise I got this error.

User.__struct__/1 is undefined, cannot expand struct User

I tried now running code prefixed with database name:

Amnesia.transaction do
john = %Database.User{name: "John", email: "[email protected]"} |> Database.User.write
end

And result was :badarg.

tomazzlender avatar Aug 17 '16 07:08 tomazzlender

Hm, not sure why I got :badarg before. I ran above code again and it worked OK.

So I guess the question is why prefixing module User inside Amnesia.transaction block does not work.

tomazzlender avatar Aug 17 '16 18:08 tomazzlender

Why do you define separate structs for User and Message? Can't you just alias Database.User and alias Database.Message at the top of your file?

jmerriweather avatar Aug 17 '16 22:08 jmerriweather

@jmerriweather agree, it doesn't make sense to have them.

Is using Database.User instead of User inside transaction block expected behaviour? If it is, I can update README example.

tomazzlender avatar Aug 19 '16 07:08 tomazzlender