Today I Learned

A Hashrocket project

8 posts by taylormock @tmock12

What applications are running in your Elixir app?

Ever wonder what applications are running in your Elixir or Phoenix app?

Pop open IEx and take a look with Applications.started_applications/1

iex(1)> Application.started_applications
[{:tilex, 'tilex', '0.0.1'},
 {:ueberauth_google, 'An Uberauth strategy for Google authentication.',
  '0.6.0'},
 {:ueberauth, 'An Elixir Authentication System for Plug-based Web Applications',
  '0.4.0'}, {:oauth2, 'An Elixir OAuth 2.0 Client Library', '0.9.1'},
 {:timex,
  'Timex is a rich, comprehensive Date/Time library for Elixir projects, with full timezone support via the :tzdata package.\nIf you need to manipulate dates, times, datetimes, timestamps, etc., then Timex is for you!\n',
  '3.1.24'},
 {:combine, 'A parser combinator library for Elixir projects.', '0.9.6'},
 {:tzdata, 'Tzdata is a parser and library for the tz database.\n', '0.5.12'},
 {:postgrex, 'PostgreSQL driver for Elixir.', '0.13.3'},
 {:db_connection,
  'Database connection behaviour for database transactions and connection pooling\n',
  '1.1.2'},
 {:connection, 'Connection behaviour for connection processes\n', '1.0.4'},
 {:phoenix_html,
  'Phoenix.HTML functions for working with HTML strings and templates',
  '2.10.2'}, {:phoenix_ecto, 'Integration between Phoenix & Ecto', '3.2.3'},
 {:ecto, 'A database wrapper and language integrated query for Elixir.\n',
  '2.1.4'}, {:poolboy, 'A hunky Erlang worker pool factory', '1.5.1'},
 {:decimal, 'Arbitrary precision decimal arithmetic.', '1.4.0'},
........

Setting breaks in IEx for debugging

With the release of Elixir 1.5 comes some handy new IEx helpers, one of which is the ability to add break points throughout your code.

You can add a break to any function using break!/2 or break!/4:

defmodule MyModule do
  def hello(name) do
    "hello " <> name
  end
end
iex(1)> break!(MyModule.hello/ 1)
or
iex(1)> break!(MyModule, :hello, 1)

Both break/2 and break/4 accept an additional argument for how many stops you want to make. Useful for recursive functions where you may want to stop multiple times.

To see what breaks you have use breaks/0

iex(1)> breaks()
 ID   Module.function/arity   Pending stops
---- ----------------------- ---------------
 1    MyModule.hello/1        1

Now when you call the function, you’ll be placed into the a debugger and you can inspect whats being passed in:

iex(4)> MyModule.hello("world")
Break reached: MyModule.hello/1 (lib/my_module.ex:2)
    1: defmodule MyModule do
    2:   def hello(name) do
    3:     "hello " <> name
    4:   end
pry(1)> name
"world"

To exit the break and start a new shell process use respawn/0

pry(2)> respawn
Interactive Elixir (1.5.0) - press Ctrl+C to exit (type h() ENTER for help)
"hello world"
iex(1)>

GenServer child_spec/1 in Elixir 1.5

Elixir 1.5 GenServer introduces overridable child_spec/1. Now instead of, in your application supervisor, calling;

# MyExample.Application
def start(_type, _args) do
  children = [
    worker(MyExample.MyChild, [], restart: :permanent, shutdown: 5000)
  ]
end

You can now let the child decide how its supposed to be implemented by overriding child_spec/1 in the child.

#MyExample.Application
def start(_type, _args) do
  children = [ 
    MyExample.MyChild
   ]
end

# MyExample.MyChild
def child_spec(_args) do
  %{
    id: __Module__,
    start: { __Module__, :start_link, []},
    restart: :permanent,
    shutdown: 5000,
    type: :worker
   }
end

You can view the defaults that child_spec/1 implements in the source code.

Arguments can be passed to child_spec/1 which can then be used for pattern matching and custom configurations based on the supervisor accessing it:

#MyExample.Application
def start(_type, _args) do
  children = [ 
    {MyExample.MyChild, "temporary"}
   ]
end

# MyExample.MyChild
def child_spec("temporary") do
  %{
    id: __Module__,
    start: { __Module__, :start_link, []},
    restart: :temporary,
    shutdown: 5000,
    type: :worker
   }
end

def child_spec(_) do
  %{
    id: __Module__,
    start: { __Module__, :start_link, []},
    restart: :permanent,
    shutdown: 5000,
    type: :worker
   }
end

Terminate incomplete expression in IEx

Occasionally you get stuck in an incomplete expression while in IEx. Instead of figuring out which character you need to type to terminate the expression, you can terminate early with #iex:break

iex(1)> ["ab
...(1)> c"
...(1)> "
...(1)> ]
...(1)> #iex:break
** (TokenMissingError) iex:1: incomplete expression
iex(1)>

Another shortcut to achieve the same result is hit ctrl-g (User switch command), i (interrupt job), c (connect to job). This puts you right back in IEx.

iex(1)> ["ab"
iex(1)>   <<<ctrl-g typed here>>>
User switch command
 --> i
 --> c
Bug Bug ..!!** (EXIT) interrupted
iex(1)>

Pry in Elixir Phoenix

One of my favorite debugging tools in Ruby is Pry, so I wanted to find something similar to use when developing Phoenix applications. Thankfully Elixir has pry built in!

To use it in Phoenix, simply include this line wherever you want to pry:

require IEx; IEx.pry

I then had to start my server in an IEx session to get the pry to work (I’ve read this will be fixed soon):

iex -S mix phoenix.server

When you hit that function, you will be asked to confirm that you want to Pry

Request to pry #PID<0.331.0> at web/controllers/user_controller.ex:7. Allow? [Yn]

Confirm by typing Y and you will be good to pry away!

pry(1)>