Skip to main content

Phoenix Resource Checklist

·425 words·2 mins
Author
Marcel Körbler
Backend Plumber

Creating a new resource in an existing phoenix project often involves multiple steps for it to fit nicely into the project. From altering the migration to include foreign keys and NOT_NULL to adding relationships to the ecto schema. I sometimes forgot a step and had to alter the migration after, which can be very anoying. Also I found it hard to remember the commands to create new resouces and often had to look them up.

This guide is highlights generating JSON resources in phoenix but it can be applied to the other options like live views too.

Generation
#

Here is an example command to create a new JSON resource in phoenix:

mix phx.gen.json Users User users name:string last_login:utc_datetime account_id:references:accounts

Explenation:

  • Users -> Plural The context name the new resource should be generated in. Contexts group functionality that belongs close to each other. For example users and logins or addresses. If unsure if an resource fits into an existing group it’s always better to create a new one.
  • User -> Singular The name of the resource.
  • users -> Plural The name of the table that will be generated
  • account_id:references:accounts -> References to other resources. Given in the form of [singular-table-name]_id:references:[plural-table-name]

Output
#

* creating lib/app_web/controllers/user_controller.ex
* creating lib/app_web/controllers/user_json.ex
* creating lib/app_web/controllers/changeset_json.ex
* creating test/app_web/controllers/user_controller_test.exs
* creating lib/app_web/controllers/fallback_controller.ex
* creating lib/app/users/user.ex
* creating priv/repo/migrations/20240123151159_create_users.exs
* creating lib/app/users.ex
* injecting lib/app/users.ex
* creating test/app/users_test.exs
* injecting test/app/users_test.exs
* creating test/support/fixtures/users_fixtures.ex
* injecting test/support/fixtures/users_fixtures.ex

Add the resource to your :api scope in lib/app_web/router.ex:

    resources "/users", UserController, except: [:new, :edit]


Remember to update your repository by running migrations:

    $ mix ecto.migrate

Alter generated code
#

  1. Alter migartion (/app/priv/repo/migrations) to create the correct database objects
    1. Add null: false to not nullable fields (also at references)
    2. Add default wherever possible
    3. Change :string to :text. In postgres, there is no performance difference between using a capped VARCHAR(255), which would be :string or an uncapped TEXT. That’s why I opt for the later.
    4. Alter references(on_delete) where possible, see the available Options
    5. Verify that columns that need it are indexed. Don’t forget the foreign keys.
    6. Execute migration with mix ecto.migrate
    7. Check the database with your favorite DB tool
      1. Datatypes correct?
      2. Not null correct? Also at foreign keys?
      3. Defaults present?
      4. Indizes present?
      5. Foreign keys present?
    8. If you notice an error, first execute mix ecto.rollback, then edit the migration and reapply it with mix ecto.migrate.
  2. Alter schema (/app/lib/app/[context_name])
    1. Add relationships
      1. belongs_to
      2. many_to_many
    2. Alter changeset
      1. Add relationships to cast (i.e. account_id)
  3. Add resources to router.ex and restrict methods like required

Your new resource is ready to go!