elixir-sqlite / sqlite_ecto2

Sqlite3 adapter for Ecto 2.2.x
https://hex.pm/packages/sqlite_ecto2
MIT License
120 stars 33 forks source link

Tried the tutorial but: `** (ArgumentError) argument error` #227

Closed ghost closed 5 years ago

ghost commented 5 years ago

Hi!

I tried to follow the tutorial but got stuck:

iex(1)> TUI.Database.insert(%TUI.Database.Notes{name: "jazzyb"})
** (ArgumentError) argument error
    (stdlib) :ets.lookup_element(Ecto.Registry, nil, 3)
    (ecto) lib/ecto/registry.ex:18: Ecto.Registry.lookup/1
    (ecto) lib/ecto/adapters/sql.ex:251: Ecto.Adapters.SQL.sql_call/6
    (ecto) lib/ecto/adapters/sql.ex:542: Ecto.Adapters.SQL.struct/8
    (ecto) lib/ecto/repo/schema.ex:547: Ecto.Repo.Schema.apply/4
    (ecto) lib/ecto/repo/schema.ex:213: anonymous fn/14 in Ecto.Repo.Schema.do_insert/4
defmodule TUI.Database do
  use Ecto.Repo,
    otp_app: :tui,
    adapter: Sqlite.Ecto2
end
defmodule TUI.Database.Tests do
  use Ecto.Schema

  schema "tests" do
      field :name, :string
      timestamps()
  end
end
config :tui, TUI.Database,
  adapter: Sqlite.Ecto2,
  database: "database.sqlite3"

config :tui, ecto_repos: [TUI.Database]
defp deps do
  [
    {:porcelain, "~> 2.0"},
    {:plug_cowboy, "~> 2.0"},
    {:nimble_parsec, "~> 0.4.0"},
    {:sqlite_ecto2, "~> 2.2"}
  ]
end

What could be wrong?

Thx!

ConnorRigby commented 5 years ago

It looks to me like your repo wasn't added to any supervision tree.

ConnorRigby commented 5 years ago

It does look like that is missing from the Readme. I'll add it tomorrow.

You should havea file called application.ex with a list of children. You will need to add Tui.Database to that list.

ghost commented 5 years ago

Thx for your quick answer!

Yes, I'm an newcomer to Elixir :-)

Well, here is my application.ex:

defmodule TUI.Application do
  # See https://hexdocs.pm/elixir/Application.html
  # for more information on OTP Applications
  @moduledoc false

  use Application

  def start(_type, _args) do
    # List all child processes to be supervised
    children = [
      {
        Plug.Cowboy,
        name: WebServer.Supervisor,
        scheme: :http,
        plug: TUI.Router,
        options: [ port: Application.get_env(:tui, :port) ]
      },
      {
        TUI.Database,
        name: Database.Supervisor
      }
    ]

    Supervisor.start_link(children, strategy: :one_for_one)
  end
end
ConnorRigby commented 5 years ago

I suggest putting the TUI.Database before the webserver, and remove the name option.

defmodule TUI.Application do
  # See https://hexdocs.pm/elixir/Application.html
  # for more information on OTP Applications
  @moduledoc false

  use Application

  def start(_type, _args) do
    # List all child processes to be supervised
    children = [
      TUI.Database,
      {
        Plug.Cowboy,
        name: WebServer.Supervisor,
        scheme: :http,
        plug: TUI.Router,
        options: [ port: Application.get_env(:tui, :port) ]
      }
    ]

    Supervisor.start_link(children, strategy: :one_for_one)
  end
end
ghost commented 5 years ago

It worked! Thx! I'm kind of puzzled that it did not work otherwise... I'm probably missing a lot there. The children are supposed to be independent, isn't ? Why the name would have any influence there? Should the config files and other places to be updated accordingly for the name option to work? Anyway, thank you! :+1:

TUI.Database.insert(%TUI.Database.Tests{name: "jazzyb"})

20:36:26.235 [debug] QUERY OK db=22.9ms queue=0.1ms
INSERT INTO "tests" ("name","inserted_at","updated_at") VALUES (?1,?2,?3) ;--RETURNING ON INSERT "tests","id" ["jazzyb", {{2018, 11, 28}, {19, 36, 26, 212121}}, {{2018, 11, 28}, {19, 36, 26, 212150}}]
{:ok,
 %TUI.Database.Tests{
   __meta__: #Ecto.Schema.Metadata<:loaded, "tests">,
   id: 1,
   inserted_at: ~N[2018-11-28 19:36:26.212121],
   name: "jazzyb",
   updated_at: ~N[2018-11-28 19:36:26.212150]
 }}