meh / amnesia

Mnesia wrapper for Elixir.
693 stars 68 forks source link

Dynamic table names with `deftable` aren't possible #44

Open EugZol opened 8 years ago

EugZol commented 8 years ago

Hello!

I'm trying to create bunch of tables at once with the following code:

use Amnesia

defdatabase Database do
  for name <- [:"Elixir.TestTable", :"Elixir.AnotherTestTable"] do
    deftable name, [{ :id, autoincrement }, :user_id], type: :set do
    end
  end
end

That gives me the following error:

== Compilation error on file web/models/database.ex ==
** (CompileError) web/models/database.ex:5: undefined function name/0
    (stdlib) lists.erl:1337: :lists.foreach/2
    web/models/database.ex:5: anonymous fn/2 in :elixir_compiler_2.__MODULE__/1
    (elixir) lib/enum.ex:1473: Enum."-reduce/3-lists^foldl/2-0-"/3
    web/models/database.ex:4: (module)
    (elixir) lib/kernel/parallel_compiler.ex:100: anonymous fn/4 in Kernel.ParallelCompiler.spawn_compilers/8

I noticed that this code, however, is compiled correctly:

defdatabase Database do
  for name <- [:"Elixir.TestTable", :"Elixir.AnotherTestTable"] do
    defmodule name, do: []
  end
end

Given that, I decided to ask that question in the Amnesia tracker, not in some general Elixir thread.

How do I do table definitions with dynamic names correctly?

meh commented 8 years ago

I don't remember the details, but this has to do with macros.

Basically deftable is a macro, and the passed name is unquoted, so it tries to call a name/0 function that does not exist.

Ask a general question in the main channel and report back please, a long time ago there were unquote fragments, I don't know what the story is currently.

DerKastellan commented 8 years ago

Actually I ran over the same issue when defining my own defconst macro (similar to Record.defrecord) and using bind_quoted in your quote block like this

quote bind_quoted: [x: x] do

helped resolve the issue for me. Because when doing something like Record.defrecord I also did a loop like the above. Without the bind_quoted I found no way to make it work.

http://elixir-lang.org/docs/stable/elixir/Kernel.SpecialForms.html#quote/2