DEV Community

wolfiton
wolfiton

Posted on • Updated on

Absinthe Journey with Wolfiton or How to Bring the Absinthe Tutorial UP to Date- Part 3 The Walls

Hi everyone,

Series navigation
PART 1 Introduction
PART 2 Foundation
PART 3 The Walls
PART 4 The Door
PART 5 Testing
PART 6 Can you fly?
PART 7 The User

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:

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

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:

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

hub create 

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

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

# 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

# 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:

# 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:


 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

mix deps.get

Let's also generate our database with this:

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:

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

git add .

git commit -m "First commit to develop"

git push --set-upstream origin develop

Good, create a new branch


git checkout -b 01-The_Wall   

Section 3

Bring the code out

Generate a new context schema and migration using this

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

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

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"
unique_constraint(:title)
field :title, :string
  • the body needs to be a string
field :body, :string
  • They are also required so if we don't add one of them we will get an error.
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.

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

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.

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:


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


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

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.

Top comments (2)

Collapse
 
kurisu3 profile image
Kurisu

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.

Collapse
 
wolfiton profile image
wolfiton

I will add an alter table to the migration to change this using a generated migration, tomorrow.

Thanks @kurisusan for the suggestion.