Absinthe Journey with Wolfiton or How to Bring the Absinthe Tutorial UP to Date- Part 3 The Walls 
Tags: beginners, elixir, graphql, absinthe
Published: 2020-02-19 12:39:17

Hi everyone,

**Series navigation**
[PART 1 Introduction](https://dev.to/wolfiton/absinthe-journey-with-wolfiton-or-how-to-bring-the-absinthe-tutorial-up-to-date-part-1-introduction-5fgg)
[PART 2 Foundation](https://dev.to/wolfiton/absinthe-journey-with-wolfiton-or-how-to-bring-the-absinthe-tutorial-up-to-date-part-2-foundation-3jnh)
[PART 3 The Walls](https://dev.to/wolfiton/absinthe-journey-with-wolfiton-or-how-to-bring-the-absinthe-tutorial-up-to-date-part-3-the-walls-n86/)
[PART 4 The Door](https://dev.to/wolfiton/absinthe-journey-with-wolfiton-or-how-to-bring-the-absinthe-tutorial-up-to-date-part-4-the-door-10m0)
[PART 5 Testing](https://dev.to/wolfiton/testing-1ohn)
[PART 6 Can you fly?](https://dev.to/wolfiton/absinthe-journey-with-wolfiton-or-how-to-bring-the-absinthe-tutorial-up-to-date-part-6-can-you-fly-3al5)
[PART 7 The User](https://dev.to/wolfiton/absinthe-journey-with-wolfiton-or-how-to-bring-the-absinthe-tutorial-up-to-date-part-7-the-user-58)

Welcome to part 3 of the series but before we jump in let's recap what we did in the second part:

- We defined the requirements to install phoenix
- We verified them one-by-one
- We created a folder to store our project wolf_blog
- We generated our first Phoenix API

Now let's get serious and bring in the tools that make any developer great and also help us manage our project better:

- git version control

- editor: VSCode, VSCodium(the opensource version of VSCode), Atom, IntelliJ Idea, nano, emacs, vim, others.


Let's dive in the code and follow the instructions from last time and type:

```shell
cd ~/Codes/wolf_blog

codium .

```

The command I typed will import wolf_blog in codium, if you have another editor **Dear Reader**, please feel free to use that to import our project.

**Optional install:** 

In the editor install elixir extension: Elixir_LS 

https://marketplace.visualstudio.com/items?itemName=elixir-lsp.elixir-ls


If you can't find your editor above, search for Elixir-lsp in your editor Plugin Management Installer.

#Section 1

**Let's Git it**


In the terminal navigate to the project 
```shell
cd ~/Codes/wolf_blog
```

>  **Word of warning** you need to have git initialized on your system before you type: `git init`

> If you don't know how I recommend this resource

> https://git-scm.com/book/en/v2/Getting-Started-First-Time-Git-Setup
> Also verify that you created the ssh key needed to be able to use git from the terminal
> Resource here https://help.github.com/en/github/authenticating-to-github/connecting-to-github-with-ssh

With that out of the way let's initialize git with:

```shell
git init

```

Now git has been added to our project, but we still need to create our git repo.

For this, I will use `hub`, https://hub.github.com/ and create the repo directly from the terminal, without visiting my GitHub page, pretty useful right?

So type

```shell
hub create 
```

After this command **Dear Reader** you should get an output like this:

```shell
hub create                                                                                                          
github.com username: wolfiton
github.com password for wolfiton (never stored): 
Updating origin

Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'github.com,ip' (RSA) to the list of known hosts.
Enter passphrase for key '/home/dan/.ssh/id_rsa': 
https://github.com/wolfiton/wolf_blog

```


That will confirm that our project is on Github now.


Optional section for custom configurations for database access

Dear reader, if you are using another username then Postgres to work with the PostgreSQL database now it is a good time to make modifications in the following files:

`/config/dev.exs`
`/config/test.exs`

In these files, you will find something similar to this

Content in `dev.exs`

```elixir
# Configure your database
config :wolf_blog, WolfBlog.Repo,
  username: "postgres", # Change the username to your postgres username
  password: "postgres",
  database: "wolf_blog_dev",
  hostname: "localhost",
  show_sensitive_data_on_connection_error: true,
  pool_size: 10

```

Content in `test.exs`

```elixir
# Configure your database
config :wolf_blog, WolfBlog.Repo,
  username: "postgres", # Change the username to your postgres username
  password: "postgres",
  database: "wolf_blog_test",
  hostname: "localhost",
  pool: Ecto.Adapters.SQL.Sandbox

```

> Also, the following are comments in elixir code:

```elixir
# Single line comment

"""
Multiline comment
"""
```

It is time to add our dependencies(packages) to our project, in phoenix this is done by hand.

So open up mix.exs from the root of the project(top-level) and add:


```shell

 deps do
    [
      {:phoenix, "~> 1.4.11"},
      {:phoenix_pubsub, "~> 1.1"},
      {:phoenix_ecto, "~> 4.0"},
      {:ecto_sql, "~> 3.1"},
      {:postgrex, ">= 0.0.0"},
      {:gettext, "~> 0.11"},
      {:jason, "~> 1.0"},
      {:plug_cowboy, "~> 2.0"},
      # All the above packages come from Phoenix inital config when we 
      # generated our project.

      # Add the new packages below
      {:absinthe, "~> 1.4"},
      {:absinthe_plug, "~> 1.4"}, #made a modification here
      {:absinthe_phoenix, "~> 1.4"}

    ]
  end

```
> Note: The comments have been added for clarity and a helper guide to Know where to add packages. They are not recommended to be added to your own project.

Now if you have installed the Elixir_LS extension you should see that 3 packages are fetched or installed. 

If not please type the following, in the terminal by navigating to `cd ~/Codes/wolf_blog` :

Then type

``` shell
mix deps.get
```

Let's also generate our database with this: 

```shell
mix ecto.create
```

#Section 2
**Organization is key**

We are all set to make our branch and branch features now.


Create the develop branch using this command:

```shell
git checkout -b develop

git pull

```

The next step is to open .gitignore from the root of the project and add this line:

Below the last line

`.elixir_ls` and save the file.

> The `.elixir_ls` line in .gitignore, is only required if you installed Elixir_LS plugin for your IDE(editor). If not, you can safely ignore it and move on to the next steps below.

Then use 

```shell
git add .

git commit -m "First commit to develop"

git push --set-upstream origin develop

```


Good, create a new branch

```shell

git checkout -b 01-The_Wall   

```



#Section 3


Bring the code out


Generate a new context schema and migration using this

```shell
mix phx.gen.context Blog Post posts title:unique body

mix ecto.migrate
```

What was that, Wolfiton?!

Phoenix uses a migration that you can see here 
`~/Codes/wolf_blog/priv/repo/migrations/_create_posts.exs` too tell the database the structure of the posts table.

Update

Thanks @TheEndIsNear, for suggesting on slack the following

> I'm reading part 3 now. Found a small typo "The cotext content is here: lib/wolf_blog/blog.ex " You want "The context content is here: lib/wolf_blog/blog.ex" (edited) 

> You might also want to mention that the migration file includes the date that the migration was created

Also, migrations include the date when the migration was created, so it is very easy to sort understand in which order they will run.


Migration _create_posts.exs content looks like this


```elixir
defmodule WolfBlog.Repo.Migrations.CreatePosts do
  use Ecto.Migration

  def change do
    create table(:posts) do
      add :title, :string #This will create a title column in the 
      # posts  table
      add :body, :string # Create the body column in the posts table

      timestamps() # create updated_at, created_at columns
    end

    create unique_index(:posts, [:title]) # create unique index for title
  end
end

```

Moving forward we have in `lib/wolf_blog/blog/post.ex`


```elixir
defmodule WolfBlog.Blog.Post do
  use Ecto.Schema
  import Ecto.Changeset

  schema "posts" do
    field :body, :string
    field :title, :string

    timestamps()
  end

  @doc false
  def changeset(post, attrs) do
    post
    |> cast(attrs, [:title, :body])
    |> validate_required([:title, :body])
    |> unique_constraint(:title)
  end
end


```

Here we have the schema, this is used to set the rules and validations for the database.

Using Ecto changeset the schema will allow or disallow to certain values to pass or get rejected.

You can think about it as a Ticket inspector that is very flexible.

**Explanations**

For our schema, we have the following rules in place:

- the title column needs to be unique and a string "string" 
```elixir
unique_constraint(:title)
field :title, :string
```
- the body needs to be a string
```elixir
field :body, :string
```
- They are also required so if we don't add one of them we will get an error.

```elixir
validate_required([:title, :body])
```

I hope that these explanations help in understanding the Phoenix Schema.


The context is used to group similar schemas and make some operations on the database.

The content for our content is here: `lib/wolf_blog/blog.ex`


When we used the generator, we got the following operations on our posts table:

- get a post by id `def get_post!(id)`

- get all the posts `def list_posts`

- create a post `def create_post`

- update a post `def update_post`

- delete a post `def delete_post`

> They all use the Ecto library to interact with the Postgres database.

Let's add our changes to the 01-The_Wall branch and end part 3 here.
```shell
git add .
git commit -m "Generated the Blog Context with the Post Schema"
git push --set-upstream origin 01-The_Wall
```
See you next time **Dear reader**, when we are going to build our first query and test.

#Section 4

**Update:**(Recommended)

As suggested in the comments by @Kurisusan, we will modify our `create_posts.ex` migration file so that we can have more than 255 characters in our body field.

The field `:body :string` will be converted to `:body :text`.

You maybe are wondering now Dear Reader, who can we do that?

Simple Wolfiton!, we are just going to edit the original file.

That could be a solution but if we want our migrations to be regenerated later, we will have to make the modification each time.

Not very pleasant is it?

So let's explore our other options, another option is to create an alter migration that will make the modification for us. So the edit on the body field will be taken care of by ECTO.

This sound like a plan, let's implement it:


Navigate to the root of our project `cd ~/Codes/wolf_blog`

**List all branches**

```shell
git branch -a #this command will show us all our current branches

```
Because we are adding a different purpose to our field considered an improvement we are creating a new branch for this feature. 
```shell
git checkout -b 02-The_Wall
```
Than type:

`mix ecto.gen.migration body_string_to_body_text`

Now let's open our migration in `~/Codes/wolf_blog/priv/repo/migrations/`numbers`_body_string_to_body_text.exs`

The content should look like this:

```elixir

defmodule WolfBlog.Repo.Migrations.BodyStringToBodyText do
  use Ecto.Migration

  def change do

  end
end

```

Let's change it to this


> Warning! The comments below are added for clarity they are not recommended


```elixir

defmodule WolfBlog.Repo.Migrations.BodyStringToBodyText do
  use Ecto.Migration

  def change do
    alter table(:posts) do # alter will modify the posts table
      modify :body, :text # modifies the body column from string to text
    end
  end
end

```

Than run

`mix ecto.migrate`

Good now, all we have to do

```shell
git add .

git commit -m "Improvement body string changed to the body text"

git push --set-upstream origin 02-The_Wall

```
We are done **Dear reader**, I hope you enjoyed this update.

Thank you again @Kurisusan for your suggestion in the comments:


 > Nice post to read. Really clear and easy to understand.

> About the posts migration file I have a suggestion.
> If the “body” column will store string of more than 255 characters  length, before running the migration I would suggest to change its type to ":text".
> This will allow to store post with unlimited length body in the database. > The Post schema however is ok with the type ":string" for the body field.


Also any questions, comments or suggestions are welcomed so please feel free Dear Reader to write. I will always read them.





Credits:

https://vscodium.com/

https://marketplace.visualstudio.com/items?itemName=elixir-lsp.elixir-ls

https://git-scm.com/book/en/v2/Getting-Started-First-Time-Git-Setup

https://help.github.com/en/github/authenticating-to-github/connecting-to-github-with-ssh

https://hub.github.com/

https://hexdocs.pm/phoenix/Mix.Tasks.Phx.Gen.Schema.html

@Kurisusan for improvements `:body :string` to `:body :text`, Now the body field can use more 255 characters.

Thanks @TheEndIsNear for improvements on migration explanations regarding the fact that migrations include the date and grammar correction.