Tutorial: How to write CRUD using Leaf

At the end of this tutorial you will Create, Read, Update and Delete (CRUD) on a User using Leaf! πŸš€

You can find the result of this tutorial on Github here

This tutorial is a natural follow-up of How to write Controllers. You can either go for that tutorial first and come back later or be a rebel, skip it and read on 😊

1. Create a new project
2. Generate Xcode project
3. View Structure
4. The CREATE view
5. The READ view
6. The UPDATE view
7. The DELETE view
8. Where to go from here

We will use the outcome of the aforementioned tutorial as a template to create our new project:

Before we generate an Xcode project we would have to change the package name within Package.swift:

Now in the terminal at the root directory projectName/ execute:

It may take a bit fetching the dependency, but when done you should have a project structure like this:

Let’s create an own view for each operation. With userview.leaf within Resources/Views/ we already have kinda the CREATE and READ part. But let’s optimize and change the file for a better and cleaner overview. First step: rename the file to e.g. crud.leaf.

NOTE: Don’t forget to adjust your list function within your controller to use crud instead of userview when calling try req.view().render(…) β˜πŸ»πŸ€“

We will prepare our view to have a nice structure and we will make use of bootstrap classes for that. In Resources/Views/crud.leaf change it to:

If you now cmd+r or run and fire up the /users route you’ll see nice titles!

Note: make sure to select Run as a scheme next to your button before running the app

It’s super simple, we only need a form with an input field and a submit button:

We are adding a form that is sending a POST request to the /users route with whatever we entered into the input field linked to the inputs name username.

This is what will arrive to our backend: username=whateverWeEntered

NOTE: No need to re-run your project when you change things in a leaf-file 😊

The Read view is in terms of simplicity no different. Just add this:

Since we are passing an array at the key userlist to our view from within our controller, we are able to simply loop on it. Let’s refresh our site. We can now create a new user and see a list of them!

Let’s get back to coding. We need a new route, in our routes.swift add this:

We are going to conform our User to the Parameter protocol so that we are able to define a route like this. It’s nothing fancy, the url that is matching this definition is β€œ/users/23" so basically just the user Id. But instead of defining Int.parameter here and then trying to grab that number inside our controller and then use it to fetch the user with that id. We have a convenient way with defining User.parameter that will do all the hard work for us!

You will see it in the controller in a second. But first we have to conform our User to Parameter like so:

Now to our Controller/UserController.swift writing the update function:

Okay we have a lot going on here let’s break it down.

So first with req.paremeters.next(User.self) we’ll get our user object fetched from our database for us with the id that was given at the url e.g: β€œusers/23”.

Now this will return a Future<User> and in order to access a value inside a Future we will always have to use one of the map functions. The question is which one? Let’s recap. When we call map or flatMap it’s always on a Future.

We choose map if the body of the call returns a non-future value.

And we call flatMap if the body does return a future value.

So secondly we have req.content.decode(UserForm.self) in which we make use of codable. If we have a struct or class that conforms to content and it has all properties that we receive from a Form (could also be JSON) we can easily say to what we want to decode and that will give us an instance of that object.

Finally we are overriding the username of the user with the username of the userForm, save the user and return a redirect. That’s it. Let’s go and add the corresponding Form to crud.leaf:

We want to be able to update every user we have, so we loop on the userlist and create a form with method POST to the route users/#(user.id)/update for each of them. We will have for each user a filled out input field with his username and if we change and submit it, we will immediately see the update. We don’t need to rerun for changes in our view, but we added a new function and route β€” so let’s cmd+r or run our project, refresh our site and try updating a username! I really like how simple it is!

This one is simple too. In our Controllers/UserController.swift add:

I think (hope 🀞🏻) this code is self explaining, too. Let’s define our last route:

And finally in our crud.leaf the laaast piece of code:

Our final cmd+r or run and refresh of our site and that’s it! You successfully implemented a CRUD API with Leaf πŸŽ‰!

You can find a list of all tutorials with example projects on Github here:
πŸ‘‰πŸ» https://github.com/vaporberlin/vaporschool

I'm an always optimistic, open minded and knowledge seeking fullstack developer passionate about UI/UX and changing things for the better :)