Today I Learned

A Hashrocket project

Create Named Structs With

I often see Struct used to create some one-off anonymous data structure like so:

> person =, :age)
=> #<Class:0x007fc6c89112e8>
>"Alice", 33)
=> #<struct name="Alice", age=33>

This will often get the job done, but on its own the resulting data structure doesn’t tell us as much as it could.

We can say more with a named struct:"Person", :name, :age)
=> Struct::Person
>"Bob", 24)
=> #<struct Struct::Person name="Bob", age=24>

When the first argument is a string that can be converted to a constant, then we’ll get a named struct that is subclassed under Struct.

We can also assign the struct initialization to a constant to do a similar thing:

> Person =, :age)
=> Person
>"Jerry", 45)
=> #<struct Person name="Jerry", age=45>


Simulate componentDidMount with a useEffect

If you want to simulate a componentDidMount class method inside your functional component, you can use the useEffect hook thusly:

const MyFunctionalComponent = () => {
   useEffect(() => {
     // any code here is run once 
   }, []); 
   // the empty array will be the same each 
   // time the component is called, so the useEffect
   // will not run in calls subsequent to the first
   return <div>Foo</div>;

ht: @greis

Legible milliseconds in Elixir using Erlang timer

In Elixir, we often need to set milliseconds. This is especially common when working with GenServer, Task.Supervisor, Agent and others.

While we could write our milliseconds directly:


or perhaps


Did you know that was 3 hours just by glancing at it? Sure the math is fairly easy, but why make us think? Erlang’s timer to the rescue!

iex()> :timer.hours(3)

Well that makes our 3 hours pretty legible if you ask me.

We also have minutes and seconds:

iex()> :timer.minutes(11)
iex()> :timer.seconds(455)

Thanks Erlang!

Readable code with objects, constants & attributes

Occasionally when working with external APIs, you need to send over some cryptic status:

  { status: 2 }

But what does 2 mean?!

We can use objects to make this a bit easier to maintain

const STATUS = { processing: 0, error: 1, completed: 2 }

  { status: STATUS.completed }

Now we can immediately see the order status is completed.

This technique is applicable in other languages as well:

Ruby with a constant:

STATUS = { error: 0, processing: 1, completed: 2 }

Elixir as a module attribute

defmodule Order do
  @status %{error: 0, processing: 1, completed: 2}

  def completed, do: @status.completed

Find duplicate routes in Elixir Phoenix

If you have duplicated routes in your route file like this:

scope "/api", MyAppWeb.Api, as: :api do
  pipe_through [:this]
  resources "/users", UserController, except: [:new, :edit]

scope "/api", MyAppWeb.Api, as: :api do
  pipe_through [:that]

  resources "/users", UserController, except: [:new, :edit]

Then you’ll get a warning like this:

warning: this clause cannot match because a previous clause at line 2 always matches

The warning doesn’t really let you know which routes are duplicated, but it’s really ease to find the duplicated routes by utilizing the uniq command.

mix phx.routes | sort | uniq -d

The -d flag for uniq is duplicates only. -d only considers similar lines in consecutive order as duplicates, so you need to run it through sort first.

The output looks like this:

api_user_path  DELETE  /api/users/:id                   MyAppWeb.Api.UserController :delete
api_user_path  GET     /api/users                       MyAppWeb.Api.UserController :index
api_user_path  GET     /api/users/:id                   MyAppWeb.Api.UserController :show
api_user_path  PATCH   /api/users/:id                   MyAppWeb.Api.UserController :update
api_user_path  POST    /api/users                       MyAppWeb.Api.UserController :create

And those are your duplicate routes!

Named bindings in Ecto (vs positional bindings)

Positional bindings in Ecto are meant to confuse when buildings large queries across several different functions.

query = Thing
|> join(:inner, [t], x in X, on: t.x_id =
|> join(:inner, [_, x], y in Y, on: x.y_id =

Using that query in another function might look like this:

|> where([_, x, _], x.type == "Articulated")

But what if the positions change? How am I supposed to know which positions are which when I’m adding to this query out of context?

Named bindings help tremendously here (note the :as option):

query = Thing
|> join(:inner, [t], x in X, as: :x, on: t.x_id =
|> join(:inner, [_, x], y in Y, as: :y, on: x.y_id =

Now I can refer to these things without knowing the position. If the position changes it’s all good the additive where statement does not have to change:

|> where([y: y, x: x], x.type == "Articulated", y.feel == "Good")

Group by and order by can use aliases

In PostgreSQL the alias of a selected expression can be used in the group by and order by clauses instead of repeating the expression.

For example, this:

select left(lower(email), 1) as first_letter, count(*) as num
from users
group by left(lower(email), 1)
order by count(*) desc;

Can be replaced with this:

select left(lower(email), 1) as first_letter, count(*) as num
from users
group by first_letter
order by num desc;

How to actually _load_ the resource with Guardian

Guardian, like all auth libraries in all languages, is tough to wrap my head around.

I know there is a plug in the pipeline called plug Guardian.Plug.LoadResource. I know there is a function called Guardian.Plug.current_resource(conn) that takes the conn and returns that returns the resource placed in the conn by the Guardian.Plug.LoadResource plug.

What I don’t know is how the LoadResource plug knows what resource to get.

In Guardian, you configure the pipeline with:

use Guardian.Plug.Pipeline, otp_app: :my_app,
                              module: GuardianImpl,
                              error_handler: ErrorHandler

The GuardianImpl is a module that uses the Guardian behaviour.

The Guardian behaviour has a callback resource_from_claims that might be implemented like this:

def resource_from_claims(claims) do
  {:ok, Repo.get(User, claims["sub"])}

So when you need to modify how you load the resource, you should look to see how the resource_from_claims callback is implemented.

Read more here.

Confirming operations with `xargs -p`

xargs is a great tool to take a lot of input and execute a lot of different commands based on that input. Sometimes though, if you are performing destructive or mutative actions with xargs you want to proceed more cautiosly.

> echo "banana apple orange" | tr ' ' '\n' | xargs -n1 echo "I like"

This outputs:

I like banana
I like apple
I like orange

But maybe I don’t like some of those things, please ask! Including the p flag with xargs forces a prompt.

> echo "banana apple orange" | tr ' ' '\n' | xargs -p -n1 echo "I like"
echo I like banana ?...n
echo I like apple ?...y
I like apple
echo I like orange ?...n

Yep, I only like apples.

Updating the ExUnit test context with setup

When using ExUnit the second argument to the test macro is context.

test "1 + 1 = value", context do
  assert 1 + 1 == 2

This context can provide setup values so that you can share setup across tests.

Use the setup macro to update the context. The keyword list you return from the setup function will be merged into the map of the context.

setup do
  [result: 2]  # this gets merged into the context

setup do
  # create some database records
  :ok # this does not get merged into the context

Also in the setup macro you can have access to the context, allowing you to potentially change the context based on the needs of the test.

setup context do
  %{result: r} = context
    [result: r + 1]

test "1 + 1 = value", %{result: value} do
  assert 1 + 1 == value

Read more about ExUnit setup here.

Get first image of animated gif

Image Magick’s convert tool has a no-option, very simple way to access the first frame of an animated gif.

convert 'animated.gif[0]' animated.first.gif

The square brackets after the file name above can contain any index for any frame of the image. 0 is the index of the first image.

To discover how many frames an animated gif has you can use:

identify animated.gif

Which will return a line for every frame in the animated gif. Those lines will look like this:

animated.gif[32] GIF 736x521 756x594+4+70 8-bit sRGB 256c 421707B 0.000u 0:00.000

ActiveRecord not is not boolean algebra negation

Today I learned that rails ActiveRecord not query is not to be considered a boolean algebra negative. Let’s see by an example:

User.where(name: "Jon", role: "admin")

This will produce a simple sql query:

SELECT "admins".*
FROM "admins"
WHERE "admins"."name" = $1
  AND "admins"."role" = $2
[["name", "Jon"], ["role", "admin"]]

If we get the same where clause and negate it:

User.where.not(name: "Jon", role: "admin")

Then we get:

SELECT "admins".*
FROM "admins"
WHERE "admins"."name" != $1
  AND "admins"."role" != $2
[["name", "Jon"], ["role", "admin"]]

But I was expecting a query like:

SELECT "admins".*
FROM "admins"
WHERE ("admins"."name" != $1
   OR "admins"."role" != $2)
 [["name", "Jon"], ["role", "admin"]]

So if you want to produce a query like that you’ll have to build on your own:

User.where.not(name: "Jon").or(User.where.not(role: "admin"))

Just beaware of that when using not with multiple where clauses.

Alphabetize Keys with jq

In a previous post, I wrote about how jq is great because it doesn’t alphabetize JSON keys by default. I still think that’s great, because sometimes the key order is meaningful, such as might be found in a package.json file.

We can add alphabetization to jq, however, using the -S flag. To format and and sort you current buffer in Vim, run the following:

:%!jq -S '.'

Happy JSON-ing!

Go to next ALE error

Has ALE overtaken your vim setup like it has mine? It constantly runs linters, compilers and formatters, just waiting for you to slip up so that it can put an X in the gutter.

Those X’s are really quite handy. They generally point me to the next place in the code that I need to make a change.

To get there quickly you can goto the next ALE error with:


This will stop at the last error in the file though. To have it wrap around use:


I really enjoy vim-unimpaired’s handy bracket mappings, but I don’t use ]a that move between args (because I don’t use args very often).

To setup my own handy bracket mappings for ALE:

:nmap ]a :ALENextWrap<CR>
:nmap [a :ALEPreviousWrap<CR>
:nmap ]A :ALELast
:nmap [A :ALEFirst

Prevent npm high level security errors in CI

In npm 6.6, a feature was added to provide security audit information for the packages that are used in your application.

This is run with:

node audit

This exits with a non-zero exit code if any ‘low’, ‘medium’, ‘high’, or ‘critical’ errors were detected.

You can use that non-zero return code in your CI to fail a check, which should notify you of the security vulnerability which you can then resolve.

If you care about ‘high’ or ‘critical’ errors but don’t care about ‘low’ or ‘medium’ you can set the audit-level npm config value to ‘high’ in you npm configuration for your CI server.

Git Interactive Rebase The First Commit

Everytime I want to do an interactive rebase I pass the number of commits back that I want using head~number:

> git rebase -i head~3

Recently I created a repo that had only 2 commits and I got an error when I tried to do a rebase the same way:

> git rebase -i head~2
fatal: Needed a single revision
invalid upstream 'head~2'

To avoid that error, you can use a --root option to rebase the first commit:

> git rebase -i --root

Elixir ExDoc has version dropdown

ExDoc released a new version that allow developers to show a version dropdown on their documentation.

Here’s how I added to my library:

Open the mix.exs file and add javascript_config_path to the docs option on your project function.

def project do
    docs: [
      main: "readme",
      extras: ~w(,
      javascript_config_path: "../.doc-versions.js"

And on my Makefile I have this:

docs: ## Generate documentation.
docs: setup
    echo "var versionNodes = [" > .doc-versions.js
    app=`mix run -e 'IO.puts(Mix.Project.config()[:app])'`; \
    for v in $$(git tag | tail -r); do echo "{version: \"$$v\", url: \"$$app/$$v/\"}," >> .doc-versions.js; done
    echo "]" >> .doc-versions.js
    mix docs

So if I run make docs this will generate or update a file .doc-versions.js from what I have on my git tag

And here is how it looks like:


Here’s the ExDoc changelog.

Elixir Pattern Matching with Variables

Let’s say you have a variable that you want to pattern match.

By default Elixir won’t use the variable’s value to do the pattern matching and it will do a regular assignment, overriding the original variable’s value:

iex(1)> year = 2020

iex(2)> car = %{year: 2019}
%{year: 2019}

iex(3)> %{year: year} = car
%{year: 2019}

iex(4)> year

Elixir has the pin opertator ^ that does exactly what we need. So in our example we can use the pin operator and if it doesn’t match you get an error:

iex(1)> year = 2020

iex(2)> car = %{year: 2019}
%{year: 2019}

iex(3)> %{year: ^year} = car
** (MatchError) no match of right hand side value: %{year: 2019}

Don't async await, especially in useEffect

Often I need to setState based on an async value. With hooks this is something like:

useEffect(async () => {
    const newVal = await asyncCall();

But wait!. This throws an error. React wants the return of useEffect to be a cleanup function.

The return type of an async function is Promise. So that won’t work. Best to just put on your big developer pants and use that promise.

useEffect(() => {

There. Now our useEffect returns undefined, and React is pleased.

Here is a sandbox if you want to see for yourself.

Archiving React Native iOS projects on Xcode 10+

I was getting the following error on the CI when it was trying to archive the project and I couldn’t figured out what was going on:

xcodebuild failed with return code: 65

So I decided to archive the iOS project locally and the error was different:

:-1: Multiple commands produce 
1) Target 'React' has a command with output '~/Library/Developer/Xcode/DerivedData/.../IntermediateBuildFilesPath/UninstalledProducts/iphoneos/libReact.a'
2) Target 'React' has a command with output '~/Library/Developer/Xcode/DerivedData/.../IntermediateBuildFilesPath/UninstalledProducts/iphoneos/libReact.a'

:-1: Multiple commands produce 
1) Target 'yoga' has a command with output '~/Library/Developer/Xcode/DerivedData/.../IntermediateBuildFilesPath/UninstalledProducts/iphoneos/libyoga.a'
2) Target 'yoga' has a command with output '~/Library/Developer/Xcode/DerivedData/.../IntermediateBuildFilesPath/UninstalledProducts/iphoneos/libyoga.a'

Then I googled it and found this:

Then I added this post_install block at the end of the Podfile:

post_install do |installer|
  installer.pods_project.targets.each do |target|
    if == "React"

    if == "yoga"

It worked locally and on the CI.

Finally I gave a 👍 on that comment.

Truncate an Array

Every time I go to truncate and array in JavaScript, I have to look up the syntax. It’s something that makes me angry.

Did you know that there is an oddly easier way to do it without reaching for splice() or slice()?

const collection = [4,6,9,1,12,42];
collection.length = 3;

collection is now [4,6,9]

Hopefully I can remember this one!

Pattern matching structs (why order is important)

When pattern matching structs with maps, many people don’t consider the consequences of order.

Say we have a user:

defmodule User do; defstruct [:name, :age] end

This will match just fine:

iex()> %{name: nil, age: nil} = %User{}
%User{age: nil, name: nil}

While the reverse will not:

iex()> %User{} = %{name: nil, age: nil}
Bug Bug ..!!** (MatchError) no match of right hand side value: %{age: nil, name: nil}

If you care to know why:

When pattern matching maps, the right side value must contain all the keys. In our example above, it appears they do:

iex()> inspect(%User{})
"%User{age: nil, name: nil}"

But looks can be deceiving:

iex()> inspect(%User{}, structs: false)
"%{__struct__: User, age: nil, name: nil}"

With our newfound knowledge, lets try again:

iex()> %User{} = %{name: nil, age: nil, __struct__: User}
%User{age: nil, name: nil}


How to assert Elixir doctest raises an error

Today I learned how to assert an Elixir doctest raises an error. Check this out:

defmodule MyModule do
  @doc """
  This function raises ArgumentError.

  ## Examples

      iex> MyModule.my_func()
      ** (ArgumentError) something is wrong
  def my_func() do
    raise(ArgumentError, "something is really wrong")

The previous doctest will fail with this message:

  1) doctest MyModule.my_func/0 (1) (MyModuleTest)
     Doctest failed: wrong message for ArgumentError
       "something is wrong"
       "something is really wrong"
     code: MyModule.my_func()
       lib/my_module.ex:10: MyModule (module)

Set the relative path of assets in a CRA app

When I build my CRA app I get a path for my assets (css, images) that begins with /static. If I deploy my app to, then the app will try to access those asset paths at That’s not where the asset lives. The asset lives at

Create React App allows you to change the prefix for a the built assets with the homepage attribute in your package.json file.

You could set it to myapp:

"homepage": "/myapp"

And then the asset will have the path of /myapp/static/asset.css, but what if you want to change paths?

"homepage": "."

Setting homepage to . will make the asset always relative to index.html, allowing you to not be concerned with the path the application is deployed to.

This actually repurposes a property of the package json file that npm uses to set the homepage of an npm package, so you may find this property used in a different way in other package.json files.

See the npm docs here.

See the Create React App docs here

Override Create React App conf w/react-app-rewired

A common problem when using Create React App is changing the configured behaviour of webpack. Generally, if you want to change the webpack configuration provided by Create React App you need to eject, but eject at the very minimum adds a lot of files to your project that you may not want.

An alternative is to use react-app-rewired in combination with customize-cra.

react-app-rewired provides a file, config-overrides.js placed in your project root directory where you can override existing behaviour.

customize-cra provides a set of handy utility functions to help you override specific configurations.

For example, when using the ant design library, you can import both the component and the css for that component with one import line if you use babel-loader.

Here is an example of a config-overrides.js file that would provide that behaviour.

const { override, fixBabelImports } = require('customize-cra');

module.exports = override(
  fixBabelImports('import', {
    libraryName: 'antd',
    libraryDirectory: 'es',
    style: 'css',

PostgreSQL query with an array of regexes

I recently wanted to query my Postgres database by matching a column based on an array of regular expressions:

To query where the column matches all expressions in the array:

select * 
from my_table 
where my_column ilike all (array['%some%', '%words%'])

To query where the column matches at least one, but not necessarily all, of the expressions in the array:

select * 
from my_table 
where my_column ilike any (array['%some%', '%words%'])

Highlight Diffs With Markdown

Today I learned about the ‘diff’ syntax, supported by many syntax highlighting libraries including those used by Github and Today I Learned.

Add diff to your fenced code block, and this:

def example do
-  :ok
+  {:ok, :more_stuff}

Becomes this:

def example do
-  :ok
+  {:ok, :more_stuff}

A nice use case is a README or pull request description; show instead of tell the changes you made, or someone should make.

Run side effect when a prop changes w/Hooks

There is a React Hook for side effects useEffect. You can pass useEffect a function and that function will run after each render.

useEffect(() => console.log('rendered!'));

In many cases it’s inefficient and unnecessary to call the effect function after every render. useEffect has a second argument of an array of values. If passing in this second argument, the effect function will only run when the values change.

useEffect(() => console.log('value changed!'), [props.isOpen]);

Now, you will see “value changed!” both on the first render and everytime isOpen changes.

Reminder: React Hooks are for functional components not class components. Check out the hooks api here

Get a ref to a dom element with react hooks

React Hooks are now available in React 16.8. There are 10 different hooks, you can read about them here. When I needed a ref to a dom element yesterday I reached for useRef.

const containerRef = useRef(null);

This isn’t a ref to anything unless you pass the ref to a tag.

return (<div ref={containerRef}></div>);

Now the ref will be assigned a dom element that you can use. In this example I’m using the useEffect hook to execute a side effect after the render takes place. Use the current attribute to access the current dom node.

useEffect(() => { = 'background-color: green;'

Compute Intermediate Values In A With Construct

The expressions you use in a with construct do not have to contain the <- syntax. You can pattern match and bind values along the way as well.

with %{id: id} <- get_user(),
     url = "/api/#{id}/blogs",
     %{status_code: 200, body: body} <- HTTPoison.get(url),
     {:ok, decoded_body} <- Poison.decode(body) do
  {:ok, decoded_body}

In the above (sorta contrived) example we were able to construct a URL in the middle of the series of expressions.

The values we compute inline will be closed into the with construct, so they won’t leak.

See the with docs for more details.

Send Tmux Pane to Window

A scenario I find myself in frequently: I’ve started a server in a Tmux pane, and realize I don’t need to see the server logging in my ‘home’ Tmux pane (pane 0 for me).

To send a Tmux pane to its own window, use :break-pane.

A nice addition is the -n flag, which lets you set the new window name while breaking the pane.

:break-pane -n frontend-elm

Check List Membership In Elixir

You can use the in operator to check if something appears in a list. This is a handy way of checking if a variable is one of a few acceptable or expected values.

For instance, a common DateTime comparison pattern relies on this to check if a DateTime is >= or <= to another DateTime.

{:ok, datetime} = DateTime.from_naive(~N[2016-05-24 13:26:08.003], "Etc/UTC"), DateTime.utc_now()) in [:lt, :eq]

Alternatively, you can check that something does not have membership in a list by also including the not operator., DateTime.utc_now()) not in [:lt, :eq]

Open FZF Result In A Split In Vim

The fzf.vim plugin allows you to do speedy fuzzy searches for filenames and line-by-line content.

Once you’ve narrowed down the results and found what you’re interested in, you can hit <enter> and a new buffer will open over what was already in the window. You can also open that file as a split.

Hitting Ctrl-x will open the file under the cursor as a horizontal split.

Hitting Ctrl-v will alternatively open that file as a vertical split.

Using When Clauses In A With Construct In Elixir

Because Elixir’s with construct supports the full power of the language’s pattern matching, we can use when clauses to further narrow down our matches.

For instance, if we want to match against the response to an API request, but only for response status codes in the 2xx range, we can do something like the following:

with %{status_code: code, body: body}
       when code >= 200 && code < 300 <- HTTPoison.get!(url),
     {:ok, decoded_body} <- Poison.decode(body) do
  {:ok, decoded_body}

See the docs for with for more details.

Pulling In Changes During An Interactive Rebase

My standard workflow when doing feature development is to checkout a feature branch and commit changes as I go. When the feature is finished, I clean up the commit history with an interactive rebase and then integrate those changes with master.

I initiate the interactive rebase like this (while on the feature branch):

$ git rebase -i master

This allows me to squash, fixup, and delete commits that I’ve made since checking out this branch from master.

It is important to note that an another thing will happen seemingly behind the scenes. Any commits on master since the feature branch was checked out will be applied to the feature branch before the effects of the interactive rebase are applied.

If you want to strictly do an interactive rebase of the commits on the feature branch ignoring what is on master, then reference the commit you checked out from — put another way, reference the commit before the first commit on this branch.

$ git rebase -i <sha-of-first-commit-on-this-branch>~

The tilde (~) will go back one commit from the specified commit sha.

See man git-rebase for more details.

Edit A File Starting On The Last Line

Generally when you start editing a file whether as a new Vim session (vim file.txt) or in an existing Vim session (:e file.txt), your cursor will be positioned at the beginning of the file.

You can start editing a file with the cursor positioned at the end of a file using an edit command — include + with no line number. This may be useful for a large file or even if you just know that you’ll be adding content directly to the bottom of the file.

If you are starting a new Vim session:

$ vim + file.txt

or if you are already in a Vim session:

:e + file.txt

See man vim or :h +cmd for more details.

Match On A Map In A With Construct In Elixir

Many usage example of the with construct show a series of matches on a tuple.

with {:ok, width} <- Map.fetch(opts, :width),
     {:ok, height} <- Map.fetch(opts, :height) do
  {:ok, width * height}

You can match on more than just tuples though. Here is how you might match on a map.

with %{status_code: 200, body: body} <- HTTPoison.get!(url),
     {:ok, decoded_body} <- Poison.decode(body) do
  {:ok, decoded_body}

In fact, you have the full power of Elixir’s pattern matching available to you in your series of matches for a with construct.

Get the return type of a function in TypeScript

Sometimes you only want to rely on the return type of a function instead of defining a new type for it.

To do that in TypeScript use ReturnType and typeof:

function extractStatusData(buffer: Buffer) {
  return {
    active: buffer[0] !== 1,
    totalErrors: buffer[1]

function onStatusChange(callback: (data: ReturnType<typeof extractStatusData>) => void) {
  listenToSomeBinaryStuff(buffer => {
    const statusData = extractStatusData(buffer)

onStatusChange(({active, totalErrors}) => {
  if (active) {
    console.log(`Task is still running`)
  } else {
    console.log(`Task is completed with ${totalErrors} errors`)

Edit A File At A Specific Line Number In Vim

I use long-running Vim sessions where I constantly open files as new buffers with the :edit (or :e) command. Generally, when I open a new file I end up with the cursor at the top of the buffer and go from there. But what if I have a specific line number in mind and I want the cursor to start there?

The :edit command can receive arguments, including a line number argument. To open up to line 159, I can include the +159 argument in the command.

:edit +159 path/to/the/file.txt

See :h :edit and :h +cmd for more details about how :edit works and what the different arguments can do.

Python Help in REPL 🐍

Heading to the internet to get help with a Python function? Slow down! There’s help right in your terminal.

With the Python executable installed, it’s as easy as:

$ python
>>> help()
help> string.lower
Help on function lower in string:

string.lower = lower(s)
    lower(s) -> string

    Return a copy of the string s converted to lowercase.


Comparing DateTime Structs In Elixir

Remember, comparisons in Elixir using ==/2, >/2, </2 and friends are structural and based on the DateTime struct fields. For proper comparison between datetimes, use the compare/2 function.

As the DateTime docs say, you’ll want to use compare/2 in order to accurately compare two DateTime structs.

{:ok, older} = DateTime.from_naive(~N[2016-05-24 13:26:08.003], "Etc/UTC")
{:ok, newer} = DateTime.from_naive(~N[2017-11-24 13:26:08.003], "Etc/UTC"), newer)
#=> :lt, older)
#=> :gt, newer)
#=> :eq

When using compare/2, you’ll get one of :lt, :gt, or :eq as a result, meaning less than, greater than, or equal respectively.

Reset Hub Credentials

On a shared computer, multiple users logged into Hub can lead to confusing Github activity, such as a PR opened from the command line with your name on it that you didn’t open.

These credentials are stored in ~/.config/hub. To reset your Hub credentials, delete this file and run a Hub command, and you will get an opportunity to reautheniticate.