links: Phoenix MOC
Create a table in Phoenix app from command line
Phoenix provides generators for a quick bootstrap of schema, views, controllers and even context. The command is a mix task and starts with phx.gen followed by necessary arguments
Let’s say I want to generate a basic CRUD for users with email, password
mix phx.gen.html Accounts User users user_id:uuid email:string:unique password_hash:string time_joined: string
This command will create necessary files for CRUD operations in controllers, views, a context named Account, a migration file
Now, let’s say I dont’ want to name id as default primary key, instead I would like to have user_id. We need to tell our phoenix about that
- open the migration file created by phoenix (it’s under priv folder)
- Inside the
create_tablearguments add primary_key: false. This tells phoenix not to create primary key with id - Now add primary_key: true to user_id (add :user_id, :uuid, primary_key: true, null: false)
The output will look like this:
def change do
create table(:users, primary_key: false) do
add :user_id, :uuid, primary_key: true, null: false
add :email, :string, null: false
add :password_hash, :string
add :time_joined, :utc_datetime
timestamps()
endNow run the migration with the following command
mix ecto.migrate which will apply this to database
We still need to modify few things in other files, since phoenix assumes id as the default primary key. we need to instruct phoenix to consider user_id as primary key
Open user.ex file created in accounts context folder.
- Inside the users schema, comment out user_id field.
- On top of users schema, add the following code
@primary_key {:user_id, Ecto.UUID, autogenerate: true}
@derive {Phoenix.Param, key: :user_id}We are instructing to use user_id as primary key, which is a type of UUID and also to take care of auto generating it.
Now for the @derive directive part. This tells to use different key name for the routes, the reason to add derive is it manages data structure to an ID in the routes.
The final result would be something like this
@primary_key {:user_id, Ecto.UUID, autogenerate: true}
@derive {Phoenix.Param, key: :user_id}
schema "users" do
field :email, :string
field :password_hash, :string, redact: true
field :time_joined, :utc_datetime
# field :user_id, Ecto.UUID
timestamps()
endIn modern versions of phoenix, you can also achieve same thing as follows. This can be used for composite keys
@primary_key false
@derive {Phoenix.Param, key: :user_id}
schema "users" do
field :email, :string
field :password_hash, :string, redact: true
field :time_joined, :utc_datetime
field :user_id, Ecto.UUID, primary_key: true
timestamps()
endtags: database, migrations source: