Getting Started

Create a Mix project

First of all, what is Mix? According to the Introduction to Mix page on elixir-lang.org,

Mix is a build tool that provides tasks for creating, compiling, testing (and soon releasing) Elixir projects. Mix is inspired by the Leiningen build tool for Clojure and was written by one of its contributors.

That sounds super, doesn't it? At the end of the day, you will use Mix for a number of reasons in your project. The first way we will use Mix today is to have it create our initial project for us with mix new --sup [project name].

$ mix new --sup your_project
* creating README.md
* creating .gitignore
* creating mix.exs
* creating config
* creating config/config.exs
* creating lib
* creating lib/your_project.ex
* creating test
* creating test/test_helper.exs
* creating test/your_project_test.exs

Your mix project was created successfully.
You can use mix to compile it, test it, and more:

    cd your_project
    mix test

Run "mix help" for more information.

$ cd your_project
$ ls -la
total 16
drwxr-xr-x  11 shane  staff   374 Feb 14 16:40 .
drwxr-xr-x  23 shane  staff   782 Feb 14 16:25 ..
-rw-r--r--   1 shane  staff    41 Feb 14 16:25 .gitignore
-rw-r--r--   1 shane  staff   428 Feb 14 16:25 README.md
drwxr-xr-x   2 shane  staff    23 Feb 14 16:25 config
drwxr-xr-x   4 shane  staff    28 Feb 14 16:25 lib
-rw-r--r--   1 shane  staff   705 Feb 14 16:31 mix.exs
drwxr-xr-x   4 shane  staff    56 Feb 14 16:25 test

Add in Sugar

See that mix.exs file Mix generated for us? It contains project-level configurations, one of which is the project dependencies. We need to ensure Sugar is returned by the deps/0 function, such as:

def deps do
  [ {:sugar, github: "sugar-framework/sugar"} ]
end

If you're running Elixir v0.13.2 or higher, hex is the preferred way of adding the dependency. For a general overview of this process, checkout the hex usage page. Here's the tuple needed for hex:

def deps do
  [ { :sugar, "~> 0.5" } ]
end

so open it up, add one of the tuples for Sugar, and save it.

You'll also need to add the Sugar application to the application/0 function in that same file, like so:

def application do
  [ applications: [:sugar],
    mod: {YourProject, []} ]
end

As of Elixir 1.4.0, the above step is unnecessary if you're using extra_applications instead of applications (the default for new Mix projects), since Mix will automatically find Sugar in your project's dependencies and do the necessary work to make sure Sugar starts when your application starts.

With all that done, we're going to use Mix to pull down a copy of Sugar and its dependencies and compile them, using mix do deps.get, deps.compile. This could also be accomplished in two commands, mix deps.get and mix deps.compile, but mix do allows us to chain commands, one after the other. This process can take a bit of time depending on the speed of your internet connection and computer.

$ mix do deps.get, deps.compile
* Getting sugar (git://github.com/sugar-framework/sugar.git)
Cloning into '/Volumes/Data/Code/elixir/your_project/deps/sugar'...
remote: Counting objects: 564, done.
remote: Compressing objects: 100% (255/255), done.
remote: Total 564 (delta 334), reused 464 (delta 277)
Receiving objects: 100% (564/564), 68.83 KiB | 0 bytes/s, done.
Resolving deltas: 100% (334/334), done.
Checking connectivity... done
* Getting mime (git://github.com/dynamo/mime.git)
Cloning into '/Volumes/Data/Code/elixir/your_project/deps/mime'...
remote: Reusing existing pack: 46, done.
remote: Total 46 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (46/46), 29.10 KiB | 0 bytes/s, done.
Resolving deltas: 100% (14/14), done.
Checking connectivity... done
* Getting cowboy (git://github.com/extend/cowboy.git)
Cloning into '/Volumes/Data/Code/elixir/your_project/deps/cowboy'...
remote: Reusing existing pack: 5810, done.
...
# The rest of the project dependencies are downloaded and compiled
...
* Compiling sugar
Compiled lib/mix/tasks/sugar/gen/router.ex
Compiled lib/mix/tasks/sugar/gen/config.ex
Compiled lib/mix/tasks/server.ex
Compiled lib/mix/tasks/sugar/gen/controller.ex
Compiled lib/sugar.ex
Compiled lib/mix/tasks/sugar/init.ex
Compiled lib/mix/tasks/sugar/gen/view.ex
Compiled lib/sugar/app.ex
Compiled lib/sugar/supervisor.ex
Compiled lib/sugar/controller.ex
Compiled lib/sugar/router.ex
Generated sugar.app

If everything goes to plan, no errors will be raised, and Generated sugar.app will be displayed, letting you know all of the dependencies have been compiled correctly.

With mix being the extensible build tool that it is, developers often add specialized mix tasks to their projects, adding functionality that makes using the project easier. Sugar is no exception. Let's see what's available.

$ mix help
mix                      # Run the default task (current: mix run)
mix archive              # Archive this project into a .ez file
mix clean                # Clean generated application files
mix cmd                  # Executes the given command
mix compile              # Compile source files
mix deps                 # List dependencies and their status
mix deps.clean           # Remove the given dependencies' files
mix deps.compile         # Compile dependencies
mix deps.get             # Get all out of date dependencies
mix deps.unlock          # Unlock the given dependencies
mix deps.update          # Update the given dependencies
mix dialyzer             # Runs dialyzer with default or project-defined flags.
mix dialyzer.plt         # Builds PLT with default erlang applications included.
mix do                   # Executes the tasks separated by comma
mix escriptize           # Generates an escript for the project
mix help                 # Print help information for tasks
mix local                # List local tasks
mix local.install        # Install a task or an archive locally
mix local.rebar          # Install rebar locally
mix local.uninstall      # Uninstall local tasks or archives
mix new                  # Create a new Elixir project
mix run                  # Run the given file or expression
mix server               # Runs Sugar and children
mix sugar.gen.controller # Creates Sugar controller files
mix sugar.gen.router     # Creates Sugar router files
mix sugar.gen.view       # Creates Sugar view files
mix sugar.init           # Creates Sugar support files
mix test                 # Run a project's tests
iex -S mix               # Start IEx and run the default task

All of the mix tasks available to your project will be listed along with a short description of what it does. Note that all of the Sugar tasks start with sugar.*.

Since sugar.init add in the necessary files for Sugar, let's run it.

$ mix sugar.init
* creating lib/your_project/router.ex
* creating lib/your_project/controllers
* creating lib/your_project/controllers/main.ex
* creating lib/your_project/models
* creating lib/your_project/views
* creating lib/your_project/views/main/index.html.eex
* creating priv
* creating priv/static

Awesome! Now we have our config module, a router, our first controller, and a view. The sugar.init task follows a few conventions regarding module names and file locations. For instance, lib/your_project/controllers/main.ex contains the YourProject.Controllers.Main module. Take a look around your project if you're unfamiliar with Elixir. Don't worry. We'll be here when you get back.

Configure Your Router

A web application wouldn't serve much of a purpose if it couldn't map URLs to a particular function or set of expressions. It would essentially sit there, thinking it was doing its job when it was really doing anything but.

Enter the router. You define the routes for your web application, and the router makes sure the application does what it's supposed to when a user hits a page.

Let's see what Sugar put in our router.

defmodule YourProject.Router do
  use Sugar.Router
  plug Sugar.Plugs.HotCodeReload

  if Sugar.Config.get(:sugar, :show_debugger, false) do
    plug Plug.Debugger, otp_app: :your_project
  end

  plug Plug.Static, at: "/static", from: :you_project

  # Uncomment the following line for session store
  # plug Plug.Session, store: :etc, key: "sid", secure: true, table: :session

  # Define your routes here
  get "/", YourProject.Controllers.Main, :index
end

Routes are defined with the form method route [guard], controller, action, so when get "/", YourProject.Controllers.Main, :index is used in the router, we are telling our application to call the index function (action) defined in the YourProject.Controllers.Main module (controller) whenever the "/" URL is accessed.

Along with defining routes, the router can also contain two other configurations: plugs and filters. Both of these allow for the modification of response on a much broader scale than what is possible with a single controller action.

To see the different ways routes can be defined or routers can be configured, checkout the documentation on routing.

Updating our Mix.Config

If you were to try to run your project at this time, it would probably fail. This is because the proper application environment vairables have not been set yet. Open up your config/config.exs file, and add these lines:

config :sugar,
  router: YourProject.Router

config :sugar, YourProject.Router,
  https_only: false,
  http: [ port: 4000 ],
  https: false

This let's the Sugar internals know about the YourProject.Router module and sets the port number on which the HTTP server will listen.

Now we're ready to run mix server. You should see some output in your terminal window:

...
Generated index.html.eex
Generated show.html.eex
== Sugar running in http://127.0.0.1:4000 ==

Now you can access your application at http://127.0.0.1:4000.

Add a Controller

One controller isn't enough to properly organize your application, you say? Good to hear! I suppose you'd like to know how to create a new controller, right? Well, look no further than your friend Mix.

$ mix sugar.gen.controller pages
* creating lib/your_project/controllers/pages.ex

Success! A new YourProject.Controller.Pages controller has been created for you.

defmodule YourProject.Controllers.Pages do
  use Sugar.Controller

  def index(conn, []) do
    raw conn |> resp(200, "Hello world")
  end
end

Now it's your turn to take this controller and mould it to do your will. Check out the controllers documentation for more information about controllers.

Sugar is released under the MIT License.

Theme based on Bolt by BlackTie.co.