I’m reading Programming Phoenix LiveView and in one chapter they create a User table using the CLI
$ mix phx.gen.auth Accounts User users
This generate the following schema
// lib/pento/accounts/user.ex
schema "users" do
field :email, :string
field :password, :string, virtual: true, redact: true
field :hashed_password, :string, redact: true
field :confirmed_at, :naive_datetime
timestamps()
end
I want to add a new field to this schema and to my database. I added field :username, :string to the schema
schema "users" do
field :email, :string
field :username, :string, null: false
field :password, :string, virtual: true, redact: true
field :hashed_password, :string, redact: true
field :confirmed_at, :naive_datetime
timestamps()
end
And ran ecto migrate again
$ mix ecto.migrate
00:02:35.628 [info] Migrations already up
$ mix ecto.create
The database for Pento.Repo has already been created
But when I check my database the field isn’t there.
Whats the proper way to add fields and modify an schema?
The book you are reading does expect you to have some knowledge of Elixir and Ecto beforehand. Stick to the main quest or learn these skills upfront a little bit, otherwise you will be fighting monsters that are out of your league.
But as you are new, a gift I will give you
Answer
You also need to create a migration for the database changes (now you only updated the model). If you had not run the migrations yet, you could have added the field in the “create_user_table” migration before running them.
In this case you want to ‘alter’ an existing table by creating a new migration.
Aside of what’s said already I wonder if you have some misunderstanding from other languages/frameworks. ecto does not updates database after you change model (in function programming we use schema naming instead). You need to understand that schema is not a direct database representation, but a representation of final data which you receive when casting parameters or fetching entries from database.
An Ecto schema maps external data into Elixir structs.
schema/2 is typically used to map data from a persisted source, usually a database table, into Elixir structs and vice-versa. For this reason, the first argument of schema/2 is the source (table) name. Structs defined with schema/2 also contain a __meta__ field with metadata holding the status of the struct, for example, if it has been built, loaded or deleted.
(…)
Besides working as data mappers, embedded_schema/1 and schema/2 can also be used together to decouple how the data is represented in your applications from the database. (…)
On the other side we have a migration which by default are located in priv/repo/migrations directory. Those files modify your database. You may wonder why we need a schema or why we can’t cast the parameters to the migration directly. As said schema does not represents your databasedirectly, but helps with translating data. schema in Phoenix have few extra features like for example you may find source and virtual options:
:source - Defines the name that is to be used in the database for this field. This is useful when attaching to an existing database. The value should be an atom. This is a last minute translation before the query goes to the database. All references within your Elixir code must still be to the field name, such as in association foreign keys.
(…)
:virtual - When true, the field is not persisted to the database. Notice virtual fields do not support :autogenerate nor :read_after_writes.