Today I Learned

A Hashrocket project

383 posts by joshbranchaud @jbrancha

Compute md5 Hash Of A String

To compute the md5 digest of a string, we can use Erlang’s top-level md5 function.

> :erlang.md5("#myelixirstatus")
<<145, 148, 139, 99, 194, 176, 105, 18, 242, 246, 37, 69, 142, 69, 226, 199>>

This, however, gives us the result in the raw binary representation. We would like it in a base 16 encoding, as md5 digests tend to be.

We can wrap (or pipe) this with Base.encode16 to get the result we are looking for.

> Base.encode16(:erlang.md5("#myelixirstatus"), case: :lower)
"91948b63c2b06912f2f625458e45e2c7"

source

Counting Records With Ecto

Sometimes you want to know how many records there are in a table. Ecto gives us a couple ways to approach this.

We can use the count1) function that the Ecto query API provides.

> Repo.one(from p in "people", select: count(p.id))

16:09:52.759 [debug] QUERY OK source="people" db=1.6ms
SELECT count(p0."id") FROM "people" AS p0 []
168

Alternatively, we can use the fragment/1 function to use PostgreSQL’s count function.

> Repo.one(from p in "people", select: fragment("count(*)"))

16:11:19.818 [debug] QUERY OK source="people" db=1.5ms
SELECT count(*) FROM "people" AS p0 []
168

Lastly, Ecto.Repo has the aggregate/4 function which provides a :count option.

> Repo.aggregate(from(p in "people"), :count, :id)

16:11:23.786 [debug] QUERY OK source="people" db=1.7ms
SELECT count(p0."id") FROM "people" AS p0 []
168

Unique Indexes With Ecto

You can create a unique index in a migration for one or more columns using the unique_index/3 function.

For example, if you are creating a join table for followers and want to ensure that duplicate follower entries are prevented, you may want to include a unique index like so:

create table(:followers) do
  add :followed_user, references(:users), null: false
  add :following_user, references(:users), null: false
end

create unique_index(:followers, [:followed_user, :following_user])

Keep in mind that unique_index/3 is a shorthand for index/3 when you set unique: true.

Rerun Only Failures With RSpec

After running a big test suite, I may have a bunch of output on the screen including the results of a couple test failures. I like to bring the context of the test failures front and center and make sure they are consistent test failures (not flickering failures). Instead of copying and pasting each failure, I can rerun rspec in a way that executes only the test cases that failed.

$ rspec --only-failures

This feature requires that you set a file for RSpec to persist some state between runs. Do this in the spec/spec_helper.rb file. For example:

RSpec.configure do |config|
  config.example_status_persistence_file_path = "spec/examples.txt"
end

See more details here.

h/t Brian Dunn

Polymorphic Path Helpers

Underlying many of the path helpers that we use day to day when building out the views in our Rails apps are a set of methods in the ActionDispatch::Routing::PolymorphicRoutes module.

The #polymorphic_path method given an instance of a model will produce the relevant show path.

> app.polymorphic_path(Article.first)
  Article Load (0.5ms)  SELECT  "articles".* FROM "articles"  ORDER BY "articles"."id" ASC LIMIT 1
=> "/articles/2"

Given just the model’s constant, it will produce the index path.

> app.polymorphic_path(Article)
=> "/articles"

Additionally, there are variants with edit_ and new_ prefixed for generating the edit and new paths respectively.

> app.edit_polymorphic_path(Article.first)
  Article Load (0.6ms)  SELECT  "articles".* FROM "articles"  ORDER BY "articles"."id" ASC LIMIT 1
=> "/articles/2/edit"
> app.new_polymorphic_path(Article)
=> "/articles/new"

Mark For Destruction

Do you have some complicated logic or criteria for deleting associated records? ActiveRecord’s #mark_for_destruction may come in handy.

Let’s say we have users who author articles. We want to delete some of the user’s articles based on some criteria — those articles that have odd ids.

> user = User.first
#=> #<User...>
> user.articles.each { |a| a.mark_for_destruction if a.id.odd? }
#=> [#<Article...>, ...]
> user.articles.find(1).marked_for_destruction?
#=> true
> user.articles.find(2).marked_for_destruction?
#=> false

We’ve marked our articles for destruction and confirmed as much with the #marked_for_destruction? method. Now, to go through with the destruction, we just have to save the parent record — the user.

> user.save
   (0.2ms)  BEGIN
  User Exists (0.8ms)  SELECT  1 AS one FROM "users" WHERE ("users"."email" = 'person1@example.com' AND "users"."id" != 1) LIMIT 1
  SQL (3.0ms)  DELETE FROM "articles" WHERE "articles"."id" = $1  [["id", 1]]
  SQL (0.2ms)  DELETE FROM "articles" WHERE "articles"."id" = $1  [["id", 3]]
   (2.1ms)  COMMIT
=> true

Note: the parent record must have autosave: true declared on the association.

class User < ActiveRecord::Base
  has_many :articles, autosave: true
end

Convert A Symbol To A Constant

If you have a symbol and need to convert it to a constant, perhaps because of some metaprogramming induced by a polymorphic solution, then you may start off on an approach like the following. In fact, I’ve seen a number of StackOverflow solutions like this.

:module.to_s.capitalize.constantize
#=> Module

That is great for one-word constant names, but what about multi-word constants like OpenStruct. This approach will not work for the symbol :open_struct. We need a more general solution.

The key is to ditch #capitalize and instead use another ActiveSupport method,#classify`. ruby :open_struct.to_s.classify.constantize #=> OpenStruct

Creating Indexes With Ecto

Using indexes in the right places within relational databases is a great way to speed up queries.

To add a basic index in an Ecto migration, use Ecto.Migration.index\2:

create index(:users, [:email])

Creating a composite index doesn’t require jumping through any hoops; just put the relevant column names in the list:

create index(:posts, [:user_id, :title])

See h Ecto.Migration.index for more details.

Use A Case Statement As A Cond Statement

Many languages come with a feature that usually takes the name cond statement. It is essentially another way of writing an if-elsif-else statement. The first conditional in the cond statement to evaluate to true will then have its block evaluated.

Ruby doesn’t have a cond statement, but it does have a case statement. By using a case statement with no arguments, we get a cond statement. If we exclude arguments and then put arbitrary conditional statements after the when keywords, we get a construct that acts like a cond statement. Check out the following example:

some_string = "What"

case
when some_string.downcase == some_string
  puts "The string is all lowercase."
when some_string.upcase == some_string
  puts "The string is all uppercase."
else
  puts "The string is mixed case."
end

#=> The string is mixed case.

source

List The Enqueued Jobs

Many Rails apps need to delegate work to jobs that can be performed at a later time. Both unit and integration testing can benefit from asserting about the jobs that get enqueued as part of certain methods and workflows. Rails provides a handy helper method for checking out the set of enqueued jobs at any given time.

The enqueued_jobs method will provide a store of all the currently enqueued jobs.

It provides a number of pieces of information about each job. One way to use the information is like so:

describe '#do_thing' do
  it 'enqueues a job to do a thing later' do
    Processor.do_thing(arg1, arg2)
    expect(enqueued_jobs.map { |job| job[:job] }).to match_array([
      LongProcessJob,
      SendEmailsJob
    ])
  end
end

To use this in your Rails project, just enable the adapter in your test configuration file:

Rails.application.config.active_job.queue_adapter = :test

Requiring Keys For Structs

When defining a struct in Elixir, we may want to ensure that certain values are provided. We can require that certain keys are used in the creation of a struct with the @enforce_keys attribute. Here is an example of a Name struct.

defmodule Name do
  @enforce_keys [:first, :last]
  defstruct [:first, :middle, :last]
end

With this defined, we can create a struct that uses all of the keys.

> jack = %Name{first: "Jack", middle: "Francis", last: "Donaghy"}
%Name{first: "Jack", last: "Donaghy", middle: "Francis"}

We can also ignore :middle and just provide the required keys.

> liz = %Name{first: "Liz", last: "Lemon"}
%Name{first: "Liz", last: "Lemon", middle: nil}

We cannot, however, omit any of the keys specified in @enforce_keys. If we do omit any of them, Elixir will raise an error.

> tracy = %Name{first: "Tracy"}
** (ArgumentError) the following keys must also be given when building struct Name: [:last]
    expanding struct: Name.__struct__/1
    iex:6: (file)

Virtual Fields With Ecto Schema

If you’d like to include a particular key-value pair in an Ecto changeset, it needs to be included as a field in the schema. In the case of something akin to a password field, you want to be able to perform validations against it, but the password itself does not have a column in the database. In other words, you want to use the password in memory as part of the validation process but not save it to the database. To accomplish this, you need to specify that it is a virtual field.

schema "users" do
  field :username, :string
  field :password_digest, :string
  field :password, :string, virtual: true
end

With that schema, you can then validate the :password and transform it into the corresponding :password_digest field.

def registration_changeset(model, params) do
  model
  |> changeset(params)                  # do other standard validations
  |> cast(params, [:password])          # include :password in the changeset
  |> validate_length(:password, min: 8) # validations
  |> put_pass_hash()                    # transform into :password_digest
end

Generating UUIDs With pgcrypto

If you check out the docs for the uuid-ossp extension, you’ll come across the following message.

The OSSP UUID library… is not well maintained, and is becoming increasingly difficult to port to newer platforms.

A little bit later, it says:

If you only need randomly-generated (version 4) UUIDs, consider using the gen_random_uuid() function from the pgcrypto module instead.

So, if we are using the UUID data type and only need to generate random UUIDs, we can rely on the pgcrypto extension. It comes with the gen_random_uuid() function which generates random v4 UUIDs.

> create extension "pgcrypto";
CREATE EXTENSION

> select gen_random_uuid();
           gen_random_uuid
--------------------------------------
 0a557c31-0632-4d3e-a349-e0adefb66a69

> select gen_random_uuid();
           gen_random_uuid
--------------------------------------
 83cdd678-8198-4d56-935d-d052f2e9db37

Close All Other Splits

If you have a couple other splits open, but you only want the window in focus, you may find yourself doing some finger gymnastics to navigate to those other split windows to close out of them.

There is an easier way.

The Ex command :only will close all other splits, excluding the window that is currently in focus.

See :h :only for more details.

Search Files Specific To A Language

The ack command makes it easy to narrow the set of searched files to those of a specific programming language. For instance, if you have a rails project and only want to search the ruby files, use the --ruby flag with your ack command.

$ ack --ruby Active

With the --ruby flag, I get a manageable number of results. Without it, not so much.

$ ack --ruby Active | wc -l
      26
$ ack Active | wc -l
    5253

See man ack for more details.

Exclude Whitespace Changes From GitHub Diffs

If you run a tidy ship and use plugins like vim-spacejam, then whitespace changes cluttering up your git diffs probably isn’t much of an issue.

However, if you are working with other people or messier code bases, then you may not be so lucky. If there are a bunch of whitespace changes in a commit, then that is going to make the diff view of a commit on GitHub annoying, and perhaps hard, to read.

You can cut to the chase by excluding whitespace changes from GitHub’s diff view by adding w=1 to the diff URL.

Check out this view of the diff and then this view of the diff that excludes whitespace.

source

Simulating Various Connection Speeds In Chrome

I spend everyday building web apps from a machine that has a wired connection to the internet. Though I spend a lot of time loading various pages and experiencing the app like a user might, I end up having a pretty narrow perspective. What will this app be like for people on various qualities of mobile connections?

Chrome has a feature built in to its devtools that makes it easy to throttle your connection to simulate various speeds. Open up devtools with Cmd+Opt+J, navigate to the Network tab, and then open the throttling drop down.

From here we can select the connection speed we want to simulate. If we then reload the page, we will not only experience the page load at that speed, we will also see the numbers in that Network tab.

Render A Template To A String

Templates in a Phoenix application ultimately get compiled to functions that can be quickly rendered with the necessary data. We can take a look at how a template will be rendered using Phoenix.View.render_to_string/3.

First, we need a template:

# user.html.eex
<h1><%= @user.first_name %></h1>
<h5><%= @user.username %> (<%= @user.email %>)</h5>

We can then render that template for the view with some user:

> user = %User{first_name: "Liz", last_name: "Lemon", username: "llemon", email: "lizlemon@nbc.com"}
%MyApp.User{...}

> Phoenix.View.Render_to_string(MyApp.UserView, "user.html", user: user)
"<h1>Liz</h1>\n<h5>llemon (lizlemon@nbc.com)</h5>\n"

Do You Have The Time? - Part 2

In Do You Have The Time?, I demonstrated a way of using an Erlang function to get at and work with time in Elixir. As of Elixir 1.3, there is now a Time module that provides a sigil and some functions for working with time.

We can use Elixir’s Time module to simplify the example from the previous iteration of this TIL:

defmodule TickTock do
  def current_time do
    Time.from_erl!(:erlang.time)
    |> Time.to_string
  end
end

> TickTock.current_time
"19:58:12"

Check For A Substring Match

Using Erlang’s :binary.match function, you can easily check if a string has a matching substring.

> :binary.match("all food is good", "foo")
{4, 3}
> :binary.match("all food is good", "bar")
:nomatch

As you can see, the return value on a successful match is a tuple with the index of where the match starts and the length of the match. If there is no match, the :nomatch atom is returned.

See the match/2 and match/3 docs for more details.

source

Do You Have The Time?

Elixir doesn’t come with any standard ways of getting at or working with time. There are packages like Timex out there that we can pull in to our projects. However, if we don’t have need for a full-featured date/time library, we can opt for a simpler solution.

Erlang can give us the time.

defmodule TickTock do
  def current_time do
    {hh,mm,ss} = :erlang.time
    "#{hh}:#{mm}:#{ss}"
  end
end

> TickTock.current_time
"11:47:13"

Or Operator Precedence

What’s the difference between || and or in Ruby?

Let’s look at an example to find out. First, let’s start with some boolean variables:

> a, b = false, true
=> [false, true]

Now, let’s try the different or operators:

> a || b
=> true
> a or b
=> true

Cool, they seem to work as expected.

Finally, let’s capture the result in a variable:

> c = a or b
=> true
> c
=> false

But why is c false and not true? Operator precedence. The assignment operator (=) takes precedence over the or operator causing c to be assigned to the value of a (false) before or’d with b.

source

Expand Emojis With The Spread Operator

There are a number of emojis that are not stand-alone unicode characters, but instead are a combination of two or more other emojis. The two main places this happens is with family emojis and emojis using non-simpsons skin tones.

You can use JavaScript’s spread operator to expand these emojis to see what their base components are. Here is a screenshot of a few that I expanded from Chrome’s dev tools.

source

Documentation Lookup With Vim and Alchemist

Which argument position is the accumulator for Enum.reduce/3?

How does group_by work?

I find myself fairly frequently jumping from vim to Chrome to do Google searches for Elixir standard lib documentation. It gets the job done, but it is kinda slow and I’d prefer to avoid the context switch.

With alchemist.vim, Elixir documentation lookup is at your finger tips. Just move the cursor over the module or function you are curious about and hit K (from normal mode).

Curious about Enum.reduce? Type it out in your current Vim buffer, move the cursor over it, and hit K.

Updating Values In A Map

When working with maps in any language, you often need a way to update key-value pairs. Furthermore, you will need a way to handle keys that are not already present in the map, generally associating some default value.

In Elixir, the Map module provides the get_and_update/3 function as a way of accomplishing such a task.

Let’s use a score counting example to see it in action:

> scores = %{}
%{}
# jake scores a point
> {_, scores} = Map.get_and_update(scores, :jake, fn(x) -> {x, (x || 0) + 1} end)
{nil, %{jake: 1}}
# chris scores a point
> {_, scores} = Map.get_and_update(scores, :chris, fn(x) -> {x, (x || 0) + 1} end)
{nil, %{chris: 1, jake: 1}}
# jake scores another point
> {_, scores} = Map.get_and_update(scores, :jake, fn(x) -> {x, (x || 0) + 1} end)
{1, %{chris: 1, jake: 2}}
# final scores
> scores
%{chris: 1, jake: 2}

We use (x || 0) + 1 as a way of providing an initial score for new keys.

The update function is expected to return a tuple with the original value and the updated value.

See the docs for more details.

Rotate Everything By 13 Letters

For some inane reason, Vim comes with a ROT-13 feature. So, if you are ever in need of rotating the letters of some portion of the file by 13, you can do that with the simple g? binding.

For example, if you hit g?? on the following line:

Six dollar eggs

you will get

Fvk qbyyne rttf

As you can see, casing is preserved.

The only practical uses of this are Vimgolf and convincing people at coffee shops that you are a hacker.

See :h g? for more details.

Show Matching Entries For Help

Looking up things with Vim’s :help command can be error prone if you don’t know exactly how to format what you are looking up. Bypass some of the guesswork by hitting Ctrl-d after writing part of the :help command. This will populate a wildmenu of possible matches.

For instance, if you know there is a command containing ?, but you aren’t sure how to look it up, try the following:

:help ?<Ctrl-d>

You can tab through to the one you want and hit enter to read up on it. Who knew there were so many Vim bindings involving a ?.

See :h help-context for more details.

Checking Commit Ancestry

I have two commit shas and I want to know if the first is an ancestor of the second. Put another way, is this first commit somewhere in the history of this other commit.

Git’s merge-base command combined with the --is-ancestor flag makes answering this question easy. Furthermore, because it is a plumbing command, it can be used in a script or sequence of commands as a switch based on the answer.

Here is an example of this command in action:

$ git merge-base --is-ancestor head~ head && echo 'yes, it is'
yes, it is
$ git merge-base --is-ancestor head~ head~~ && echo 'yes, it is'

In the first command, head~ is clearly an ancestor of head, so the echo command is triggered. In the second, head~ is not an ancestor of head~~ so the return status of 1 short-circuits the rest of the command. Hence, no echo.

See man git-merge-base for more details.

source

List Different Commits Between Two Branches

There are times when I want to get a sense of the difference between two branches. I don’t want to look at the actual diff though, I just want to see what commits are on one and the other.

I can do just this by using the git-log command with a couple flags, most importantly the --cherry-pick flag.

To compare the feature branch against the master branch, I can run a command like the following:

$ git log --left-right --graph --cherry-pick --oneline feature...branch

This lists commits with the first line of their messages. It also includes either a < or > arrow at the front of each commit indicating whether the commit is on the left (feature) or right (master) branch, respectively.

Note: you can use more than branches in a command like this. Any two references will work. You can just use two SHAs for instance.

source

Jump To The Ends Of Your Shell History

There are all sorts of ways to do things in your shell environment without reaching for the arrow keys. For instance, if you want to move up to the previous command, you can hit Ctrl-p. To move down to the next command in your shell history, you can hit Ctrl-n.

But what if you want to move to the beginning and end of your entire shell history?

Find your meta key (probably the one labeled alt) and hit META-< and META-> to move to the end and beginning of your shell history, respectively.

source

List Names Of Files With Matches

I often use grep and ag to search for patterns in a group or directory of files. Generally I am interested in looking at the matching lines themselves. However, sometimes I just want to know the set of files that have matches. Both grep and ag can be told to output nothing more than the names of the files with matches when given the -l flag.

This can come in particularly handy if you just want a list of files that can be piped (or copied) for use with another command. This eliminates all the extra noise.

h/t Dillon Hafer

Reversing A List

To efficiently work with and transform lists in Elixir, you will likely need utilize a list reversing function from time to time. Your best bet is to reach for the Erlang implementation which is available as part of the lists module.

Here are a couple examples of how to use it:

> :lists.reverse([1,2,3])
[3, 2, 1]
> :lists.reverse([1, :a, true, "what", 5])
[5, "what", true, :a, 1]

Note: though I said “transform lists” above, what is actually going on is that a new version of the list representing my transformation is being created, per Elixir’s functional nature.

Reset Target tslime Pane

The combination of tslime and turbux makes running tests from Vim in a tmux session as easy as a single key binding. One problem that can arise from time to time is having tslime focused on an undesired tmux window/pane combination. There is no binding to tell tslime that you’d like to re-select the target window and pane.

I’ve often resorted to closing out of Vim in order to reset the prompt. There is a better way and it doesn’t require you to wipe out your Vim session.

Just unlet the global Vim variable for the tslime plugin like so:

:unlet g:tslime

The next time you invoke turbux it will see that g:tslime isn’t set and will prompt you for a new window and pane combination.

h/t Josh Davey

Dynamically Generating Atoms

Atoms are constants where their name is their own value.

The use of atoms like :ok and :error show up all over the place in Elixir. These are atoms that tend to be statically defined. Atoms can also be dynamically defined using string interpolation.

For example, I can generate a handful of atoms by mapping over a range of integers.

> Enum.map(1..5, &(:"some_atom_#{&1}"))
[:some_atom_1, :some_atom_2, :some_atom_3, :some_atom_4, :some_atom_5]

Note: atoms are not garbage collected. If you dynamically generate atoms in excess, you may run your VM out of heap space.

List Of Sessions To A Machine

The last command is a handy way to find out who has been connecting to a machine and when.

Last will list the sessions of specified users, ttys, and hosts, in reverse time order. Each line of output contains the user name, the tty from which the session was conducted, any hostname, the start and stop times for the session, and the duration of the session. If the session is still continuing or was cut short by a crash or shutdown, last will so indicate.

In particular, this can be useful for finding an IP address that you want to connect to.

See man last for more details.

Assert An Exception Is Raised

Elixir’s ExUnit comes with a number of different ways to make assertions in your tests. One of those functions is assert_raise which allows you to test that a particular exception is raised when the given function is invoked.

Using assert_raise/2 looks something like this:

assert_raise FunctionClauseError, fn ->
  Enum.chunk([1,2,3], 0)
end

The assert_raise/3 form is also available which allows you to test both the type of exception and the resulting message.

assert_raise FunctionClauseError, ~r/^no function clause matching/, fn ->
  Enum.chunk([1,2,3], 0)
end

Using the regex sigil for the second argument is generally a good way to go to keep tests from getting too brittle.

String Interpolation With Just About Anything

Coming to Elixir from Ruby, I am used to being able to interpolate literally anything into a string. In Elixir, this is not the case.

By default, it handles strings, atoms (including nil, true, false and module name aliases like String – which are all just atoms behind the scenes), integers, floats, and some lists. That’s it.

There are two approaches you can take to interpolate everything else into a string. The easier approach is to use Kernel.inspect/2.

> IO.puts "A map #{inspect %{a: 1, b: 2}}"
A map %{a: 1, b: 2}

The other approach is to implement the String.Chars protocol for the thing that you are trying to print. You can read more about that in Elixir String Interpolation for Rubyists.

Pattern Matching In Anonymous Functions

Pattern matching shows up everywhere in Elixir, even where you may not be expecting it. When declaring an anonymous function, you can use pattern matching against different sets and shapes of input parameters to invoke different behaviors.

Here is an example of how you might use this:

> handle_result = fn
  {:ok, result} -> IO.puts "The result is #{result}"
  :error -> IO.puts "Error: couldn't find anything"
end
#Function<6.50752066/1 in :erl_eval.expr/5>

> Map.fetch(%{a: 1}, :a) |> handle_result.()
The result is 1
:ok
> Map.fetch(%{a: 1}, :b) |> handle_result.()
Error: couldn't find anything
:ok

source

Quitting IEx

There are two ways to quit out of an Interactive Elixir shell. The standard way is with Ctrl-c. This gives you a list of options, one of which is a for abort. This will terminate your IEx session and drop you back on the command line where the process started.

Additionally, IEx also understands Ctrl-\ which is control key that will terminate just about any interactive environment. This command will cause IEx to immediately exit with no prompt. Note: IEx does not, however, respond to Ctrl-d. source

Diffing With Patience

The default diff algorithm used by Git is pretty good, but it can get mislead by larger, complex changesets. The result is a noisier, misaligned diff output.

If you’d like a diff that is generally a bit cleaner and can afford a little slow down (you probably can), you can instead use the patience algorithm which is described as such:

Patience Diff, instead, focuses its energy on the low-frequency high-content lines which serve as markers or signatures of important content in the text. It is still an LCS-based diff at its core, but with an important difference, as it only considers the longest common subsequence of the signature lines:

Find all lines which occur exactly once on both sides, then do longest common subsequence on those lines, matching them up.

You can set this as the default algorithm by adding the following lines to your ~/.gitconfig file:

[diff]
    algorithm = patience

or it can be set from the command line with:

$ git config --global diff.algorithm patience

source

h/t Josh Davey

Execute Raw SQL In An Ecto Migration

If you are performing a database migration with Ecto, perhaps the most straightforward approach is to use Ecto’s DSL. However, the DSL may not always be the best choice. Being able to write raw SQL gives you more control. It will also enable you to use database features that may not be directly or easily available through the DSL.

Raw SQL can be included in a Ecto migration with a combination of Elixir’s heredoc syntax and the Ecto.Migration#execute/1 function. You’ll also need to provide both an up and down function to ensure that your migrations are reversible.

defmodule MyApp.Repo.Migrations.CreatePostsTable do
  use Ecto.Migration

  def up do
    execute """
      create table posts (
        id serial primary key,
        title varchar not null,
        body varchar not null default '',
        inserted_at timestamptz not null default now(),
        updated_at timestamptz not null default now()
      );
    """
  end

  def down do
    execute "drop table posts;"
  end
end

Word Lists For Atoms

The ~w sigil works similarly to Ruby’s %w (word array notation). It allows you to create a list of words (i.e. strings).

> ~w(one two three)
["one", "two", "three"]

It sets itself apart though with some modifiers. The default behavior matches the s modifier (for strings).

> ~w(one two three)s
["one", "two", "three"]

Where it gets more interesting is with the a modifier allowing you to create a list of atoms.

> ~w(one two three)a
[:one, :two, :three]

Note: there is a third modifier, c, for char lists.

> ~w(one two three)c
['one', 'two', 'three']

source

List Functions For A Module

During an iex session, I can do a little introspection on modules using either the __info__/1 function or Erlang’s module_info/0 function. In particular, I can pass :functions to either one to get a list of the functions for that module.

This is what __info__/1 looks like for the functions of the List module:

> List.__info__(:functions)
[delete: 2, delete_at: 2, duplicate: 2, first: 1,
 flatten: 1, flatten: 2, foldl: 3, foldr: 3, insert_at: 3,
 keydelete: 3, keyfind: 3, keyfind: 4, keymember?: 3,
 keyreplace: 4, keysort: 2, keystore: 4, keytake: 3,
 last: 1, replace_at: 3, to_atom: 1, to_existing_atom: 1,
 to_float: 1, to_integer: 1, to_integer: 2, to_string: 1,
 to_tuple: 1, update_at: 3, wrap: 1, zip: 1]

source

Blank Lines Above And Below

Generally when I want to add a line above or below the line that the cursor is on, I use O and o, respectively. This has a couple potential drawbacks. First and most prominent, the cursor is moved to the new line and left in insert mode. Usually, I’d like to remain in normal mode and stay on the current line. Second, these commands will emulate indentation and other formatting rules. This is either exactly what you want or a bit of an annoyance.

The vim-unimpaired plugin provides an alternative worth adding to your toolbelt. By hitting [<space> and ]<space>, a new line will be opened above and below the current line, respectively. Additionally, it leaves you in normal mode, keeps the cursor on the current line, and moves the cursor to the first non-indented character. In the case of performing this command in the midst of a comment in a source code file, neither the indentation nor the comment character will be propagated onto the new line.

Hold on to O/o and [<space>/]<space> and know the difference. You’ll likely need each of them from time to time.

h/t Josh Davey