2022-10-17
GeneratorCrudAdmin

How to create a resource with the custom generator

Phoenix has some generators built in. But in my opinion, they can be improved. Especially when it is used with the SAAS Starter Kit. So, the SAAS Starter Kit comes with a generator designed to save time, especially when you generate a resource that belongs to another resource.

The resource generator is based on the phx.gen.live generator that comes with Phoenix but has some improvements:

  • It handles belongs_to out of the box without manual code modifications
  • It generates admin CRUD as well as the normal LiveView CRUD
  • You can make resources account-scoped so it supports multi-tenancy

When you generate and download a SAAS Starter Kit, you also get an key for the resource generator. The actual key is located in the.env-file and you can update it on https://livesaaskit.com/my

# config/config.exs
config :saas_kit,
  admin: true,
  api_key: System.get_env("SAAS_KIT_API_KEY")

NOTE, if you picked the admin-option as well when you downloaded the Starter Kit, it will have the optionadmin: trueset as well.

Generate the Resource

In the first example, I want to generate a Posts resource. A post doesnt belong to anyone.

mix saaskit.gen.resource Posts Post posts title content:text published:boolean

When I type the command and press enter, I am prompted with a question:

I need to answer if this belongs to an account. That is the multi tenancy feature that comes with the boilerplate. Since posts does not belongs to a specific account, I will just go ahead and press n.

Next, I get prompted with if this should have a LiveView interface. If I press Y, it will generate the LiveView CRUD that is not under admin.

In this, I don't plan to have a CRUD that is public for all users, so once again, I press n.

Last question that I get prompted with is if I want an admin interface. I think its a good idea to press Y because I to plan to write the posts from the admin interface.

Pressing Y means that the generator goes ahread and generates the following files and also outputs the relevant routes that you can copy paste into your routes file.

Generate a resource the belongs to a another resource

In this scenario, I want to create a resource that belongs to a user.It will be a Todo that belongs to a user. And the command for generating this is:

mix saaskit.gen.resource Todos Todo todos name completed:boolean user_id:references:users

Note, that i have appended user_id:references:users

That means that it will add a user_id field that has a database reference to users table. What it also does, is modifying the code to reflect this relationship.

So, when I press enter, I get propted with this question:

And as you can see, this is not correct. No, when I press n, I get promped with a new question:

This is correct and I can go ahead and press Y. However, if I would have presses no, I would be prompted with filling in the contect and schema myself.

When the files are generated, I can open up and inspect then.

For example, the schema file:

# lib/screen_builder/todos/todo.ex
schema "todos" do
  field :completed, :boolean
  field :name, :string

  belongs_to :user, ScreenBuilder.Users.User # <- This is autoadded

  timestamps()
end

Same thing is reflected in the context file with the CRUD functions. One example are the list_todos

# lib/screen_builder/todos.ex
def list_todos(user) do
  Repo.all(from u in Todo, where: u.user_id == ^user.id)
end

This is the same for get_todo! and create_todo. And also, same type of modifications for the tests.

When I run all tests, they pass out if the box