Today I Learned

A Hashrocket project

Show escaped bash color codes in less #linux

My ls command colors directories and files according to their type and permissions:

ls with color

But when the window is too small to fit the content I pipe the result into less:

less broken

Which cannot correctly parse the escape code from ls and turn them into color. To fix that add -r to the less command:

solution

Notes:

My l alias is gls -F -G --color --group-directories-first -lah (gls is GNU ls)

You can alias less=less -r if you want this to be the default behavior for less.

Vim: Peek horizontally without moving the cursor

Some people like wordwrapping in Vim. Personally I find it annoying for code because it can destroy the meaning of the code in the context that it was formatted in by the original author, making it hard to understand where one line begins and ends.

Turning wordwrap off though, can put you in a situation where you have a line of text slightly longer than the screen can show, and you may want to scroll a bit to the right/left for reference but not move your cursor and lose your position with ^ or $.

Vim allows you to do that with zs and ze mappings.

DEMO demo

Learn more with :h zs or :h ze.

Disable Swipe Navigation For A Specific App On Mac

Mac’s touch pad has a bunch of handy swipe gestures, including swiping two fingers to the left or the right to navigate backward or forward. This particular gesture can be globally enabled and disabled. I find it useful for most apps and a pain in a few apps, such as Google Chrome.

From the terminal we can disable it for a specific app (like Google Chrome):

$ defaults write com.google.Chrome AppleEnableSwipeNavigateWithScrolls -bool FALSE

Restart the target application, in my case Chrome. The left and right swipe navigation will no longer be triggered.

source

Show materialized view definition in #postgresql

PSQL offers a handy \dv function for showing the definition of a view. That function does not seem to work on materialized views.

To see the definition of a materialized view use the following instead:

select pg_get_viewdef('search_documents');

Another option is to use \d+ search_documents which shows both the query and the columns.

(Replace search_documents with the name of your view.)

Hide all other windows on #macOS

Sometimes your desktop gets cluttered with windows of different running applications which makes it difficult to concetrate on the task at hand.

This can also come in handing when sharing your screen or presenting.

Fortunately macOS offers some shortcuts to remediate this common problem:

⌘+h - hide current window

⌘+⌥+h - hide all other windows

⌃+⌘+f - toggle full screen mode

Create A Cancelable Promise With PCancelable

If an async task takes a really long time and we find out in the middle of its execution that we no longer want the results of that activity, it would be nice to be able to cancel that promise. There was a proposal for cancelable promises, but it has since been withdrawn. There is an alternative though.

The p-cancelable package provides a promise wrapper that acts as a cancelable promise.

import PCancelable from 'p-cancelable';

const fetchPromise = new PCancelable((resolve, reject, onCancel) => {
  setTimeout(() => {
    resolve({ ok: true, data: [1, 2, 3] });
  }, 10000);

  onCancel(() => {
    console.log('Promise is being canceled');
  });
});

fetchPromise.then(response => {
  console.log('Promise Resolved: ', response.data);
}).catch(err => {
  console.log('Promise Rejected: ', err);
});

fetchPromise.cancel();

We can create a promise in a familiar manner. We get an additional argument — the onCancel function. This is a function that will be executed if cancel is called before the promises has resolved or rejected. In the above example, the fetchPromise.cancel() line will be invoked before the setTimeout resolves. The promise will be canceled, causing a rejection which will push us into the catch handler.

Execute command from register

Here’s a cool command

:nmap <leader>s :smile<CR>

If you read the above in vim, how would you execute it? You can use the system buffer or tmux copy+paste and paste it to the command line, but that seems very not-vim.

Vim has a :@ command that will execute registry contents. Just put the line into your registry with yy and then call:

:@"

This executes the contents of the default register

`yo` has been replaced by `]op`

vim-unimpaired is a fantastic vim plugin full of utility mappings, many to do with toggling. I have relied heavily on yo to enter insert mode with the paste option set when I want to use the system buffer for pasting.

Recently, the yo mapping has been repurposed. Read the github issue here.

Instead, ]op is the new mapping to put you in insert mode with the paste option set.

The documentation now looks like this:

                                                *[op* *]op* *yop*
A toggle has not been provided for 'paste' because the typical use case of
wrapping of a solitary insertion is inefficient:  You toggle twice, but
you only paste once (YOPO).  Instead, press [op, ]op, or yop to invoke |o|,
|O|, or |0||C| with 'paste' already set.  Leaving insert mode sets 'nopaste'
automatically.

Interval Comparison in JavaScript

Today I learned a bit about interval comparison. It’s something you might recall from grade-school math:

1 < 5 < 10 -- is this true?

Two languages I’ve found that support it are Python and Clojure:

> if (1 < 5 < 10):
...   True
...
True
> (< 1 5 10)
=> true

JavaScript doesn’t support interval comparison, so we have to find another way to check that condition. Here’s one technique:

if (1 < number && number < 10) {
  // do something
}

It’s a wordier that the previous examples, but I think keeping the variable in the middle of the condition stays true to the interval comparison idea.

Forcing A Child Remount With The Key Prop

There are a couple prop names that have reserved usage in React. One of those is key. We generally use key when we are rendering a list of things. It is a way of uniquely identifying each element in a list so that React minimizes re-rendering when parts of the list change.

We can flip this on its head and utilize key as a way of forcing a remount and re-render of a child component.

Imagine I have a component that does a number of things including rendering a component with some internal state, such as a counter.

class MyComponent extends React.Component {
  state = {
    remountKey: (new Date()).getTime(),
  }

  resetCounter = () => {
    this.setState({
      remountKey: (new Date()).getTime(),
    });
  }

  render() {
    return (
      <div>
        {/* some other stuff in my component */}

        <Counter key={this.state.remountKey} />
        <button onClick={this.resetCounter}>Reset Counter</button>
      </div>
    );
  }
}

I can force this Counter component to remount, thus resetting its state by passing it a new key value. The button can trigger this by updating the remountKey value.

Create An Object With No Properties

When you call new Object or even just instantiate an object with {}, you are creating an object that uses the Object prototype. This means it inherits from Object.prototype.

You can deliberately create an object with no properties by making sure that it does not inherit Object.prototype.

> const propertylessObject = Object.create(null);
{}

> propertylessObject.__proto__
undefined

Unlike most objects that we encounter as we write JavaScript, this object we created with Object.create(null) has no properties including no __proto__.

See Object.create and Object.prototype for more details.

Allow HTTPS Through Your UFW Firewall

UFW — Uncomplicated Firewall — is just what is sounds like. I have it running on a DigitalOcean box and it is only letting through traffic on ports 80 (HTTP) and 22 (SSH). I am setting up SSL for a domain hosted on this box which means I need to also let through traffic on 443 (HTTPS).

The allowed ports can be checked with the status command:

$ sudo ufw status

Status: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
Nginx HTTP                 ALLOW       Anywhere
OpenSSH (v6)               ALLOW       Anywhere (v6)
Nginx HTTP (v6)            ALLOW       Anywhere (v6)

As we can see, HTTPS has not yet been allowed by ufw. We can allow HTTPS traffic with the allow command.

$ sudo ufw allow https

Check the status again and see that HTTPS is now included in the list.

source

h/t Dillon Hafer

Turn Off Console Error Messages In A Test

I’m using Jest to test a React component that requires a prop via PropTypes. In one of my tests, I want to test that component when the required prop is excluded. The side effect of doing this is that my test output gets cluttered with the PropType warning.

The thing to do is silence the error message during that test.

it('renders a component without a required prop', () => {
  const originalError = console.error;
  console.error = jest.fn();

  // test code here
  expect(shallow(<My Component />)).toDoSomething;

  console.error = originalError;
});

We can silence console.error by temporarily replacing it with a Jest-mocked function and then putting it back at the end of the test.

Display line break content in React with just CSS

Let’s say you have an array of strings and you want to display its content inside a paragraph:

const locations = ['Location 1', 'Location 2']
<p>{locations.join('\n')}</p>

That will display all the items inline even if the line break is present :

Location 1 Location 2

Instead of adding unnecessary <br /> tags to the markup you can simply specify a css property to render line breaks:

<p style="white-space: pre-line">{locations.join('\n')}</p>

This will look like:

Location 1
Location 2

Extract a Shared Yup Validation

In a growing React app with Yup validations, schemas can become repetitive. But since the validation schema is a JavaScript object, we can extract single validations, or a group of validations.

Here’s my schema definition for an address form:

validationSchema: yup.object().shape(addressValidation)

And the address validation:

const addressValidation = {
  address: yup.string().required(),
  address2: yup.string(),
  city: yup.string().required(),
  state: yup.string().required(),
  zip: yup.string().required(),
};

Reuse this helper anytime you need to collect an address.

Using `yarn global` w/ Node through asdf (mac)

The asdf version manager is an awesome tool for managing many different language runtime versions. I recently started using it for Node and noticed that yarn global no longer plays nice with it.

Turns out that if you install yarn through homebrew - your global directory will not take into account the asdf node version and path.

To correct this, first uninstall yarn from homebrew:

brew uninstall yarn

Then in your .zshrc or equivalent remove the yarn global path (see my previous post about Yarn global)

Now you want to find where asdf is being sourced into your .zshrc and insert a dynamic yarn global path:

~/.zshrc

# asdf global version manager
source "$HOME/.asdf/asdf.sh"
source "$HOME/.asdf/completions/asdf.bash"

# set yarn binaries on path
# must be below the .asdf source commands ^
export PATH="$(yarn global bin):$PATH"

You can now install yarn again from npm which will put it in your asdf versioned node:

npm i -g yarn

When done restart your terminal and test to see that everything worked. I had to delete the ~/.config/yarn/global to make this work.

echo $PATH should contain something that looks like /Users/dkarter/.asdf/installs/nodejs/9.11.1/.npm/bin which should match yarn global bin.

Spelunking Through Components With Enzyme's Dive

Most of the components we write have other components nested in them.

const Hello = ({ name }) => <h1>Hello {name}!</h1>;

const HelloContainer = (props) => (
  <div>
    <Hello {...props} />
  </div>
);

If we are to shallow render the above component using Enzyme, we’ll only see things one layer deep:

const wrapper = shallow(<HelloContainer name="World" />);
// wrapper ~= <div><Hello name="World" /></div>

If we’d like to explore a particular child of the rendered component further, we can do a little find and dive.

const wrapper = shallow(<HelloContainer name="World" />);
const helloWrapper = wrapper.find(Hello).dive();
expect(helloWrapper.text()).toEqual("Hello World!");

This allows us to make pinpoint assertions about how our components render without mounting the entire thing.

See a live example here.

h/t Vidal Ekechukwu

Use React 16 With Gatsby

Gatsby, the blazing fast static site generator for React, is tied to React 15.6. If you’ve been using React 16+ for a while, then this may come as a bit of a buzzkill.

Fortunately, there is a Gatsby plugin that lets you use React 16 with a Gatsby v1 site — gatsby-plugin-react-next.

Add it the plugin as a dependency:

$ yarn add gatsby-plugin-react-next

Then add it to the list of plugins in gatsby-config.js:

plugins: [`gatsby-plugin-react-next`];

source

Add Fab Icons To Your Site With FontAwesome 5

Check out the latest version of FontAwesome.

Version 5 has been re-written and re-designed completely from scratch.

One part of the rewrite is that brand icons have been organized into their own collection. Whether you are using the full suite or just the brands bundle, you’ll be referencing these icons with the fab class name.

<i class="fab fa-react" />

This will give you a React icon.

Check out all the different brand icons here.

Avoid The Notch With SafeAreaView On React-Native

iOS devices, especially the iPhone X, have areas of the screen that are cut off in ways that present quite a challenge to developers. One of the easiest ways to deal with rounded corners and the notch when developing for iOS is to avoid them all together.

The purpose of SafeAreaView is to render content within the safe area boundaries of a device.

import { SafeAreaView, View, Text } from 'react-native';

const App = () => {
  return (
    <SafeAreaView style={{ flex: 1, backgroundColor: "#e6e6e6" }}>
      <View>
        <Text>Safely rendered in the visible area of the device!</Text>
      </View>
    </SafeAreaView>
  );
}

The unsafe area can be styled however you like and everything inside <SafeAreaView> will be pushed into the visible area of the screen.

h/t Dillon Hafer

source

Custom errors in JavaScript ⚠️

Javascript provides the ability to create custom errors by modifying the prototype of a function to the Error protorype. This is how one would create a custom error:

function ValidationError(message) { 
  this.name = 'ValidationError'; 
  this.message = message; 
}
ValidationError.prototype = Error.prototype;

// USAGE
throw new ValidationError('the form is invalid');

To catch it you can check the class of an error using instanceof:

try {
    // do stuff
  throw new ValidationError('the form is invalid');
} catch (ex) {
    if (ex instanceof ValidationError) {
    alert(ex.message); // the form is invalid
  } else {
    // crash and burn
    throw ex;
  }
}

Elixir String Manipulation

To get the list of string that compose a longer string, use String.codepoints/1

iex> cdp =  String.codepoints("abcdefg")
["a", "b", "c", "d", "e", "f", "g"]
iex> Enum.at(cdp, 0)
"a"

To get the list of codepoints that represent each letter in the string, use String.to_charlist/1

iex> chr = String.to_charlist("abcdefg")
'abcdefg'
iex> Enum.at(chr, 0)
97

📅 Get begining and end of week with Moment.js

To get the date for benining of week for a date in moment you can use the startOf and endOf functions on moment objects.

const today = moment();
const from_date = today.startOf('week');
const to_date = today.endOf('week');
console.log({
  from_date: from_date.toString(),
  today: moment().toString(),
  to_date: to_date.toString(),
});

// {
//   from_date: "Sun Apr 22 2018 00:00:00 GMT-0500",
//   today: "Thu Apr 26 2018 15:18:43 GMT-0500",
//   to_date: "Sat Apr 28 2018 23:59:59 GMT-0500"
// }

NOTE: Remember that the start of week will depend on the user’s locale settings on their machine. If you want to use start of week based on ISO 8601 you can use moment().startOf('isoWeek');

The same technique can be used for start of month (startOf('month')), start of year (startOf('year')) and even quarter (startOf('quarter');).

Dynamically Create HTML Elements

An HTML element can be created with a string that matches a recognized entity.

const Paragraph = 'p';
return <Paragraph>Some paragraph content</Paragraph>

This means we can dynamically create HTML elements such as headers:

const H = ({ level, ...props }) => {
  const Heading = `h${Math.min(level, 6)}`;
  return <Heading {...props} />;
};

return (
  <React.Fragment>
    <H level={1}>Header 1</H>
    <H level={2}>Header 2</H>
    <H level={5}>Header 5</H>
  </React.Fragment>
);

With some inspiration, I’ve created a live example here.

Fix Timeouts and Speed Up Jest on CI

If you have a large or complex test suite, running Jest on CI can make your build especially slow or cause timeouts. Luckily, Jest has an option cut out for this.

jest --runInBand

runInBand runs all tests serially inside the current process instead of creating a bunch workers. Using this option, we were able to trim suite time above 20mins down to less than 4 mins. 🏎️😎

create-react-app Has A Default Test Setup File

In Configure Jest To Run A Test Setup File, I pointed to a way of configuring Jest in either the package.json or jest.config.js file with the setupTestFrameworkScriptFile value.

In a create-react-app project, this is not an option because setupTestFrameworkScriptFile is not one of the permitted config values for Jest.

There is a built-in value which happens to match what was recommended in the above post — <rootDir>src/setupTests.js.

This means that there is no configuration required. Instead, just create a setupTests.js file in the src directory of your CRA project and add any framework setup you need there. That file is already configured to run when you invoke yarn test.

source

Vim Verbose Map

Do you have a Vim mapping you’d like to know more about? One technique to explore a mapping is map. Here’s what my machine knows about gcc:

:map gcc
n  gcc           <Plug>CommentaryLine
o  gc            <Plug>Commentary
n  gc            <Plug>Commentary
x  gc            <Plug>Commentary

Need more information? Add verbose, which will also display where it was last set.

:verbose map gcc
n  gcc           <Plug>CommentaryLine
        Last set from ~/hashrocket/dotmatrix/.vim/bundle/vim-commentary/plugin/commentary.vim
o  gc            <Plug>Commentary
        Last set from ~/hashrocket/dotmatrix/.vim/bundle/vim-commentary/plugin/commentary.vim
n  gc            <Plug>Commentary
        Last set from ~/hashrocket/dotmatrix/.vim/bundle/vim-commentary/plugin/commentary.vim
x  gc            <Plug>Commentary
        Last set from ~/hashrocket/dotmatrix/.vim/bundle/vim-commentary/plugin/commentary.vim

Now we know which modes support gcc (normal, plus operator-pending, normal, and ex-mode as gc), what happens when the command is used, and who set it last.

h/t Chris Erin

Configure Jest To Run A Test Setup File

Jest can be configured to run a setup file before each test. This is useful for configuring your testing framework in a single place, rather than in each test file.

This setup file can be specified in package.json (or jest.config.js).

// package.json
{
  // ...
  "jest": {
    "setupTestFrameworkScriptFile": "<rootDir>src/setupTests.js"
  }
}

The setupTestFrameworkScriptFile points to a test setup file at the specified location rooted at <rootDir> (the root of your project).

This kind of setup is helpful for something like Enzyme that needs to be configured with a specific adapter for use throughout your tests.

Case insensitive `in` query in #postgres #psql

If you have a list of strings and you want to query a column to get all the matching records, but you do not care about the casing, Postgres offers a cool and easy way of doing that with the citext extension.

Given this table:

id | company_name
 1 | Abibas
 2 | Nykey
 3 | Pumar

We want to match the following:

select company_name
from vendors 
where company_name in ('Abibas', 'NyKey', 'PUMAr');

First you will have to make sure you have the citext extension created if you haven’t already:

create extension citext;

Then you can cast the searched field to citext:

select company_name
from vendors 
where company_name::citext in ('Abibas', 'NyKey', 'PUMAr');

h/t joshbranchaud for helping me find this

ActiveRecord where.not

When I need a IS NULL SQL expression with ActiveRecord it is easy to avoid a SQL string fragment.

User.where(deactivated_at: nil)

But in early versions of Rails using IS NOT NULL required a string.

User.where("deactivated_at is not null")

But modern Rails has where.not expressions which can eliminate the string.

User.where.not(deactivated_at: nil)

Check If Something Is An Array

The Array class has a function on it called isArray() which can be used to check if something is an array.

> Array.isArray('Hello, World!');
// => false

> Array.isArray(['One', 2, [3]]);
// => true

> Array.isArray({ foo: 'bar' });
// => false

> Array.isArray([]);
// => true

The MDN docs provide an example polyfill if it is not natively available.

if (!Array.isArray) {
  Array.isArray = function(arg) {
    return Object.prototype.toString.call(arg) === '[object Array]';
  };
}

Access System Information On OS X

On machines running OS X, there is an Apple icon in the upper left corner as part of the menu bar. Clicking on this icon reveals a number of options. The first reads About This Mac.

If you hold down the option key, however, that first option will instead read System information…

Select that option to access the System Information panel which can tell you details about your hardware, software, and network.

h/t Dillon Hafer

Delete all node_modules dirs recursively with find

If you have hundreds of past JavaScript projects sitting in your workspace folder, you probably also have hundreds of node_modules folders nested inside of them, and hundreds of thousands actual npm modules resting peacefully in those.

Often enough all you care about is the code that uses the modules and not the modules themselves, so to save yourself some precious laptop diskspace you can just delete all those folders! When you need them again cd into the project directory and run yarn install or npm install.

First let’s do a dry run:

find . -name "node_modules" -type d -prune

and now that you checked the output of the above command you can delete all the nested node_module folders.

If you are still feeling paranoid (and you’re on macOS) you can simply move those to the Trash:

find . -name "node_modules" -type d -prune -exec trash '{}' +

If you feel a little braver just unlatch the airlock and toss them into a black hole 🕳 using rm -rf

find . -name "node_modules" -type d -prune -exec rm -rf '{}' +

I saved a whopping 80GB with this technique 🤑. Hope you find it helpful.

Resolve And Pass Multiple Values From A Then

Let’s say you are chaining multiple async function calls together.

fetchTrainer(trainerName)
  .then(response => {
    const trainerData = response.body;

    return fetchPokemonFor({ trainerId: trainerData.id });
  })
  .then(response => {
    // I want trainerData, but it is now out of scope...
  });

But in the last then() you want access to both the trainerData and the pokemonData. So, how do you pass both the trainerData and the resolved response of fetchPokemonFor() through to that last then().

fetchTrainer(trainerName)
  .then(response => {
    const trainerData = response.body;

    return Promise.all([
      trainerData,
      fetchPokemonFor({ trainerId: trainerData.id })
    ]);
  })
  .then(([trainerData, pokemonResponse]) => {
    const pokemonData = pokemonResponse.body;

    // do something with trainerData and pokemonData
  });

Promise.all allows us to resolve and pass multiple promises. If any of the values in the array argument is not a promise, it simply passes it through.

h/t Brian Dunn

Generate Zeropadded Ranges

Need to generate 100 directories, named 01/ to 99/? Today I learned that command line brace expansion supports zeropadded (starting with one or more zeroes) ranges. The following command will create 100 zeropadded, numbered directories:

$ mkdir {01..99}

Hit tab to see the expanded command.

The second zeropad, if there is one, can be omitted— the following creates a range of 01-05, even thought there’s no zero in front of the 5:

$ mkdir {01..5}


Which expands to:

$ mkdir 01 02 03 04 05

Shell Out With Elixir

Today I wrote a staging and production deploy script for Tilex, learning about System.cmd/3 along the way. The first argument to this function is the command, the second are arguments, and the third are options.

Here’s an example implementation from our script that deletes a Git tag and pushes that updated reference to origin:

System.cmd("git", ["tag", "-d", "staging"])
System.cmd("git", ["push", "origin", ":refs/tags/staging"])

Mocking Requests With Partial URIs Using Regex

Generally when mocking out requests with the webmock gem, we specify full request URIs like so:

stub_request(:post, 'http://localhost:4000/api/posts')

We may not want to specify the entire URI though. For instance, the host may change or be configurable. The stub_request method allows us to use regex.

stub_request(:post, %r|/api/posts|)

Using the %r regex literal syntax, we are able to avoid escaping all of the / characters in our URI.

h/t Brian Dunn

Use a proxy on curl/wget commands

Using a proxy can be a good way to debug http issues. Unfourtunately setting the proxy on macOS globally does not apply to all command line utilities.

On Curl for example you can set the proxy using the --proxy flag:

curl http://example.com --proxy 127.0.0.1:8080

Or by adding the following to your ~/.curlrc configuration file for a more persistent setting:

proxy = 127.0.0.1:8080

A similar thing can be done with the wget utility by editing the ~/.wgetrc and adding:

http_proxy = http://127.0.0.1:8080

Sync Your react-router State With Redux

If you are building a React app that uses both redux and react-router, you’ll find that you are managing app state in two places. Most of your app state is in redux. The router-specific state is component-state in the Router.

You can unify it all in redux with react-router-redux.

You’ll need to apply some middleware, combine routerReducer with the rest of your reducers, and then swap out your BrowserRouter with a ConnectedRouter. You can read about the details here.

Get application's current version in production

If you use Distillery to produce Elixir releases for production you may be in a situation where your application is deployed and running but you are not sure what version is loaded into memory.

To verify the version:

  1. SSH into your server
  2. navigate into the bin directory of your release (e.g. app_release/your_project/bin)
  3. run the remote console ./your_project remote_console
  4. Run the spec function on Application: Application.spec(:your_project, :vsn)

You will get back a string such as ‘0.0.1’.

Create Dynamically Named Custom React Components

A React element is as simple as a function that returns some valid JSX. Any function will do.

const CustomComponent = ({ children }) => {
  return (
    <React.Fragment>{children}</React.Fragment>
  );
};

This function provides us with a React component that has a fixed name — CustomComponent. With the help of the displayName property, we can create dynamically named components.

const ComponentGenerator = ({ customName, children }) => {
  const CustomComponent = ({ children }) => {
    return (
      <React.Fragment>{children}</React.Fragment>
    );
  };
  CustomComponent.displayName = customName;

  return (
    <CustomComponent>{children}</CustomComponent>
  );
};

const App = () => {
  return (
    <ComponentGenerator customName="RandomComponentName">
      Hello!
    </ComponentGenerator>
  );
}

If we inspect the generated React tree, we will not see anything called <CustomComponent>, but instead we will see our <RandomComponentName> component.

Remember, React components need to have an uppercase name.