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_table` arguments 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:
```elixir
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()
end
```
Now 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
```elixir
@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
```elixir
@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()
end
```
In modern versions of phoenix, you can also achieve same thing as follows. This can be used for composite keys
```elixir
@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()
end
```
---
tags: #database, #migrations
source:
- [https://stackoverflow.com/questions/57083826/phoenix-problem-when-get-model-with-two-custom-primary-key](StackOverFlow)
- [https://hexdocs.pm/phoenix/1.3.0-rc.2/custom_primary_key.html](Old Docs)
- [https://medium.com/@brucepomeroy/specifying-primary-key-values-with-ecto-57405b7ecbc5](specifying primary key values with ecto)