Mix
Mix.install([
{:jason, "~> 1.4"},
{:kino, "~> 0.9", override: true},
{:youtube, github: "brooklinjazz/youtube"},
{:hidden_cell, github: "brooklinjazz/hidden_cell"}
])
Navigation
Home Report An Issue Pascal’s TriangleGames ProjectReview Questions
Upon completing this lesson, a student should be able to answer the following questions.
- What is the purpose of Mix?
- Where should our application go inside of a mix project?
- How do we compile a mix project and explore it using the IEx shell?
Mix
Mix is a build tool that ships with Elixir that automates tasks for creating, compiling, and testing your application.
We start a new Mix application by running the following in the command line.
mix new app_name
Where app_name
is the name of the project.
Your Turn
Create a hello_world
application.
You should notice that the command generated several files.
$ mix new hello_world
* creating README.md
* creating .formatter.exs
* creating .gitignore
* creating mix.exs
* creating lib
* creating lib/hello_world.ex
* creating test
* creating test/test_helper.exs
* creating test/hello_world_test.exs
Your Mix project was created successfully.
You can use "mix" to compile it, test it, and more:
cd hello_world
mix test
Run "mix help" for more commands.
Your project should have the following file and folder structure.
hello_world/
lib/
hello_world.ex
test/
hello_world_test.exs
test_helper.exs
.formatter.exs
.gitignore
mix.exs
README.md
We’ll walk through the mix project structure and how you can build Elixir applications.
The lib
Folder
The lib/
folder contains the files for the project. We start with a single module
named after the project. You should have a HelloWorld
module in the lib/hello_world.ex
file.
We use @moduledoc
and @doc
to document our code.
defmodule HelloWorld do
@moduledoc """
Documentation for `HelloWorld`.
"""
@doc """
Hello world.
## Examples
iex> HelloWorld.hello()
:world
"""
def hello do
:world
end
end
Running A Mix Project
To execute the Elixir code for our Mix project, you can load the project into the IEx Shell by running the following command in the project folder.
iex -S mix
Now, all of the .ex
files and modules under the lib/
folder are available in the IEx shell environment.
Mix ignores .exs
files, so any modules in a .exs
file will not be available in the IEx shell.
Your Turn
Load your project into the IEx Shell.
iex -S mix
Call the hello/0
function.
iex> HelloWorld.hello()
:world
Notice that the iex -S mix
command compiles your project into the _build
folder. This folder contains .beam
files which are executable files generated by the Erlang compiler.
You can also compile the project by running mix compile
in the command line.
Tests
ExUnit is a built-in testing framework. Test files are under the test/
folder in .exs
files.
In your hello_world
project, there should be an example test file test/hello_world_test.exs
with
the following content.
defmodule HelloWorldTest do
use ExUnit.Case
doctest HelloWorld
test "greets the world" do
assert HelloWorld.hello() == :world
end
end
Test files generally correspond to another file in the lib/
folder.
For example, a lib/greeting/hola.ex
file might have a corresponding test/greeting/hola_test.exs
file.
We will dive deeper into how to test Elixir projects in the ExUnit section.
For now, know that you can execute all of your tests by running the following in the command line.
$ mix test
Your Turn
Run mix test
in your hello_world
project folder from the command line, and you
should see an output similar to the following.
Compiling 1 file (.ex)
Generated hello_world app
..
Finished in 0.02 seconds (0.00s async, 0.02s sync)
1 doctest, 1 test, 0 failures
Randomized with seed 768874
File And Module Names
Mix compiles all .ex
files under the lib/
folder and bundles them together into a project.
Generally, Elixir projects organize modules under the main project namespace.
So all of the modules in the HelloWorld
application would be grouped under the HelloWorld
namespace.
For example, a new Greeting
module would be defined under HelloWorld.Greeting
.
defmodule HelloWorld.Greeting do
def salutations(name) do
"Salutations, #{name}!"
end
end
Nested modules generally relate to each other, often sub-modules deal with a more specific application of the higher-level module.
For example, a Formal
module would be under the Greeting
module.
defmodule HelloWorld.Greeting.Formal do
def charmed() do
"Charmed, I'm sure."
end
end
While not enforced, module and file structure often follow a pattern, where the module name matches its folder and file.
For example, the HelloWorld.Greeting.Formal
module would be in a lib/greeting/formal.ex
file,
and the HelloWorld.Greeting
will be in the lib/greeting.ex
file.
lib/
greeting.ex
hello_world.ex
greeting/
formal.ex
Your Turn
Modules can call functions from any other modules in .ex
files under the lib/
folder,
just as you have already seen in livebook cells.
defmodule ModuleA do
def run do
"A"
end
end
defmodule ModuleB do
def run do
ModuleA.run() <> "B"
end
end
ModuleB.run()
In your hello_world
application, create a new module, HelloWorld.Name
in a lib/name.ex
file, which will return a random name.
defmodule HelloWorld.Name do
def random do
Enum.random(["Peter", "Bruce", "Tony"])
end
end
Then, call the HelloWorld.Name.random/0
function from the HelloWorld
module in hello_world.ex
.
defmodule HelloWorld do
def hello do
"Hello, #{HelloWorld.Name.random()}."
end
end
Run your project in the IEx shell and ensure the HelloWorld.hello/0
function works as expected.
$ iex -S mix
iex> HelloWorld.hello()
"Hello, Peter."
Mix.exs
The mix.exs
file’s main responsibility is to configure the mix project.
It defines two public functions, project/0
and application/0
.
The project/0
function returns project configuration such as the project name, current version, and installed dependencies. The project/0
function relies on the private deps/0
function to provide a list of dependencies.
The application/0
function returns application configuration used to generate an application manifest file in the _build
folder. This file is used under the hood to run the project. For more, you can see the Application module
on HexDocs. Sometimes removing the _build
folder and recompiling a project can resolve compilation bugs.
Dependencies
Other developers create open-source Elixir projects hosted on GitHub, which we can add as dependencies to our project.
There is a massive ecosystem of Elixir projects, which means you don’t have to reinvent the wheel and solve already solved problems. The Hex.pm contains a list of available Elixir projects you may find useful. For a curated list, check out the awesome-elixir project.
To install a dependency, include the name of the project and desired version in a tuple inside the deps/0
function
in mix.exs
. Notice that mix.exs
includes comments on installing a dependency using the project version or GitHub URL.
defp deps do
[
# {:dep_from_hexpm, "~> 0.3.0"},
# {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}
]
end
Your Turn
Add the Faker project to your hello_world
application.
Faker provides functions for generating fake data, often useful for randomized test data.
It’s often most reliable to check the Hex page of a project for the latest version.
Ensure you add :faker
with the latest version to the deps/0
function in mix.exs
.
defp deps do
[
{:faker, "~> 0.17.0"}
]
end
Then run mix deps.get
to update your project dependencies.
Once installed, you have access to the Faker module.
Use the Faker.Person.first_name/0
function in your HelloWorld.hello/0
function.
For more on how to use Faker, you can read the Faker Documentation.
def hello do
"Hello, #{Faker.Person.first_name()}."
end
Ensure your hello/0
function works in the IEx shell.
iex -S mix
iex> HelloWorld.hello()
"Hello, Salvador." # The name will be random each time.
Versions
Project Versions are generally represented by
Major.Minor.Patch
numbers.
When installing dependencies, we specify a version requirement.
We can even specify a version between two numbers using comparison operators. i.e. >= 2.0.0 and < 2.1.0
,
The locally installed dependency may not exactly match the version requirement, but must belong in the range specified.
The ~>
symbol you see in dependencies means it will never go above its upper bound.
-
~> 2.1
would allow any version below3.0.0
and above or equal to2.1.0
. -
~> 2.1.2
would allow any version below2.2.0
and above or equal to2.1.2
.
The Version documentation goes into further depth.
You can automatically update project versions by running the following in your command line.
mix deps.update example_dep
Or with the --all
option to update all deps.
mix deps.update --all
Formatting
The .formatter.exs
file contains project configuration for how to format Elixir source code files automatically.
You can run mix format
from the command line in the project folder to format elixir code.
Your Turn
Indent the code in hello_world.ex
. Then, run mix format
and notice the code automatically
formats. If it does not, ensure that you do not have syntax errors that prevent code formatting.
README.md
Most projects include a README.md file which contains basic information about the project written in markdown.
There is no universal README structure however it’s common to include:
- The repository name.
- The project purpose.
- Setup instructions.
- Collaborators on the project.
GitHub pages display the README on the front of the repository page for the project.
When building your own projects, you’ll want to make sure you update the default README to include relevant information.
View the Markdown cheat-sheet for a quick guide on markdown syntax.
Mix Environments
Mix projects can run in different environments. The default environment is your development :dev
environment.
Run your hello_world
project in the IEx shell and call Mix.env()
to see that :dev
is the current environment.
$ iex -S mix
iex> Mix.env()
:dev
The project will use the :test
environment when running tests and :prod
when deployed to production.
We can change project behavior or configuration based on the current environment. For example,
if you had SMS (text) notifications in your project, you might want to disable them in the :dev
and :test
environment to ensure that developers don’t accidentally send out text messages to users.
Further Reading
For more on Mix, consider reading the following.
Commit Your Progress
DockYard Academy now recommends you use the latest Release rather than forking or cloning our repository.
Run git status
to ensure there are no undesirable changes.
Then run the following in your command line from the curriculum
folder to commit your progress.
$ git add .
$ git commit -m "finish Mix reading"
$ git push
We’re proud to offer our open-source curriculum free of charge for anyone to learn from at their own pace.
We also offer a paid course where you can learn from an instructor alongside a cohort of your peers. We will accept applications for the June-August 2023 cohort soon.