Hi there, I just followed the “getting started” article and started playing around with Ecto. I was pleased to discover mix phx.gen.schema, because it makes it easier to create a schema and its migration in one go. I do have two questions, related to two use cases:
Sometimes, for big types, it is cumbersome to write out all fields in the terminal. It would be nice to write things out in a schema definition and have the migration be generated afterwards. Is there any way to do this?
Sometimes we modify an existing schema and need a new migration. Is it possible to generate the migration automatically, or do we have to do it manually? I assume it is a manual process, but since I have seen this feature in other libraries (.NET EF Core) I thought I would ask just in case.
The generator is a convenience, but the migrations are the ultimate source-of-truth; for instance, column options like null: false don’t appear in the schema at all and so couldn’t be generated.
For more complex cases you don’t want to do this; you can have more than one schema for a table (different use cases might have different views) and this is a way to restrict domain access and limit how many columns your query performs a pull on.
The Ash Framework (https://www.ash-elixir.org) has migration generation based on model changes and it seems pretty reliable. But it requires adoption of Ash, which requires a well-informed decision as it ends up being a pretty fundamental part of your stack. You could dig through the source code to see how the migrations are calculated and maybe spin up a small project to see how it works. “Resource snapshots” are recorded each time a migration is created in order to calculate the difference. In that sense it works a little like model-first in EF, but without the 15-minute wait each time.
That’s it for me as well. Decoupling the illusion that tables map 1:1 to schemas is really important and a big distinction to what I’ve seen elsewhere. Ecto doesn’t care what you do in the db for as long as the data coming out maps to a given schema. The table name given to schema … do is really only a means of telling constructed queries which table to use – and that’s just a default overridable with {"other_table", Schema} for query building.
I can certainly see the convenience for cases where schema and migration do indeed align 1:1, but that’s an assumption ecto explicitly doesn’t make.