Today I Learned

A Hashrocket project

11 posts by taylormock @tmock12

View your outdated packages

To see which packages in a mix app need updating, you can run mix hex.outdated

$ mix hex.outdated
Dependency           Current  Latest  Update possible
appsignal            1.3.2    1.3.3   Yes
basic_auth           2.1.4    2.1.4
cachex               2.1.0    2.1.0
...

It prints out a handy table letting you quickly view the current and latest versions and if they can be updated. If Update possible is No, check your semantic version lockdown of that package in mix.exs.

mix hex.outdated accepts a few arguments:

  • --all which shows all outdated packages, including children of packages defined in mix.exs
  • --pre which include pre-releases when checking for newer versions (be adventurous!)

Happy updating!

Run an Elixir function on Module load

If you want to run a function on Module load, you can turn to Modules @on_load hook.

#hello_world.ex
defmodule Example do
  @on_load :hello_world

  def hello_world do
    IO.puts("Hello World!")
    :ok
  end
end
$ elixir hello_world.ex
Hello World!

Your function must return :ok otherwise the module load will be aborted.

Using @on_load can be an efficient way to run examples, quick scripts, setup requirements, benchmarking or load in libraries from other languages.

Looking at the state of processes in Elixir

When debugging gen_server, gen_statem and gen_event processes it can be helpful to take a look at the state.

Its easy to do this in Elixir by calling out to Erlangs sys.get_state/1:

iex(1)> defmodule Example, do: use GenServer
iex(2)> {:ok, pid} = GenServer.start_link(Example, %{ping: "pong"})
iex(3)> :sys.get_state(pid)
%{ping: "pong"}

For more common sys debugging functions, take a look here

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)>

Use colorcolumn to visualize maximum line length

With the large screen real estate we get nowadays, its hard to recognize when your code’s line length is getting out of control. You can use auto word wrapping (:set textwidth=n) or some other restrictive method. However I just want to visually see where the break is:

:set colorcolumn=80

This adds a nifty highlight line at 80 characters that I can use as a reference.

h/t Vinicius Negrisolo

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)>