Sqlite3: Generators need plural table names (was: workaround for the testing sandbox)

I don’t use generators but I’m interested as I’m developing a (small) app slated for production using sqlite.

Are there any missing steps to reproduce? I generated a new project and generated two contexts using phx.gen.live. I copied in the routes and ran tests maybe 20 times in a row and never got a failure. Maybe OS matters? I’m on latest macos.

This has also been my experience with it, and I’m on linux.

I am on linux as well. I have created the project with

Erlang/OTP 25 [erts-13.0.4] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit:ns]

Elixir 1.15.4 (compiled with Erlang/OTP 25)

versions I used:

# Type `mix help deps` for examples and options.
  defp deps do
      {:bcrypt_elixir, "~> 3.0"},
      {:phoenix, "~> 1.7.7"},
      {:phoenix_ecto, "~> 4.4"},
      {:ecto_sql, "~> 3.10"},
      {:ecto_sqlite3, ">= 0.0.0"},
      {:phoenix_html, "~> 3.3"},
      {:phoenix_live_reload, "~> 1.2", only: :dev},
      {:phoenix_live_view, "~> 0.19.0"},
      {:floki, ">= 0.30.0", only: :test},
      {:phoenix_live_dashboard, "~> 0.8.0"},
      {:esbuild, "~> 0.7", runtime: Mix.env() == :dev},
      {:tailwind, "~> 0.2.0", runtime: Mix.env() == :dev},
      {:swoosh, "~> 1.3"},
      {:finch, "~> 0.13"},
      {:telemetry_metrics, "~> 0.6"},
      {:telemetry_poller, "~> 1.0"},
      {:gettext, "~> 0.20"},
      {:jason, "~> 1.2"},
      {:plug_cowboy, "~> 2.5"},
      {:credo, "~> 1.7", only: [:dev, :test], runtime: false}

Hmm, I can try on another machine if it happens there as well. Surprising.

Can you share this project with us?

I have generated a fresh one, still exhibiting the problem, and put it at GitHub - lindem/sqlite3_testsetup: SQLite3 failure example application

Thanks very much for looking into this!

Ah ha, it’s because you didn’t pluralize your table name. It’s throwing off the generator.

I was able to reproduce with:

$ mix phx.gen.live Things Thing thing thingvalue:integer thingdescription:string

as in your example.

$ mix phx.gen.live Things Thing things thingvalue:integer thingdescription:string

works just fine.


Also, if you look at the test that is failing it can’t find "Edit" because you are looking for

"#thing-#{thing.id} a"

When the element in the output is

<tr id="thing_collection-1" ....

And the output under that <tr> tag is

<a href="/thing/1/edit" data-phx-link="patch" data-phx-link-state="push">Edit</a>

It’s there.

@sodapopcan is right.

1 Like

sooo… table names have to be plural? This seems like an odd choice. In all of the companies I have ever worked in, everybody always used singular table names. It is certainly not intuitive that that is a hard requirement.

What happens to entities whose names cannot be properly pluralized?
I have closed the issue I opened earlier.

It’s a common pattern in Ruby on Rails, which Ecto and Phoenix have taken inspiration from heavily. It’s the convention used here. Nothing is stopping you from using singular table names, just don’t expect the generators to work when straying outside of convention.

1 Like

If you want to use the generators you could always generate with a plural name then edit the migration and the schema to be singular.

…or open an issue in Phoenix to make singular table names work! Not sure it would be accepted but you can always try :slight_smile:


I see. Thanks for clearing that up. I guess I will have to decide if I can live with it or not.

Nah, I think I do not have the energy to fight an established convention like that; it is a matter of opinion after all, in which I (and all of my colleagues, who I will never convince, because we use raw sql all day, where you INNER JOIN ON apple.shape = otherapple.shape, you know) firmly fall into the “other” camp.

I can accept that people do this, but I do not wish to do this myself.

1 Like

I’m using sqlite3 in production on a client project for years. There’s certainly space to improve, but it’s also very possible to use. However it’s been ages since I last used phoenix generators besides for creating an initial new project.


Hey, if you want to get used to it that’s cool, but it’s literally just editing two tokens each time. The convention doesn’t affect anything other than the generators.

Thanks, that is good to know.

I think I will probably not be using generators for long, so I can probably get along.

What about the integration tests that use database, you just run them synchronously?

We run them synchronously, but due to the fact that our integration tests are heavy anyways and don’t really run much faster async.

1 Like

Ya, sqlite is crazy fast. It’s even recommended not to worry about N+1 since you’re reading from a consistently open file (not that you have a choice with Ecto, though).

It consumes way more memory if you do all the preload magic that is encouraged for regular tcp database connections.