Elixir, Ecto, OTP? The beginner's view, Part II.
Published: 2020-06-25 08:06:26


In [Part I](https://dev.to/mpevec9/elixir-ecto-otp-the-beginner-s-view-2fl0) of this series, we were researching the OTP concepts for the single purpose, to understand initial steps of Ecto integration. What was missing was the understanding of the *Elixir Application* concept.

###Elixir application ? 

In the examples used in Part I, we have been actually working inside of the application the entire time! 

When we run *mix new app*, mix creates application for us. And whenever we run *iex -S mix*, mix compiles, and then even starts our app by default. In our previous examples, we just haven't implemented the so-called *application callback* yet. A callback to run/start something, like e.g. Greetings.Supervisor, when our application is started.

Let's add one.

If we open a file mix.exs and check the following function:

```elixir
def application do
  [
    extra_applications: [:logger]
  ]
end
```
we see that there is an option with key *extra_applications* defined. The value represents the list of the applications that needs to be started before our app is started. You are right if you're thinking that iex is starting :logger application too.

Now let's add the application callback:

```elixir
def application do
  [
    extra_applications: [:logger],
    mod: {App, []}
  ]
end
```

With the *mod* keyword we are defining which Elixir module is our *application callback module*. You can not put here whatever callback you want, but only elixir module that uses *Application* behavior:

```elixir
defmodule App do
  use Application

  def start(_type, _args) do
    Greetings.Supervisor.start_link
  end
end
```

Here we used start/2 callback, which will be called when the application starts and inside we are calling our Greetings.Supervisor.start_link, like we did before manually.

Let's try it. After we call *iex -S mix*, which compiles and runs our application with application callback, we can do directly our API calls:

```elixir
iex(1)> Greetings.Server.add(:supervised_greetings_genserver, 1, "Hi")
:ok
iex(2)> Greetings.Server.add(:supervised_greetings_genserver, 2, "Hello")
:ok
iex(3)> Greetings.Server.list(:supervised_greetings_genserver)           
%{1 => "Hi", 2 => "Hello"}
```

Sweet. We didn't need to do any calls related to the supervisor or similar, everything was done for us in the callback.

You can see more details about our app in the so-called *application definition file*, which is actually an artifact created by the compilation process. The file is located in _build/dev/lib/example-app/example-app.app. There you can see the list of all applications to be run before, names, etc.

### A lit a bit of a different taste
As we saw, we created a supervisor module in the previous example of the [Part I](https://dev.to/mpevec9/elixir-ecto-otp-the-beginner-s-view-2fl0) and we used the *start_link/3* function: 

*start_link(module, init_arg, options \\ [])* 

This is so-called [module-based supervisor](https://hexdocs.pm/elixir/Supervisor.html#start_link/3).

But there is, again, a shorter way, where we can use *start_link/2* function directly in our application callback module. That means we can remove our supervisor module file and do the following:

```elixir
defmodule App do
  use Application

  def start(_type, _args) do
    children = [
        {Greetings.Server, name: :supervised_greetings_genserver}
    ]

    # name is optional
    opts = [strategy: :one_for_one, name: Greetings.Supervisor]
    Supervisor.start_link(children, opts)
  end
end
```
As we can see, now we can call *start_link/2* directly and we made our code even cleaner!

Why are we showing all this? If you remember, our mission is to understand Ecto initial steps as a total outsider to Elixir. Lets do the recap now.

### Recap
So far we saw how the [Elixir syntax](https://dev.to/mpevec9/elixir-syntax-part-i-p6k) for Ecto config is used. We saw the basics of the OTP and communication between processes. And above we saw the concept of the Application - we saw everything in order to understand initial steps for using Ecto. Let's use this knowledge and start from scratch.

First, we use mix and create new application with the support of the supervisors (and supervision trees):

```elixir
mix new greetings —sup
```

This will create Greetings.Application with *Application behavior*, will add *application callback* in the mix.exs and implement the application callback function with calling *start_link* of Supervisor.

mix.exs:
```elixir
...
def application do
  [
    extra_applications: [:logger],
    mod: {Greetings.Application, []}
  ]
end
...
```

application.ex:
```elixir
defmodule Greetings.Application do
  use Application

  def start(_type, _args) do
    children = []

    opts = [strategy: :one_for_one, name: Greetings.Supervisor]
    Supervisor.start_link(children, opts)
  end
end
```

The list of its children (workers) is still empty at this point, we will complete it later.

Now let's add Ecto specifics. First let's add dependencies in the mix.exs:

```elixir
defp deps do
  [
    {:ecto_sql, "~> 3.0"},
    {:postgrex, ">= 0.0.0"}
  ]
end
```
and install them with running *mix deps.get*. 

Now let's create Ecto configuration and repository by running the following line:

```elixir
mix ecto.gen.repo -r Greetings.Repo
```

This will create a lot of artifacts, but what's important now is that configuration is added in the config.exs:

```elixir
import Config

config :greetings, Greetings.Repo,
  database: "greetings_repo",
  username: "user",
  password: "pass",
  hostname: "localhost"
```
Where we can put appropriate data for our database.

Also the Ecto.Repo behavior module was created:

```elixir
defmodule Greetings.Repo do
  use Ecto.Repo,
    otp_app: :greetings,
    adapter: Ecto.Adapters.Postgres
end
```

Because we can have more repositories and we want our application to know about them all, we need to add a newly created repository to the list in the config. So we add in the config.exs the following:

```elixir
config :greetings,
  ecto_repos: [Friends.Repo]
```

Last step is to add our Ecto repository as a child of the application supervisor, as we saw before with our Greeting.Server:

```elixir
defmodule Greetings.Application do
  use Application

  def start(_type, _args) do
    children = [Greetings.Repo]

    opts = [strategy: :one_for_one, name: Greetings.Supervisor]
    Supervisor.start_link(children, opts)
  end
end
```

That's it! We put a lot of effort into understanding all the concepts, but I hope now it's more clear, at least it is for me.

Now let's try it out. We run *iex -S mix* (as we know now, this will do all the hard work) and run a DB query:

```elixir
iex(1)> Ecto.Adapters.SQL.query(Greetings.Repo, "SELECT now()", [])

09:46:51.405 [debug] QUERY OK db=9.6ms decode=1.2ms queue=19.7ms idle=1231.4ms
SELECT now() []
{:ok,
 %Postgrex.Result{
   columns: ["now"],
   command: :select,
   connection_id: 86343,
   messages: [],
   num_rows: 1,
   rows: [[~U[2020-06-25 07:46:51.371536Z]]]
 }}
```
That's it, we manage to get to the end of our mission.