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

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.

Ah, that is good to know. I’m a recent sqlite convert and really loving it. I have high hopes for LiteFS. I guess there’s no elegant way around Ecto preloads, though? Obviously there is manually looping but I wouldn’t call that elegant :slight_smile: I assume that would be a micro optimization anyway?

I have tried ecto in 2019, but it did not click with me back then. But I urgently needed mssql support, which also was not ready, so maybe it has not been ecto’s fault.

Now I want to try again. I still have nightmares from Hibernate and Entity Framework sometimes.

Do all of you not use generators? I resent form building and ui validation for CRUD. Do you all code these things by hand or is there something I should know other than generators?

Yea I would just say to keep preloading as normal, but don’t worry too much about using Dataloader if you are using GraphQL. Just let it do N+1 loads.

1 Like

The only generator I use day to day is mix ecto.gen.migration everything else is build as I need it. None of the generators produce even close to what we have for our admin panel and structuring. That has been my experience with generators (rails, django, phoenix, etc…) for the last 8 years.


Ya, I do by hand with help of editor snippets. For example I type defm<space> which expands to:

@impl true
def mount(_params, _session, socket) do
  | # <- cursor

  {:ok, socket}

and then type sa=<space> to get:

@impl true
def mount(_params, _session, socket) do
  socket =
    |> assign(|)

  {:ok, socket}

It’s actually recommended not to use the builtin generators for anything other than learning (sorry, I can’t find the citation). You end up tweaking them a bunch anyway. If you find yourself in a consistent pattern you like you can always make your own.

I’ve had the same experience as @warmwaffles… I use them for generating migrations and phx_new. I think that is pretty common!