Transformation: Fetch from GitHub

Now let’s continue down our data-transformation chain. Having parsed our arguments, we need to transform them by fetching data from GitHub. So we’ll extend our run function to call a process function, passing it the value returned from the parse_args function. We could have written this:

 process(parse_args(argv))

But to understand this code, you have to read it right to left. I prefer to make the chain more explicit using the Elixir pipe operator:

project/1a/issues/lib/issues/cli.ex
 def​ run(argv) ​do
  argv
  |> parse_args
  |> process
 end

We need two variants of the process function. One handles the case where the user asked for help and parse_args returned :help. The other handles the case where a user, a project, and a count are returned.

project/1a/issues/lib/issues/cli.ex
 def​ process(​:help​) ​do
  IO.puts ​"""
  usage: issues <user> <project> [ count | #{@default_count} ]
  """
  System.halt(0)
 end
 
 def​ process({user, project, _count}) ​do
  Issues.GithubIssues.fetch(user, project)
 end

We can use mix to run our function. Let’s first see if help gets displayed.

 $ ​​mix​​ ​​run​​ ​​-e​​ ​​'Issues.CLI.run(["-h"])'
 usage: issues <user> <project> [ count | 4 ]

You pass mix run an Elixir expression, which gets evaluated in the context of your application. Mix will recompile your application, as it is out of date, before executing the expression.

If we pass it user and project names, however, it’ll blow up because we haven’t written that code yet.

 % mix run -e 'Issues.CLI.run(["elixir-lang", "elixir"])'
 ** (UndefinedFunctionError) undefined function: Issues.GithubIssues.fetch/2
  GithubIssues.fetch("elixir-lang", "elixir")

Let’s write that code now. Our program will act as an HTTP client, accessing GitHub through its web API. So, it looks like we’ll need an external library.