Today I Learned

A Hashrocket project

412 posts by joshbranchaud @jbrancha

String Interpolation With Template Literals

ES6 adds support for template literals. Template literals make it much easier to compose strings of content — string interpolation. They allow for single and double quotes without having to fuss with escaping. Embedded expressions are also supported which means you can avoid awkward-to-type string concatenation with the + operator.

Here is an example:

> let movie = 'it'
undefined
> `What's up, I just saw "${movie.toUpperCase()}".`
"What's up, I just saw "IT"."

Proxy To An API Server In Development With CRA

create-react-app is a great way to bootstrap a React project, especially if you are building a single-page app. When building an SPA, you more likely than not will have a backend API that you interact with.

You can set up your React app to interact with that backend API server in development using the proxy configuration in package.json.

// package.json
  ...
  "proxy": "http://localhost:4000",
}

This will allow you to keep your API calls nice and clean.

fetch("/api/session", ...

No need to manage some sort of host URL environment variable.

Additionally, this will remove an CORS issues because the webpackDevServer will be proxying any paths that it doesn’t recognize to the host and port that you’ve specified.

See the create-react-app docs for more details.

Split The Current Window

Generally when I want to open up a buffer in a window split, I use :sp or :vsp and type out the filename. It may be a bit more convenient to use window commands to create the splits.

To open a horizontal split:

Ctrl-w s

To open a vertical split:

Ctrl-w v

With the split made, you can use Ctrl-o/Ctrl-i, BufExplorer, or whatever way you like to navigate between buffers.

h/t Ryan Messner

Show File Diffs When Viewing Git Log

Include the -p flag with the git log command to include the diffs along with the rest of the information for each commit. Here is an example of running this against my TIL repository.

$ git log -p
commit b9809a329acd8150b2474168f8faaf008f376e35
Author: jbranchaud <jbranchaud@gmail.com>
Date:   Wed Oct 11 07:27:53 2017 -0500

    Add Inline Style Attributes Should Be Camel Cased as a react til

diff --git a/README.md b/README.md
index c982f8e..6ee7d32 100644
--- a/README.md
+++ b/README.md
@@ -10,7 +10,7 @@ smart people at [Hashrocket](http://hashrocket.com/).
 For a steady stream of TILs from a variety of rocketeers, checkout
 [til.hashrocket.com](https://til.hashrocket.com/).

-_574 TILs and counting..._
+_575 TILs and counting..._

 ---

See man git-log for more details.

Inline Style Attributes Should Be Camel Cased

When adding a few quick styles to React components, you can add it directly on the tags in the JSX. To do this, use the style tag with a plain old JavaScript object of styles.

<div style={{ padding: "1em", color: "#fff" }}>

If you are using a CSS attribute that is normally hyphenated like padding-top or background-color, you’ll need to camel case it in the JSX.

<div style={{ paddingTop: "1em", backgroundColor: "#fff" }}>

This is because our styles now need to conform to JavaScript syntax rules since they are in the form of a POJO.

Read the documentation for more details.

Passing Props Down To React-Router Route

When using react-router, you’ll often use the component prop to have a certain component rendered.

<Route
  path="/my/path"
  component={MyComponent}
/>

If, however, you need to pass props down into MyComponent, then you’ll want to use the render prop with an inline function.

<Route
  path="/my/path"
  render={(routeProps) => (
    <MyComponent {...routeProps} {...props} />
  )}
/>

The two spread operator statements are essential. They will pass down the route props that Route would have passed down plus the additional set of props that you want to pass down.

Break Current tmux Pane Out To Separate Window

You have a split pane open in your current window. Perhaps it is running a local server or has a connection to a database. The pane is taking up too much space in the current window, but it is important so you don’t want to just kill it. If that is the case, break it out into a separate window.

With that pane in focus, enter into command mode (<prefix>:) and then issue the break-pane command.

Alternatively, you can trigger this with a keybinding: <prefix>!.

See man tmux for more details.

Jump To The Next Misspelled Word

If you turn on spelling with set spell, Vim will highlight any words it considers misspelled. For a large document it can be tedious to scroll through and find all of the spelling errors.

Fortunately, Vim makes it easy to jump to the next misspelled word. Hit ]s and your cursor will be transported to that word.

Likewise, hit [s to jump backwards in the document to the closest misspelled word behind the cursor.

See h ]s for more details.

Show Create Statement For A Table In MySQL

In MySQL, you can get a quick rundown of a table using describe users. An alternative to this approach is to have MySQL show the create statement for a table.

> show create table users\G
*************************** 1. row ***************************
       Table: users
Create Table: CREATE TABLE `users` (
  `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
  `first_name` varchar(80) NOT NULL,
  `last_name` varchar(80) NOT NULL,
  `email` varchar(80) NOT NULL,
  `middle_initial` varchar(80) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `unique_email` (`email`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1

This includes some additional information like primary key and index information. It is also a great way to study the SQL that it takes to create all the facets of a table.

See the show create table docs for more details.

h/t Jake Worth

Use dotenv In A Non-Rails Project

Up to now I’ve only used dotenv in a Rails context. It can just as easily be used in a plain old Ruby project.

Install the non-Rails version of the gem.

$ gem install dotenv

Then add the following lines wherever you want dotenv included and loaded. In my case, I want it pulled in as part of my RSpec setup in spec_helper.rb.

require 'dotenv'
Dotenv.load

Your environment variables declared in .env are now accessible via fetches against the ENV object.

ENV.fetch('my_env_var')

Force A Component To Only Have One Child

A component can normally have an arbitrary number of elements nested directly inside it. React’s Children.only function can be used to force it to a single direct child.

import React, { Children, Component } from "react";

class App extends Component {
  render() {
    return (
      <SingleChildContainer>
        <span>There can only be one!</span>
      </SingleChildContainer>
    );
  }
}

const SingleChildContainer = props => {
  return Children.only(props.children);
};

export default App;

The React docs describe the behavior of Children.only as such, “Returns the only child in children. Throws otherwise.”.

If you modify the return in App to contain the following JSX

<SingleChildContainer>
  <span>There can only be one!</span>
  <div>What about me?!</div>
</SingleChildContainer>

then an error will be thrown (React.Children.only expected to receive a single React element child).

The Provider component in react-redux is an example of where this is used.

From Ruby Variables To JavaScript Variables

I sometimes find myself writing so much Ruby that as soon as I am back in a JavaScript file, my code starts looking like this:

const my_javascript_var = 123;

It would be easy enough to hit caw to the delete the entire word and then retype it as camel case. I happen to have the Abolish.vim plugin installed, so there is an even quicker way.

If I hit crc over the variable, it will be coerced to camel case.

const myJavascriptVar = 123;

If I hit crs then it will be coerced back to snake case. Hit crc one more time and I can get back to writing some JavaScript.

See :h abolish-coercion for more details.

Escaping String Literals With Dollar Quoting

String literals in PostgreSQL are defined by surrounding the content with the ' character. For string literals that contain the ' character, you may have seen it escaped with a preceding '.

> select 'Isn''t this nice?';
     ?column?
------------------
 Isn't this nice?

This is easy enough to do, but can be error prone and doesn’t work well if SQL is being programmatically generated. A great workaround is to escape string literals using what is called dollar quoting.

> select $$Isn't this even nicer?$$;
        ?column?
------------------------
 Isn't this even nicer?

Just wrap both ends in $$ instead of '.

source

Require Additional JS Libraries In Postman

When writing pre-request scripts and test scripts as part of a Postman request, you aren’t limited to vanilla JavaScript. There are a handful of libraries that can be required where needed.

This short list of available libraries includes cherrio, lodash, and moment.

To pull one of these into a particular script, use the standard require feature:

var moment = require('moment');

var now = moment();

For a full list of what is available, check out Postman’s Sandbox API Reference.

Render An Array Of Elements With React 16

React 16 was released today. Among many exciting features and updates is support for rendering an array of elements.

This can look as simple as this example:

return [
  <li key="1">One</li>,
  <li key="2">Two</li>,
  <li key="3">Three</li>
];

It really shines in the case of generating elements from an array of data.

let data = [
  { value: "One", key: "1" },
  { value: "Two", key: "2" },
  { value: "Three", key: "3" }
];
return data.map(item => {
  return (
    <li key={item.key}>
      {item.value}
    </li>
  );
});

No need to wrap the result in a <div>!

source

Matching Multiple Values In A Switch Statement

Switch statements are a handy way to execute different branches of code based on a value match. This is often what is used in Redux reducers when updating the state in response to certain actions.

But what if you need multiple values to result in the same branch of execution without duplicating the code?

The execution of a switch statement falls through, so after one match, it will continue to try and do subsequent matches if you don’t interrupt the execution with a break or return. Conveniently, this solves our problem of matching multiple values.

switch (action.type) {
  case "UPDATE_NAME":
  case "UPDATE_DURATION":
    let newData = anotherReducer(state.data, action);
    return { ...state, data: newData };
  default:
    return state;
}

See the MDN docs for more details.

Generate New Phoenix App Without Brunch

By default when you create a new Phoenix app using phx.new, a set of files and configurations will be generated for Brunch. Though the Phoenix team decided to use Brunch, you don’t have to. You may not want Phoenix to handle asset building or you may just prefer another build tool. Either way, if you’d like to opt out, you can include the --no-brunch flag when generating the project.

$ mix phx.new --no-brunch my_app

If you have an existing project that you’d like to remove Brunch from, there is some information in Phoenix’s Static Assets documentation.

Fix The Spelling Of A Word

If there is a misspelled word (:set spell to see what is misspelled), you can navigate the cursor over that word and hit (from normal mode) z=. This will open up a screen of possible corrections. The one you are most likely looking for will be toward the top. Each possible spelling will have a number next to it. Enter the number of the word you are looking for and hit enter. The spelling of that word will have been updated.

Try misspelling something and give it a try yourself.

See :h z= for more details.

h/t Jake Worth

Serve Static Assets From Custom Phoenix Directory

When you new up a Phoenix project, an endpoint.ex file will be generated. This file is full of different plugs for handling incoming traffic. The Plug.Static declaration specifies how your application will handle and serve requests for static files.

  plug Plug.Static,
    at: "/", from: :my_app, gzip: false,
    only: ~w(css fonts images js favicon.ico robots.txt)

The from options declares where these static files are located. In this case it references our application (:my_app) as the target which will translate to its priv/static directory.

If you instead want to serve your files from a different, custom directory, you can replace it with the path to that directory.

  plug Plug.Static,
    at: "/", from: "priv/my_frontend/static", gzip: false,
    only: ~w(css fonts images js favicon.ico robots.txt)

source

Specifying The Digest Directory For Phoenix

By default, Phoenix targets priv/static when preparing digested assets for production. This process happens when running mix phx.digest.

If you are doing some custom work with your assets such that they are in a different location, you’ll need to tell Phoenix where to look. To do this, just include an optional path argument.

$ mix phx.digest path/to/my/assets

The digests will be put in that target directory. If you’d like to specify a different output directory, such as priv/static, include the -o flag.

$ mix phx.digest path/to/my/assets -o priv/static

Capitalize All The Words In PostgreSQL

PostgreSQL provides the string function initcap() as a way of capitalizing all words. In the process, it cleans up the casing of the remaining parts of the words.

Here are some examples of how it works.

> select initcap('hello, world');
   initcap
--------------
 Hello, World

> select initcap('HELLO, WORLD');
   initcap
--------------
 Hello, World

See the String Functions and Operators docs for more details.

Lighten And Darken With CSS Brightness Filter

CSS has a filter property that can be used with a variety of filter functions. One of them is the brightness() filter. By feeding a percentage less than 100% to brightness(), the target element will be made darker. Inversely, feeding a percentage greater than 100% to brightness() will make the element brighter.

.brighter-span {
  filter: brightness(150%);
}

.darker-span {
  filter: brightness(50%);
}

brighter, regular, and darker spans

See this CSS Tricks Article on the filter property for more details. Check out the browser support story here.

Go To File With Line Number

I often use gf as supported by Vim or with the help of plugins like rails.vim as a way of quickly navigating to existing files. For unloaded files, this loads a buffer with the cursor at the top of the buffer. For existing buffers, it opens to that buffer with the cursor where it was when you left.

Vim also supports a slightly fancier goto file command, gF. If this command is used while the cursor is over a file with a line number appended to the end, it will not only open up a buffer with that file, it will move the cursor to the specified line number.

With this repository, I could try it out by moving the cursor over the following text and hitting gF.

README.md:100

This will open up a buffer for README.md with the cursor at line 100.

See :h gF for more details.

Access A Value Logged To The DevTools Console

Did your app just log an object to the dev tools console and you’d like to interact with that object? It’s not straightforward, but you can do it.

Assuming you already have dev tools opened to the console tab, right click on the value that has been logged to the console. Select the Store as Global Variable option. This will re-log the value assigning it to the temp1 variable.

You can now reference that object as temp1 accessing its values and calling functions.

You can even do this with multiple logged values, each subsequent one will be assigned incrementing variable names: temp2, temp3, etc.

source

List Files Ordered By Modification Date

The ls command lists the files in a directory. Tacking on the -l flag will list it in long format. By default, everything is listed in lexicographical order. This is what ls -l looks like for this repository.

-rw-r--r--    1 jbranchaud  staff    628 Feb 14  2016 CONTRIBUTING.md
-rw-r--r--    1 jbranchaud  staff   1058 Feb 19  2015 LICENSE
-rw-r--r--    1 jbranchaud  staff  40983 Aug 18 16:59 README.md
drwxr-xr-x    5 jbranchaud  staff    170 Apr  1 14:45 ack
drwxr-xr-x    5 jbranchaud  staff    170 Feb 24 16:31 chrome
...

Sometimes you want a sense of what has been modified and when. Lexicographical order isn’t going to help much here. By tacking on the -t flag, the files will be listed in order of their modification dates. Here is ls -lt for the same repository.

-rw-r--r--    1 jbranchaud  staff  40983 Aug 18 16:59 README.md
drwxr-xr-x  119 jbranchaud  staff   4046 Aug 17 11:38 vim
drwxr-xr-x    5 jbranchaud  staff    170 Aug 16 10:47 internet
drwxr-xr-x   23 jbranchaud  staff    782 Aug  1 10:17 javascript
drwxr-xr-x    7 jbranchaud  staff    238 Jul 22 14:04 webpack
...

See man ls for more details.

Quickly Switch To A Buffer By Number

There are a number of different commands you can use for switching to a buffer by its number. For example, if you want to switch to the buffer assigned 7, you can do :7b or :e #7. However, there is a quicker way than typing out either of those commands.

You may already be familiar with CTRL-^ for switching to the alternate file which is generally the previous buffer. If you precede that command with a number, you will switch to the buffer with that number instead of the alternate file.

From normal mode

7 Ctrl-^

will switch to buffer 7.

See :h Ctrl-^ for more details.

Search Tweets By Author

Twitter has some advanced search features that allow you to do more than just search by keyword. The from:<author> syntax is the way that you can restrict your search results to a specific twitter user.

twitter from search

By using "pair programming" from:hashrocket, I am able to find all of the tweets by @hashrocket that use the exact phrase pair programming.

Detect If You Are On A Mac

There are a couple ways of detecting with vimscript if you are on a mac. This can be useful if you are writing a plugin with OS-specific functionality. Here are two ways to make that check.

if has('macunix') || has('mac') || has('osx')
  ...
endif

Alternatively, you can use Vim’s system() function to execute unix’s uname command. This command will give you the name of the operating system. In the event you are using a Mac, the result of uname should be Darwin. The following regex match is a good way to make this check.

if system('uname') =~ "Darwin"
  ...
endif

See :h has(), :h system(), and man uname for more details.

Check For An Executable

Sometimes Vim needs to reach outside of itself to use an existing program. For example, wiring up auto-formatting of JavaScript code requires Vim to call out to the prettier binary.

We want our .vimrc files and plugins to, generally, be as portable as possible. What happens if you haven’t yet installed a particular program? Vim will likely experience a runtime exception. One way to get around this is to check for the presence of that program on the path. If it isn’t there, don’t do the thing. We can use the executable() function for this.

if executable('prettier')
  ...
endif

It will return 1 (true) if prettier is an executable on the path, otherwise it will return 0 (false).

See :help executable() for more details.

Create Bootstrapped Apps With Yarn

The yarn cli comes with a create command that is a convenience command for generating bootstrapped apps that follow the create-<name>-app convention.

Want to create a React.js app using create-react-app, invoke the following command:

$ yarn create react-app my-app

Don’t already have a particular package globally installed? yarn create will install it for you. For instance, the following command with install and use create-vue-app:

$ yarn create vue-app my-other-app

h/t Gabe Reis

Specify Port Of CRA's Webpack Dev Server

create-react-app gives you a set of scripts, one of which allows you to start a development server that bundles and serves your javascript. This is handled under the hood via webpack-dev-server. By default it attempts to serve from port 3000. If port 3000 is taken it will attempt to connect to another sequential port.

Alternatively, you can just specify the port when starting the development server. This can be done with the PORT env var.

$ PORT=3333 yarn start

Yarn Commands Without The Emojis

If you are a hater and you’d like to run yarn commands without emojis being playfully included in the output, just include the --no-emoji flag. The output of a command like add will look like this:

$ yarn add chalk --no-emoji
yarn add v0.17.10
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
[4/4] Building fresh packages...
success Saved lockfile.
success Saved 7 new dependencies.
├─ ansi-styles@3.1.0
├─ chalk@2.0.1
├─ color-convert@1.9.0
├─ color-name@1.1.3
├─ escape-string-regexp@1.0.5
├─ has-flag@2.0.0
└─ supports-color@4.2.0
Done in 0.54s.

See yarn help for details.

Rebase Commits With An Arbitrary Command

Interactive rebasing is a powerful way to manage and tend to the history of a git repository. Rewording and squashing commits are fairly common actions. But what if you need to run some arbitrary command against a series of recent commits?

This is where the --exec flag comes in to play.

$ git rebase -i HEAD~3 --exec "git commit --amend --reset-authors -CHEAD"

This generates an interactive rebase file that you can review and save when ready.

pick ea4a215 Add Globally Install A Package With Yarn as a javascript til
exec git commit --amend --reset-author -CHEAD
pick a4f4143 Add Initialize A New JavaScript Project With Yarn as a javascript til
exec git commit --amend --reset-author -CHEAD
pick 2f00aeb Add Default And Named Exports From The Same Module as a javascript til
exec git commit --amend --reset-author -CHEAD

As you can see, the specified command is prepared for execution for each commit involved in the rebase.

h/t Patricia Arbona

Default And Named Exports From The Same Module

ES6 module syntax allows for a single default export and any number of named exports. In fact, you can have both named exports and a default export in the same module.

Here is an example:

// src/animals.js
export default function() {
  console.log('We are all animals!');
}

export function cat() {
  console.log('Meeeow!');
}

export function dog() {
  console.log('Rufff!');
}

In this case, you could import the default and named exports like so:

// src/index.js
import animals, { cat, dog } from './animals.js';

animals(); // "We are all animals!"
cat();     // "Meeeow!"
dog();     // "Rufff!"

source

Show Tables That Match A Pattern In MySQL

An unfamiliar MySQL database with tons of tables can be a difficult thing to navigate. You may have an idea of the kind of table you are looking for based on a domain concept you’ve seen elsewhere.

You can pare down the results returned by show tables by including a like clause with a pattern. For example, this statement will show me only tables that have the word user in them:

> show tables like '%user%';
+-------------------------------+
| Tables_in_jbranchaud (%user%) |
+-------------------------------+
| admin_users                   |
| users                         |
+-------------------------------+

Rename A Remote

If you just added a remote (git remote add ...) and messed up the name or just need to rename some existing remote, you can do so with the rename command.

First, let’s see the remotes we have:

$ git remote -v
origin  https://github.com/jbranchaud/til.git (fetch)
origin  https://github.com/jbranchaud/til.git (push)

To then rename origin to destination, for example, we can issue the following command:

$ git remote rename origin destination

See man git-remote for more details.

Dump A MySQL Database To A File

The mysqldump client is a handy tool for creating a backup or snapshot of a MySQL database. The standard use of this command produces an alphabetical series of statements that comprise the structure and data of the specified database. It directs all of this to stdout. You’ll likely want to redirect it to a file.

$ mysqldump my_database > my_database_backup.sql

The output will include special comments with MySQL directives that disable things like constraint checking. This is what allows the output to be in alphabetical order without necessarily violating any foreign key constraints.

If you need to dump multiple databases, include the --databases flag with a space-separated list of database names. Or dump all of them with --all-databases.

See man mysqldump for more details.

Display Output In A Vertical Format In MySQL

Output for tables with lots of columns can be hard to read and sometimes overflow the terminal window. Consider the output from Show Indexes For A Table:

> show indexes in users;
+-------+------------+--------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name     | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+--------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| users |          0 | PRIMARY      |            1 | id          | A         |           0 |     NULL | NULL   |      | BTREE      |         |               |
| users |          0 | unique_email |            1 | email       | A         |           0 |     NULL | NULL   |      | BTREE      |         |               |
+-------+------------+--------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

We can vertically orient the output of a statement by terminating it with \G instead of ; (or \g).

> show indexes in users\G
*************************** 1. row ***************************
        Table: users
   Non_unique: 0
     Key_name: PRIMARY
 Seq_in_index: 1
  Column_name: id
    Collation: A
  Cardinality: 0
     Sub_part: NULL
       Packed: NULL
         Null:
   Index_type: BTREE
      Comment:
Index_comment:
*************************** 2. row ***************************
        Table: users
   Non_unique: 0
     Key_name: unique_email
 Seq_in_index: 1
  Column_name: email
    Collation: A
  Cardinality: 0
     Sub_part: NULL
       Packed: NULL
         Null:
   Index_type: BTREE
      Comment:
Index_comment:

Show Indexes For A Table In MySQL

When describing a table, such as users:

> describe users;
+------------+-----------------------+------+-----+---------+----------------+
| Field      | Type                  | Null | Key | Default | Extra          |
+------------+-----------------------+------+-----+---------+----------------+
| id         | mediumint(8) unsigned | NO   | PRI | NULL    | auto_increment |
| first_name | varchar(80)           | NO   |     | NULL    |                |
| last_name  | varchar(80)           | NO   |     | NULL    |                |
| email      | varchar(80)           | NO   | UNI | NULL    |                |
+------------+-----------------------+------+-----+---------+----------------+

We can see in the Key column that there’s a primary key and a unique key for this table on id and email, respectively.

These keys are indexes. To get more details about each of the indexes on this table, we can use the show indexes command.

> show indexes in users;
+-------+------------+--------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+
| Table | Non_unique | Key_name     | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type |
+-------+------------+--------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+
| users |          0 | PRIMARY      |            1 | id          | A         |           0 |     NULL | NULL   |      | BTREE      |
| users |          0 | unique_email |            1 | email       | A         |           0 |     NULL | NULL   |      | BTREE      |
+-------+------------+--------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+

List Databases And Tables In MySQL

If you’ve started a mysql session, but haven’t connected to a particular database yet, you can list the available databases like so:

> show databases;
+-----------------------------+
| Database                    |
+-----------------------------+
| information_schema          |
| my_app_dev                  |
+-----------------------------+

If you are curious about the tables in a particular database, you can list them by specifying the database’s name:

> show tables in my_app_dev;
+------------------------------+
| Tables_in_my_app_dev         |
+------------------------------+
| pokemons                     |
| trainers                     |
+------------------------------+

Alternatively, you can connect to the database of interest and then there is no need to specify the name of the database going forward.

> use my_app_dev;
> show tables;
+------------------------------+
| Tables_in_my_app_dev         |
+------------------------------+
| pokemons                     |
| trainers                     |
+------------------------------+

Change The Nullability Of A Column

Do you have an existing table with a column that is exactly as you want it except that it needs to be changed to either null: false or null: true?

One option is to use ActiveRecord’s change_column_null method in your migration.

For example to change a nullable column to null: false, you’ll want a migration like the following:

def change
  change_column_null :posts, :title, false
end

Note, if you have existing records with null values in the title column, then you’ll need to deal with those before migrating.

If you want to make an existing column nullable, change that false to true:

def change
  change_column_null :posts, :title, true
end

Create A List Of Atoms

The ~w sigil makes it easy to create a word list — a list of strings — where each word is separated by a space.

> ~w(bulbasaur charmander squirtle)
["bulbasaur", "charmander", "squirtle"]

By appending an a onto that sigil construct, you are instructing Elixir that you would instead like a list of atoms.

> ~w(bulbasaur charmander squirtle)a
[:bulbasaur, :charmander, :squirtle]

source

Pretty Printing JSONB Rows in PostgreSQL

Who needs a document store when you can just use PostgreSQL’s JSONB data type? Viewing rows of JSONB output can be challenging though because it defaults to printing them as a single line of text.

> select '{"what": "is this", "nested": {"items 1": "are the best", "items 2": [1, 2, 3]}}'::jsonb;
                                      jsonb
----------------------------------------------------------------------------------
 {"what": "is this", "nested": {"items 1": "are the best", "items 2": [1, 2, 3]}}
(1 row)

Fortunately, Postgres comes with a function for prettying up the format of the output of these rows — jsonb_pretty

> select jsonb_pretty('{"what": "is this", "nested": {"items 1": "are the best", "items 2": [1, 2, 3]}}'::jsonb);
            jsonb_pretty
------------------------------------
 {                                 +
     "what": "is this",            +
     "nested": {                   +
         "items 1": "are the best",+
         "items 2": [              +
             1,                    +
             2,                    +
             3                     +
         ]                         +
     }                             +
 }
(1 row)

h/t Jack Christensen