Today I Learned

A Hashrocket project

prevent execution when creating materialized views

When working with foreign data wrappers, one uses a materialized view to store the downloaded foreign table data. The process of downloading could be very expensive and managed by another process or program, but your program needs to define the parameters of materialzied view/foreign table. Maybe the data is loaded out of band by cron:

@daily /usr/bin/psql -d cool_db -c 'refresh materialized view big_view;'

So to create the materialized view without loading the data we use the WITH NO DATA clause:

create foreign table measurement_y2016m07
    partition of measurement for values from ('2016-07-01') to ('2016-08-01')
    server server_07;

create materialized view big_view
  as select *
  from measurement_y2016m07
  with no data;

This way we are able to execute the create foreign table and create materialized view statements in a very short amount of time. A different process can start the download with refresh materialized view

Alias a Git Branch Name 🏷

I’m working on a long-running Git branch with a long name, and I’d like to have an alias for that long branch name. The best solution I’ve found so far is to use a Git symbolic ref:

$ git symbolic-ref refs/heads/epic refs/heads/long-epic-branch-name

Once in place, this alias can be used to reference the longer branch name:

$ git checkout epic
Switched to branch 'epic'
$ git branch --show-current
long-epic-branch-name

Resources:

git-symbolic-refs
Answer: Creating aliases for Git branch names

Tmux not starting after an upgrade

Recently upgraded my version of Tmux and after could no longer start a session. After banging my head on tmux’s config files it turned out that sessions that were currently in play were the problem.

So if you find yourself in this situation… make sure to stop all sessions and most likely you’ll have Tmux working again.

An easy way to kill everything would be tmux kill-server.

There's a "whereami" alias in Pry

Since version 0.10.0, the pry gem has shipped with a built in alias for whereami: the extremely convenient @

Other useful aliases can be found using the help command:

[1] pry(main)> help

Aliases
  !!!                Alias for `exit-program`
  !!@                Alias for `exit-all`
  $                  Alias for `show-source`
  ?                  Alias for `show-doc`
  @                  Alias for `whereami`
  clipit             Alias for `gist --clip`
  file-mode          Alias for `shell-mode`
  history            Alias for `hist`
  quit               Alias for `exit`
  quit-program       Alias for `exit-program`
  reload-method      Alias for `reload-code`
  show-method        Alias for `show-source`

Finding a Data Attribute

Some codebases use data attributes for automated testing, and today I learned how to access and manipulate these attributes from a DevTools console.

document.querySelector(`[data-test-attribute="submit-button"]`).click()

This technique lets me visually verify that the attribute is in the right place and behaves as test software expects it should, without reading the HTML at all.

10x Your Playback Rate

Consuming pre-recorded conference talks, video tutorials, and podcasts at accelerated speeds is possible and addictive. Each week I send a newsletter containing at least one recent conference talk I’ve watched, and I wouldn’t be able to do this without the following hack:

Most videos players (YouTube, Vimeo, QuickTime) let you increase the playback rate, but often these controls are hard to find or have an arbitrary ceiling like 2x. If there’s a video element in the DOM, I like to bump up the rate in the DevTools console like this:

document.querySelector('video').playbackRate = 3

‘3’ equals three-times the normal speed, and that seems to be my limit for the moment.

playbackRate MDN docs

The Zen of Python 🐍

$ python
>>> import this
The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
>>>

Gonna be pondering these for some time. Thanks Phil!

All Jest Describes Run First

When writing a Jest test, the setup code inside any top-level describe function gets run before any scenario. So, if you setup a world in one describe, and a competing world in another, the last one that is run wins.

This even applies when you’ve marked a describe as ‘skip’ via xdescribe. The code inside that setup will still be run.

This is a first pass at a TIL, because I’m not sure the behavior I’m seeing is expected, and if so, why it is expected. It certainly surprised me 😳. I think one solution is to limit your tests to one top-level describe which has the important benefit of being more readable, too.

Disallow Large Jest Snapshots Using ESLint

eslint-plugin-jest has a handy rule to limit the size of snapshots - no-large-snapshots. This is especially useful for maintainability of snapshot tests. Snapshots of a large component are cumbersome to maintain as it requires the dev to have a deep knowledge of this components DOM and contained logic.

Github - eslint-plugin-jest/no-large-snapshots

Bonus Round: React Native has updated their documentation and added some great testing guidelines for mobile apps.

Google Font Popular Pairings

Google fonts are an incredible resource, and I use them a lot because of how easy they are to set up. Today I learned that Google has a ‘popular pairings’ feature at the bottom of each font page. Here’s that page for the Spectral font:

image

The Spectral/Open Sans pairing shown above gives design newbies like myself a nice serif/sans-serif combination to play with. When you click the ‘+’ icon, your paired font is added to the import statement, so you can get both with one link tag.

Design for everyone.

Fix poor type support in immutablejs

Immutablejs doesn’t work very well with typescript. But I can patch types myself for some perceived type safety:


import {Map,fromJS} from 'immutable';

interface TypedMap<T> extends Map<any, any> {
  toJS(): T;
  get<K extends keyof T>(key: K, notSetValue?: T[K]): T[K];
}

interface User {
  name: string;
  points: number;
}

const users = List() as List<TypedMap<User>>;

users.forEach(u => {
  const aString = u.name
  const aNumber = u.points
});

How to convert JSON to CSV with jq

I had this json file that was an array of objects and some of those objects had different keys. I wanted to visualize that data in a spreadsheet (data science, AI, machine learning stuff) so I thought about having a CSV file where each JSON key would become a CSV column.

// file.json
[
  {
    "type": "Event1",
    "time": 20
  },
  {
    "type": "Event2",
    "distance": 100
  }
]

jq to the rescue:


cat file.json | jq -r '(map(keys) | add | unique) as $cols | map(. as $row | $cols | map($row[.])) as $rows | $cols, $rows[] | @csv' > file.csv

Here is the output:

"distance","time","type"
,20,"Event1"
100,,"Event2"
Screen Shot 2020-08-07 at 4 39 16 PM

Typescript Bang

The “non-null assertion operator” or “!” at the end of an operand is one way to tell the compiler you’re sure the thing is not null, nor undefined. In some situations, the compiler can’t determine things humans can.

For example, say we have a treasure map with some gold in it.

type TreasureMap = Map<string, number>

const map: TreasureMap = new Map()
const treasure = 'gold'
map.set(treasure, 10)

And we’re cranking out some code that tells us if

function isItWorthIt(map: TreasureMap) { 
  return map.has(treasure) && map.get(treasure) > 9
}

Obviously we are checking if the map has gold first. If it doesn’t, the execution returns early with false. If it does, then we know we can safely access the value.

But the compiler gets really upset about this:

Object is possibly ‘undefined’. ts(2532)

In this case, the compiler doesn’t keep map.has(treasure) in context when evaluating map.get(treasure). There is more than one way to solve this, but for now we can simply “assert” our superiority over the compiler with a bang.

return map.has(treasure) && map.get(treasure)! > 9

Typscript Docs - non-null-assertion-operator

Count Occurrences in Elixir

Elixir recently introduced an useful couple of functions to count how many times a value appears in an Enumerable. It comes in two formats: frequencies/1 and frequencies_by/2. Here’s an example:

iex> [
...>   %{name: "Falcon", power: "Flight"},
...>   %{name: "Titan Spirit", power: "Flight"},
...>   %{name: "Atom Claw", power: "Strength"},
...>   %{name: "Electro", power: "Electricity Control"},
...>   %{name: "Loki Brain", power: "Telekinesis"},
...> ] |> Enum.frequencies_by(& &1.power)
%{
  "Electricity Control" => 1,
  "Flight" => 2,
  "Strength" => 1,
  "Telekinesis" => 1
}

Generic React Components

When props are generic like this:

inteface SelectProps<T> {
  options: T[];
  onChange: (value: T) => void;
}

function CoolSelect<T> (props: SelectProps<T>) {
    // ...
}

The generic part can be specified in JSX like this:

interface Fruit {
  name: string;
  isFruit: boolean
}

const fruits = [
  { name: 'Pumpkin', isFruit: true },
  { name: 'Avocado', isFruit: true },
  { name: 'Cucumber', isFruit: true },
  { name: 'Bell Pepper', isFruit: true },
]

funciton App() {
  return <CoolSelect<Fruit> options={fruits} />
}

See it? <CoolSelect<Fruit> options={fruits} />

Now when crafting the onChange function in this example, it’s type will be infered as this:

type OnChange = (value: Fruit) => void
funciton App() {
  return (
    <CoolSelect<Fruit>
      options={fruits}
      onChange={value => {
        if (value.isFruit && value.name === 'Bell Pepper') {
          console.log("You're blowing my mind dude!")
        }
      }}
    />
  )
}

*This syntax is available in Typescript v2.9+

Git + NPM: Resolving Lockfile Conflicts 🤝

Here’s a challenging real-world scenario: you’re doing a big merge or rebase on a JavaScript project, and you keep getting conflict after conflict in your package-lock.json. These conflicts are tough to resolve, because your package-lock.json is not easy to read, and is, say, 30,000 lines long. What do you do?

When you hit to conflict, on the the conflicting Git SHA, run the following command. Your lockfile will be regenerated, conflict resolved:

$ npm install --package-lock-only

💥

From the resolving lockfile conflicts docs:

image

Tmux Send Keys to Pane

I wrote a script the other day designed to help me download and edit files faster. In part of the script, I wanted to open Vim in an existing Tmux pane, and in the process I learned about the tmux send-keys command. Here’s how it works:

$ tmux send-keys -t 3 "vim" Enter

send-keys, aliased send, sends your string of commands to your pane (t) of choice. Running the above opens Vim in pane #3.

The -t flag accepts negative numbers, too, like an array index. In my version of the above command, I send the keys to pane -1, the last pane on the screen, which is where I keep Vim in my Tmux session.

Use Enzyme's `wrappingComponent` option in `mount`

Also works with shallow:

const provided = {super: 'cool', object: ['of', 'things']};

// This means that the root of the tree is going to be the provider
describe('Some Component', () => {
  it('does cool things when props change', () => {
    const target = mount(
      <CoolProvider thing={provided}
        <Component changeMe={false} />
      </CoolProvider>
  })
})

// This means that the root of the tree will be your Component
describe('Some Component', () => {
  it('does cool things when props change', () => {
    const target = mount(<Component changeMe={false} />, {
      wrappingComponent: CoolProvider,
      wrappingComponentProps: {super: 'cool', object: ['of', 'things']}
  })
})

This pattern is particularly meaningful when you want to call setProps or other methods that are only valid on the root of the component tree, because dive can’t help you there. If you want to change the props on both, you can use target.getWrappingComponent() to get at the wrapping component in the same way!

https://enzymejs.github.io/enzyme/docs/api/ReactWrapper/getWrappingComponent.html

Enzyme debug() 🐞

Debugging React unit tests can be tricky. Today I learned about the Enzyme debug() function. Here’s the signature:

.debug([options]) => String

This function:

Returns an HTML-like string of the wrapper for debugging purposes. Useful to print out to the console when tests are not passing when you expect them to.

Using this in a log statement will dump a ton of valuable data into your test runner’s output:

console.log(component.debug());

debug() docs

Postgres Identity Column

The Postgres wiki recommends not using the serial type, and instead added identity columns to replace them.

Old way:

create table todos (
  id bigserial primary key,
  todo text not null
);

The new way with identity columns:

create table todos (
  id bigint generated by default as identity primary key,
  todo text not null
);

Data:

insert into todos (todo) values
  ('write a til'),
  ('get some coffee');

select *
from todos;
 id |      todo
----+-----------------
  1 | write a til
  2 | get some coffee
(2 rows)

Source: PG wiki: Don’t use serial

Turning off a specific linter w/ALE

Ale comes configured with a set of default linters for each filetype it might encounter.

For typescript, if eslint is available as an executable, eslint will run, lint your code and display the results in vim. To turn off eslint for typescript you can set the variable g:ale_linters_ignore in your vimrc like this:

let g:ale_linters_ignore = {
      \   'typescript': ['eslint'],
      \}

Currently, I’m going through the typescript exercism track and I want to be able to play around a little bit with the syntax and would prefer not having a typescript linter at the moment.

Give git config more context with `--show-scope`

git config is only as helpful as the options you pass.

In the simplest instance I only get a value:

> git config user.email
dev@example.com

If I pass the --get-regexp flag I get the key and the value for all the instances of that key:

> git config --get-regexp user.email
user.email computer@example.com
user.email dev@example.com

If I pass the --show-scope flag (added in 2.26) I get the scope:

> git config --show-scope --get-regexp user.email
global user.email computer@example.com
local  user.email dev@example.com

If I pass the --show-origin then I also get the file where the key was configured:

> git config --show-scope --show-origin --get-regexp user.email
global file:/home/dev/.gitconfig user.email computer@example.com
local  file:.git/config user.email dev@example.com

The git blog is an incredible way to learn about the new functionality in each git release.

`isNaN` vs `Number.isNaN` (hint: use the latter)

Chalk this up to JavaScript is just weird. The isNaN function returns some surprising values:

> isNaN(NaN)
true

> isNaN({})
true

> isNaN('word')
true

> isNaN(true)
false

> isNaN([])
false

> isNaN(1)
false

What’s going on here? Per MDN, the value is first coerced to a number (like with Number(value)) and then if the result is NaN it returns true.

Number.isNaN is a little bit more literal:

> Number.isNaN(NaN)
true

> Number.isNaN({})
false

> Number.isNaN('word')
false

> Number.isNaN(true)
false

> Number.isNaN([])
false

> Number.isNaN(1)
false

So, if you really want to know if a value is NaN use Number.isNaN

I learned about this via Lydia Hallie’s Javascript Questions

Throttle iOS simulators' network speed

Get MacOS’s Network Link Conditioner.prefPane.

  1. Sign in at apple: https://developer.apple.com/download/more/?=Additional%20Tools%20for%20Xcode
  2. Download “Additional Tools for Xcode [version]” for your Xcode version.
  3. Run the DMG
  4. Open Hardware and double-click Network Link Conditioner.prefPane to install.

Use it:

  1. Open Settings then Network Link Conditioner
  2. Adjust the Profile and toggle the switch ON

Remember to turn it off :)

Destructure into an existing array

This one’s got my head spinning. Let’s say you have an existing array:

const fruits = ['banana', 'apple', 'kumquat']

You can destructure right into this array.

{name: fruits[fruits.length]} = {name: 'cherry'}

//fruits is now ['banana', 'apple', 'kumquat', 'cherry']

Generally, I would think of the {name: <some var id>} = ... syntax as renaming the value that you are destructuring, but now I think of it more as defining a location that the value will be destrcutured to.

If you try to declare a new variable in the same destructuring however you will get an error if you use const:

const {name: fruits[fruits.length], color} = {name: 'cherry', color: 'red'}
// Uncaught SyntaxError: Identifier 'fruits' has already been declared

Or the new variable will go onto the global or window object if you don’t use const:

{name: fruits[fruits.length], color} = {name: 'cherry', color: 'red'}
global.color
// 'red'

Check for members in Ruby

Ruby’s Enumerable class has a member? method that returns a boolean.

For arrays, the method checks if the supplied value is included (similar to ['a'].include?('a')):

[:a, :b].member?(:b) # => true
[:a, :b].member?(:c) # => false

For hashes, the method checks if the supplied value is included in the keys for the hash:

{ a: 'b' }.member?(:a) # => true
{ a: 'b' }.member?(:c) # => false

Supercharge Your Script with psql -c 🥞

Want to execute a PostgreSQL command from the command line? You can! The --command or -c flag takes a string argument that will be executed on your database of choice.

I’ve been using it as part of a script that creates a remote database backup, downloads the backup, drops and creates a local database, dumps the database backup into the local database, and then runs a select statement on the dataset. That final command looks like this (query has been simplified):

$ psql -d tilex_prod_backup -c "select count(*) from posts";

 count
-------
  2311
(1 row)

Repeat subs with `g&` and `:&` and `:&&`

The tricks from Vim Un-Alphabet keep coming. Repeating your substitution is a cool trick and you can do it one of 3 ways.

g& will repeat the last substitution you did, but for the whole file, whatever file you’re in at the moment.

:& will repeat the last substitution on the line you are on but you get to change the flags if you want. So you can decide now to make it global with :&g.

:&& will repeat the last substitution on the line you are on with the flags you used for that substitution.

3 very nice tricks to smooth out your workflow when making substitutions.

Inline MD codeblock with double backticks

A pair of single backticks signify an inline code block in Markdown. But if you need to put a backtick in that code block the backtick ends the codeblock!

Another way to signify an inline codeblock is with double backticks, two backticks in sequence on either side of the codeblock.

When using double backticks for a codeblock, a single backtick within the codeblock will be interpreted as just that, not the end of the codeblock.

Jump to the last place you were in INSERT mode

I’ve known for a while that you can jump to the last place you edited with the gi command but it’s always been slightly annoying to me that gi places you into INSERT mode.

To get back to the same place, but in NORMAL mode you can use the ^ mark by typing `^. This mark is reset everytime you leave edit mode. You can see what that mark is set to with :marks ^ Shoutout to Josh Branchaud and his Vim Un-Alphabet series for teaching me a new vim trick!

zsh comes with help (set the $HELPDIR)

zsh helpfully comes installed with help files for all the builtins and a run-help command to help you access those help files. There is a trick though, before setting any environment variables here’s what happens:

$ run-help
There is no list of special help topics available at this time.

This is because the HELPDIR isn’t set. You have to find the install location for zsh’s help files and set the env var to that dir. On my system that looks like this:

export HELPDIR='/usr/share/zsh/help'

Then when you run run-help you should see a list of builtins for which there is help documentation. This is the same documentation that you can get via man builtins but much more readable and discoverable. run-help will call man as well if it can’t find you’re arg in the help files.

For me run-help is cumbersome to type so I alias it. Here’s what goes into my .zshrc:

export HELPDIR='/usr/share/zsh/help'
alias help=run-help

zsh is now much more helpful!

zsh comes with Tetris

zsh comes with it’s very own tetris game. No plugins needed!

You do need to autoload the tetriscurses function:

autoload -Uz tetriscurses

And then run tetriscurses.

While in the game, you can press H to learn which keys do what, and that looks like this:

left: h, j, left
right: right, n, l
rotate: up, c, i
soft drop: down, t, k
hard drop: space
quit: q
press space to return

also, maybe you want an alias for this?

autoload -Uz tetriscurses
alias tetris=tetriscurses

I’m putting the above straight into my .zshrc! Happy Sunday!

Follow the link in linux with `readlink -e`

Sometimes linux can be a maze of symbolic links. On my system, the java command exists at /usr/bin/java which is a link that points to /etc/alternatives/java which is a link that points to /usr/lib/jvm/java-8-oracle/jre/bin/java.

Instead of looking up each of the links of these files with ls -l, readlink -e will the links all the way through to the eventual file. In my case that would look like this:

$ readlink -e `which java`
# returns /usr/lib/jvm/java-8-oracle/jre/bin/java

You can learn more with man readlink.

On Mac, there is a readlink command, but there is no -e flag and it is not recursive.

Elixir Date and Time conversion into US standards

Today I learned how to manually convert a Date and Time into US standards: mm/dd/YYYY and hh:mm am|pm. Here’s my code snippet:

defmodule Utils.Converter do
  def to_usa_date(%Date{day: day, month: month, year: year}) do
    "~2..0B/~2..0B/~4..0B"
    |> :io_lib.format([month, day, year])
    |> to_string()
  end

  def to_usa_time(%Time{} = time) do
    period = (time.hour < 12 && "am") || "pm"
    hour = time.hour |> rem(12)

    "~2..0B:~2..0B ~2..0s"
    |> :io_lib.format([hour, time.minute, period])
    |> to_string()
  end
end

This way I can convert dates like ~D[2020-05-29] into 05/29/2020" and times like ~T[11:00:07.001] into 11:00 am" and ~T[23:00:07.001] into 11:00 pm".

Here’s the erlang :io_lib documentation

Choosing your `--cloud` provider on Gigalixir

One cool thing about gigalixir is that you can choose both cloud platform and the datacenter/region where you’d like to install your app.

By default gigalixir create <app name> will put an app in Google Cloud Platform.

But what if you already have infrastructure that you want to take advantage of on AWS in the us-east-1 region (this is where heroku is by default putting it’s servers)?

Well you can change providers with the --cloud flag and the region with --region flag.

gigalixir create -n gigatilex --cloud aws --region us-east-1

AWS it is!