A Crystal app adventure!
Tags: crystal, tutorial, shards, database
Published: 2020-01-02 19:49:13

# Introduction

We are starting an adventure: we are going to build a *great-outstanding-marvelous* application using the [Crystal](https://crystal-lang.org) language!

But, since these are our first steps using the Crystal language, maybe we could start with a first *simple* app? 🤔 Yeah! It sounds good! So, this is the goal for this post: **3 steps for creating a *simple* app using Crystal**! 🚀

1, 2, 3 … Hold it! We are assuming that you already have installed the Crystal language. But, what if you didn't? 😱 

Well, in that case here it is **step 0**: 

* Go to the Crystal language site and click on [Install](https://crystal-lang.org/install/). There you'll find all you need to install the language compiler for your platform ... don't worry, we'll wait for you ...

and another **step 0** 😝:

* In the [overview](https://crystal-lang.org/reference/overview/) section, you will find some great examples if you didn't use Crystal before.

⏰*a few minutes later*

Are you ready? Great! Let's start!

# Step 1: `init` is the magic word

So, first things first: assuming that our app is called `my_app` (if you can think of a better name, go ahead and rename it! 🙃) then we create the application using the same Crystal's command line, like this:

```shell-session
$ crystal init app my_app
```

And Crystal will reply:

```shell-session
create  my_app/.gitignore
   create  my_app/.editorconfig
   create  my_app/LICENSE
   create  my_app/README.md
   create  my_app/.travis.yml
   create  my_app/shard.yml
   create  my_app/src/my_app.cr
   create  my_app/spec/spec_helper.cr
   create  my_app/spec/my_app_spec.cr
Initialized empty Git repository in /great_projects/my_app/.git/
```

Perfect! We have the project with the Git repository already initialized and with a basic `.gitignore` (thanks Crystal! ❤️)

In the folder `my_app/src/my_app.cr` we have the entry point to our application. Although we may use other file, it is a standing point to start building our app.

# Step 2: Hello ~~world~~ database!

Not the Hello World example! With `step 1` we have a new Crystal App ready to grow! So let's continue with a more interesting example ... maybe we could connect to a database? Yeah! Let's do that!

We'll be using a MySQL database, It won't be necessary to install the database in our computer, instead we could use a [Docker](https://www.docker.com) [container](https://www.docker.com/resources/what-container)! Here's the `docker-compose.yml` file:

```yml
version: '3'

services:
  db:
    image: mysql:8.0.17
    command: --default-authentication-plugin=mysql_native_password
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: root
    container_name: crystal_db
    ports:
      - 3306:3306

volumes:
  db:
```

Great! With this, we may start the container and have a MySQL database ready for us to use!

Let's start the container:

```shell-session
$ docker-compose up
```

If it's all good, then the response from docker should end with something like this:

```shell-session
crystal_db | Socket: '/var/run/mysqld/mysqlx.sock' bind-address: '::' port: 33060
```

Now, using our favourite database tool (in my case I'm using [TablePlus](https://tableplus.com)), we may connect to the database using this configuration:

```yml
host: 127.0.0.1
port: 3306

user: root
password: root
```

And last (but not least) we will create a new database for our project called `crystal123_db`

```sql
CREATE DATABASE `crystal123_db`;
USE `crystal123_db`;
```

# Step 3: (Actually) using the database from our app!

And here we are, the final step! We will need the corresponding [MySQL-connector](https://github.com/crystal-lang/crystal-mysql) in order to use the database from our Crystal app.

First, we need to add the mysql-shard in our application's `shard.yml` file, like this:

```yml
dependencies:
  mysql:
    github: crystal-lang/crystal-mysql
```

And then, we install all the dependencies with:

```shell-session
$ shards install
```

Shards will reply:

```shell-session
Fetching https://github.com/crystal-lang/crystal-mysql.git
Fetching https://github.com/crystal-lang/crystal-db.git
Installing mysql (0.10.0)
Installing db (0.8.0)
```

**Note:** [Shards](https://github.com/crystal-lang/shards) is the *Dependency manager for the Crystal language*.


Now, let's try to **connect to the database**! (*remember we called the database: `crystal123_db` ... a great name if you ask me* 😎) And, since we are there, we will **create a new table** called `bank_accounts` (with to columns: `name` and `amount`)

```crystal
# my_app.cr
require "mysql"

db = DB.open "mysql://root:root@localhost/crystal123_db"

db.exec "drop table if exists bank_accounts"
db.exec "create table bank_accounts (name varchar(30), amount int)"
```

Let's run the code using Crystal's command line:

```shell-session
$ crystal ./src/my_app.cr
```

Go to the database ... yes! The table `bank_accounts` was created!!

And for the same price, let's **add 2 rows to the table**. Here is the final version of `my_app.cr`:

```crystal
# my_app.cr

require "mysql"

db = DB.open "mysql://root:root@localhost/crystal123_db"

db.exec "drop table if exists bank_accounts"
db.exec "create table bank_accounts (name varchar(30), amount int)"

# first row
db.exec "insert into bank_accounts values (?, ?)", "John", 100

# second row
db.exec "insert into bank_accounts values (?, ?)", "Sarah", 250
```

We run the application:

```shell-session
$ crystal ./src/my_app.cr
```

Let's check the database and ... yes! Now we have the table `bank_accounts` created and with 2 rows! We did it! 🎉

## Farewell and see you later

We have reached the end of this first journey. To recap:
* we have initialized a Crystal application using the command line.
* we have installed a database (actually a container with the database)
* and finally we have use the database from our Crystal application!

Hope you enjoyed it! Until the next `Crystal` adventure!😃 

References:
* Using the Crystal [compiler](https://crystal-lang.org/reference/using_the_compiler/)
* Using a [database](https://crystal-lang.org/reference/database/) with Crystal.
* The [shards command] (https://crystal-lang.org/reference/the_shards_command/)