Today I Learned

Slow Terminal Startup Tip: Lazy Load NVM

For a long time, my ZSH shell windows/tabs have had very slow startup times, sometimes taking 5-10 seconds before .zshrc fully loads and the input cursor appears. This slows down my daily development cycles.

It turns out that loading NVM was the main culprit. Using this Medium post and this gist as motivation, I have added this snippet to my .zshrc file in order to lazy load nvm, npm, node, and npx (copied from the gist, credit goes to that author). I have immediately observed major speed improvements in my shell speed load times.

lazynvm() {
  unset -f nvm node npm npx
  export NVM_DIR=~/.nvm
  [ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" # This loads nvm
  if [ -f "$NVM_DIR/bash_completion" ]; then
    [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion
  fi
}

nvm() {
  lazynvm 
  nvm $@
}

node() {
  lazynvm
  node $@
}

npm() {
  lazynvm
  npm $@
}

npx() {
  lazynvm
  npx $@
}

Ignore some paths from git diff

Problem

I want to do a git diff, but I need some paths to be ignored.

e.g. git diff --name-only

Output:

some_dir/aaa
some_dir/bbb
some_dir/ignore_me/aaa
some_dir/ccc
some_dir/ddd

What I want:

some_dir/aaa
some_dir/bbb
some_dir/ccc
some_dir/ddd

Solution

Git pathspecs!

After a path matches any non-exclude pathspec, it will be run through all exclude pathspecs (magic signature: ! or its synonym ^). If it matches, the path is ignored.

git diff --name-only -- '!**/ignore_me/*'

Disable special characters in OS X (no 3rd party)

RubyMine comes with handful of mnemonics which are supposed to boost your productivity. However ones that are combined with alt keys can sometimes cause unexpected behaviours since some of them are bound to special characters (e.g. ™, Ó, µ ...).

You can disable special characters by choosing Unicode Hex Input as an input source (System Preferences > Keyboard > Input Sources > Others).

Now typing Alt + key won't interfere with any keyboard shortcuts. Happy RubyMining!

Lazy-load NVM to speed up zsh initialization

UPDATE Once appending --no-use, ensure to source $NVM_DIR/.nvm.sh when actually needed. For example, yarn install will complain node: No such file or directory

I was curious as to why the zsh initialization was so slow. After some benchmarking .zshrc, I learned that oh-my-zsh and NVM were the main source of slow-down. For oh-my-zsh, I'm trying to see if I can avoid loading plugins that I rarely use to cut some time. However for nvm, simply passing `--no-use the following will make a big difference.

[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" --no-use

Benchmarking with bash's buil-in time command...

Before --no-use:

❯ for i in $(seq 1 5); do /usr/bin/time zsh -i -c exit; done
        1.43 real         0.65 user         0.62 sys
        2.42 real         0.66 user         0.61 sys
        1.42 real         0.65 user         0.61 sys
        1.42 real         0.65 user         0.61 sys
        2.43 real         0.66 user         0.62 sys

After --no-use:

❯ for i in $(seq 1 5); do /usr/bin/time zsh -i -c exit; done
        0.48 real         0.26 user         0.17 sys
        0.46 real         0.25 user         0.16 sys
        0.46 real         0.25 user         0.16 sys
        0.46 real         0.26 user         0.16 sys
        0.49 real         0.27 user         0.17 sys

Sources:

https://github.com/creationix/nvm/issues/539 https://github.com/michaelmoussa/dotfiles/commit/8d67223aad5885ffc17e540b00e00478dd3c44d2 https://blog.jonlu.ca/posts/speeding-up-zsh

Rebase your branch from one branch to another

Use: git rebase --onto new-base-branch current-base-branch

For example, let's say we have a feature branch based on master, and we decided it's better to rebase it off production. This is our current git history:

commit 6 [my-feature-branch]
commit 5
commit 4 [master]
commit 3
commit 2 [production]
commit 1

We just need to run:

git checkout my-feature-branch
git rebase --onto production master

And we will end up with the following history:

commit 6 [my-feature-branch]
commit 5
commit 2 [production]
commit 1

Reference: https://makandracards.com/makandra/10173-git-how-to-rebase-your-feature-branch-from-one-branch-to-another

Before Callback Changes in Rails 5

In Rails 4 and below, callbacks like before_validation always had a gotcha that you had to watch out for:

before_validation :ensure_field_is_false_when_condition

def ensure_field_is_false_when_condition
  self.field = false if condition?
end

When condition? is true, the assignment happens. However, assignment returns the value that was assigned, so the before_validation receives the returned value false. As the docs mention:

If the returning value of a before_validation callback can be evaluated to false, the process will be aborted and Base#save will return false.

This is usually handled by an explicit return (i.e. nil does not stop the callback chain):

def ensure_field_is_false_when_condition
  self.field = false if condition?

  # extraneous return that is not Ruby-ish
  return
end

Rails 5 Update

There is a great change to the before_validation callback behaviour in Rails 5:

If the before_validation callback throws :abort, the process will be aborted and ActiveRecord::Base#save will return false.

This makes halting the callback chain much more transparent and intention revealing:

before_validation :safely_assign_false, :always_halt_validation

def safely_assign_false
  self.field = false
end

def always_halt_validation
  throw(:abort)
end

Use Chrome to make "desktop apps"

You can use Chrome to make slick desktop apps for your frequently used tabs, and even make aliases:

alias twitter="open -na 'Google Chrome' --args '--app=https://mobile.twitter.com'"

# replace #{UID} with the index of the google account you want to use
# if you are signed in to multiple accounts on your computer, otherwise 0 should be fine.
alias cal="open -na 'Google Chrome' --args '--app=https://calendar.google.com/calendar/b/#{UID}/r'"

# for fun
alias pm="open -na 'Google Chrome' --args '--app=https://packmanager.nulogy.net/'"

Original tweet: https://twitter.com/JaKXz92/status/1025050967111344128, credits to Elijah Manor!

Accessing Redux Store Without Redux DevTools

Thank you Dan Ambrogio for discovering this tip. Also, check out this blog post for more on the topic of Redux DevTools on production environments.

Let's say that you want to access the Redux Store on a production environment of your React/Redux application. Normally, you would do this through the Redux DevTools. However, your app has these DevTools disabled on production. What do you do then?

As long as your browser has the React DevTools installed, there's this awesome workaround (assuming you are using Chrome, could easily be ported to other browsers):

  • Navigate to the web page in question
  • Open up the Chrome DevTools
  • Click on the React tab
  • Click on the top-level <Provider> element/component
  • Press <ESC> to bring up a console in a split panel
  • Execute the following code: $r.store.getState(). VOILA!

Hash keys must be symbols for keyword arguments

Recently our team worked on a ticket which required us to remove the tooltips for Edit, Delete button.

As an initial approach, we changed the signature by parameterizing the tooltip, and inserted into #link_to helper. To preserve the options parameter, we converted it into a keyword argument (**options).

def link_to_delete_remote(object, path, tooltip: _("Delete"), **options)
   
   link_to(options[:title], path, options.merge('data-bad-after': js, id: link_id, title: tooltip, remote: true))
end
 <%= link_to_delete_object(job, tooltip: nil) %>


However, bunch of specs started failing with the following message.

# ArgumentError: wrong number of arguments (given 3, expected 2)

Turns out, there were few callers of the method who were passing in an object that contains String keys, and they weren’t being used as keyword arguments…

<%= link_to_delete_object(
      attachment,
      "some-string-key" => _("some_string_value"),
      "another-string-key" => true
    ) %>

In the end, we reverted the signature, injected tooltip: nil to options object, and just inlined options.fetch(:tooltip, _(“Delete”))

  def link_to_delete_remote(object, path, options = {})
    ...
    link_to(options[:title], path, options.merge('data-bad-after': js, id: link_id, title: options.fetch(:tooltip, _("Delete")), remote: true))
  end

Dig-ging into Data

Ruby 2.3 added a couple of dig methods to aid in accessing nested data.

Here's some Hash and Array examples:

hash = {
  animals: {
    furry: ["dog", "cat"],
    spikey: ["porcupine", "echidna"]
  }
}

hash.dig(:animals, :furry)
# => ["dog", "cat"]

# safely returns `nil` for missing keys
hash.dig(:plants, :yellow)
# => nil

array = [1, [[2, 3], 4, 5], 6]

array.dig(1, 0, 1)
# => 3

# dig on arrays take indexes, and repeatly call dig on the result
# thus, you have to be careful if the return type is not an array!
array.dig(2)
# => 6

array.dig(2, 3)
# => TypeError: Fixnum does not have #dig method

# and duck typing means they can be combined!
hash.dig(:animals, :spikey, 1)
# => "echidna"

Finding Where Rake Tasks Are Defined in Rails

Rake has an option to print where a task was loaded from.

$ rake -W gettext:find
rake gettext:find   $HOME/.rvm/gems/ruby-2.3.3/gems/gettext_i18n_rails-1.8.0/lib/gettext_i18n_rails/tasks.rb:64:in `block in <top (required)>'

We can also get this data with code. This allows us to explore the tasks (e.g. filtering). In a Rails console:

# load up all the tasks Rails knows about
> Rails.application.load_tasks
...

# if you know the task you are looking for:
> Rake::Task["gettext:find"].actions.map(&:source_location)
 => [["$HOME/.rvm/gems/ruby-2.3.3/gems/gettext_i18n_rails-1.8.0/lib/gettext_i18n_rails/tasks.rb", 64]]

 # if you want to explore known tasks
 > gettext_tasks = Rake.application.tasks.select { |e| e.name.start_with? "gettext:" }
 => [<Rake::Task gettext:add_language => [environment]>, <Rake::Task gettext:base_without_table_attributes => [environment]>, <Rake::Task gettext:find => [setup]>, <Rake::Task gettext:pack => [setup]>, <Rake::Task gettext:setup => [environment]>, <Rake::Task gettext:store_model_attributes => [environment]>]
 >
 > pp Hash[gettext_tasks.map { |t| [t.name, t.locations] }]
 {"gettext:add_language"=>
  ["$HOME/.rvm/gems/ruby-2.3.3/gems/gettext_i18n_rails-1.8.0/lib/gettext_i18n_rails/tasks.rb:99:in `block in <top (required)>'"],
 "gettext:base_without_table_attributes"=>
  ["$HOME/src/packmanager/master/lib/tasks/gettext.rake:27:in `block in <top (required)>'"],
 "gettext:find"=>
  ["$HOME/.rvm/gems/ruby-2.3.3/gems/gettext_i18n_rails-1.8.0/lib/gettext_i18n_rails/tasks.rb:64:in `block in <top (required)>'"],
 "gettext:pack"=>
  ["$HOME/.rvm/gems/ruby-2.3.3/gems/gettext_i18n_rails-1.8.0/lib/gettext_i18n_rails/tasks.rb:59:in `block in <top (required)>'"],
 "gettext:setup"=>
  ["$HOME/.rvm/gems/ruby-2.3.3/gems/gettext_i18n_rails-1.8.0/lib/gettext_i18n_rails/tasks.rb:43:in `block in <top (required)>'"],
 "gettext:store_model_attributes"=>
  ["$HOME/.rvm/gems/ruby-2.3.3/gems/gettext_i18n_rails-1.8.0/lib/gettext_i18n_rails/tasks.rb:82:in `block in <top (required)>'"]}

How to trigger a redeploy on ECS from web console

Sometimes, there is a neeed to trigger a redeploy on an ECS service without making any task changes (for example: rerun initialization scripts to pull secret updates). To trigger such a redeploy on an ECS service from the web console:

  1. Open the ECS service module on the AWS web console
  2. Click on the Cluster, then the Service you wish to trigger the redeploy on
  3. Press the Update button on the top-left
  4. Select the Force new deployment checkbox. Make no other changes. Press on the Next Step button.
  5. Click Next Step and Confirm on all subsequent screens without making any other changes.

You can observe that the process is a success by watching the Events tab for new tasks startin and old tasks stopping, and the Tasks tab to witness the new tasks go live.

ORDER BY NULL Sorting Options

The ORDER BY clause has options for placement of NULL columns. From the Postgres docs, the ORDER BY grammar is:

[ ORDER BY expression [ ASC | DESC | USING operator ] [ NULLS { FIRST | LAST } ] [, ...] ]

It shows we can put the NULL columns first or last.

Example

Imagine we have a datetime range, implemented as (start_at, end_at) tuples.

CREATE TABLE dates (id INT, start_at TIMESTAMP, end_at TIMESTAMP);

INSERT INTO dates VALUES 
(1, TIMESTAMP '2018-01-01 9:45', TIMESTAMP '2018-01-01 10:00'),
(2, TIMESTAMP '2018-01-01 10:00', null),
(3, TIMESTAMP '2018-01-01 10:15', null);

We want to order by end_at, then start_at. However, we want the NULL end_at tuples to appear before any with a value.

By default, NULL values will appear after non-NULL. With the NULLS FIRST option, we can change that:

SELECT * FROM dates ORDER BY end_at NULLS FIRST, start_at, id;

╒══════╤═════════════════════╤═════════════════════╕
│ id   │ start_at            │ end_at              │
╞══════╪═════════════════════╪═════════════════════╡
│ 2    │ 2018-01-01 10:00:00 │ <null>              │
├──────┼─────────────────────┼─────────────────────┤
│ 3    │ 2018-01-01 10:15:00 │ <null>              │
├──────┼─────────────────────┼─────────────────────┤
│ 1    │ 2018-01-01 09:45:00 │ 2018-01-01 10:00:00 │
╘══════╧═════════════════════╧═════════════════════╛

You can also specify NULLS when creating indexes too.

Def keyword can also be used as a begin statement

In Ruby, the begin keyword for exception handling (ie, begin...rescue...ensure, traditionally try...catch...finally in other languages) is optional. You can have a method that only declares a rescue or an ensure statement without begin. That's because the def statement in the method can serve the same purpose as begin. This means that this method:

def edit
  begin
    @user = find(params[:id])
    ...
  rescue ActiveRecord::RecordNotFound
    redirect_to :back
  end
end

Can legally be shortened to:

def edit
  @user = find(params[:id])
  ...
rescue ActiveRecord::RecordNotFound
  redirect_to :back
end

Safe Navigation Operator

If you have worked in a Rails project, you have probably came across the try and try! methods. try saves us from checking conditions before drilling-down through a message chain. try! is more restrictive; it raises when the receiver does not respond to the method:

require "active_support"
require "active_support/core_ext/object/try"

User = Struct.new(:name)

users = [User.new("Jason")]

users.first.try(:name)
# "Jason"

users.first.try(:unknown_method)
# nil

users.first.try!(:unknown_method)
# NoMethodError: undefined method `unknown_method' for #<struct User name="Jason">

Note these methods are provided by ActiveSupport. As of Ruby 2.3, this behaviour is now available in the language, called the safe navigation operator &.:

users = [User.new(name: "Jason")]
users.first&.name
# "Jason"

users = []
users.first&.name
# nil

Gotchas

When an object does not respond to a method, &. behaves like try!; it raises an error. However, nil seems to break this pattern:

# behaviour like try!
user&.unknown_method
# NoMethodError: undefined method `unknown_method' for #<struct User name="Jason">

# given that
nil.nil?
# true

# this is confusing
nil&.nil?
# nil

The last example has a simple explanation: &. checks the receiver. Since the receiver is nil, &. immediately returns nil. It does not matter that nil responds to the message.

Block Kwargs

Ruby 2.0 introduced keyword arguments. Ruby 2.1 further added required keyword arguments. It is common to see methods using kwargs:

def some_method(keyword_arg: "Hello", required_arg:)
  puts "#{keyword_arg} #{required_arg}"
end

some_method(required_arg: "world")
# Hello world

However, these changes also apply to block arguments:

define_method :prints_block_arguments do |default_arg: "hello", required_arg:, **others|
  puts "default_arg: #{default_arg}"
  puts "required_arg: #{required_arg}"

  others.each_pair do |key, value|
    puts "other arg: #{key} => #{value}"
  end
end

prints_block_arguments(required_arg: "world")
# default_arg: hello
# required_arg: world

prints_block_arguments(default_arg: "ciao", required_arg: "mondo", something: "else")
# default_arg: ciao
# required_arg: mondo
# other arg: something => else

prints_block_agruments()
# ArgumentError: missing keyword: required_arg

Git Shortlog

There are many ways to customize your git log output. However, the structure still the same: commit by commit.

A new variation I recently discovered was git shortlog. It displays commits by author, rather than most recently committed order. It is intended to help producing release notes.

This lets you find out who your largest contributors are, especially with the --summary option.

Try this:

$ git shortlog --summary | sort -r

Default Value for Deconstructed Object Parameter

In ES6, you can deconstruct a function's object parameter to have its properties assigned to local named variables:

function MyComponent({
  item: { foo, bar }
}) { ... }

Also in ES6, the properties of the object parameter can have a default value set:

function MyComponent({
  item = "LOL"
}) { ... }

TIL: The object parameter can have both destructuring and default values applied to it!

function MyComponent({
  item: { foo, bar } = { foo: 1, bar: 2 }
}) { ... }

Debug Arrow Functions With Comma Operator

Use the Comma Operator to execute many JavaScript expressions in one 'location', but only return the value from the last expression.

This is commonly used in classic for loops, but has an interesting use case to quickly debug a single-line arrow function. For example, suppose you wanted to throw a console.log() into this function:

const myFunc = value => doCrazyOperation(value.foo);

Without the comma operator, this function would have to be expanded into a multi-line block function with a return statement, which is relatively quite longer:

const myFunc = (value) {
  console.log("value", value);
  return doCrazyOperation(value.foo);
};

With the Comma Operator, this debugging is much easier to write and maintain:

const myFunc = value => (console.log("value", value), doCrazyOperation(value.foo));

Using module_function instead of extend self

It's a common pattern to use extend self inside ruby module to make all methods available in a static context/declared as class methods.

Instead of this, you can use module_function instead which will do the same as extend self but also have the added benefit of making those method private instance methods when they are included in another file.

module UserNameFormatter
  module_function

  def format_name(user)
    "#{user.name}"
  end
end

class User
  include UserNameFormatter

  def something
    format_name(self)
  end
end

Searching Through Gems

Sometimes you need to peak at the source of a class or method of a gem from your Gemfile. Since gems are managed by bundler, it has a command-line option that can help.

bundle show --paths will list the paths of all the gems from your Gemfile. You can grep through these directories to search.

I'm currently using ripgrep for searching at the command line, so can pass the paths there.

Here’s it all together in a simple Bash function:

function bundle-search() {
    rg $1 `bundle show --paths`
}

Enumerable Predicate Methods Have a New Argument

Enumerable#grep accepts an argument that returns elements that are true using case equality (===). These elements can then be passed to its block for further proccessing:

fruits = %w(apples orange grapes)
fruits.grep(/s$/) # => ["apples", "grapes"]
fruits.grep(/s$/) { |e| e.start_with?("a") } # => [true, false]

In Ruby 2.5, this parameter argument was added to the Enumerable predicate methods all?, none?, one?, and any?.

fruits = %w(apples orange grapes)
fruit.any?(/s$/) # => true

# === works with more than Regexes!
[1, 3.14, 2ri].all?(Numeric) # => true
[0, 1, 2, 3].all?(1..10) # => false
[0, 5].one?(1..3) # => false
[0, 5].none?(1..3) # => true

More Expressive Regular Expressions with Ruby

I came across some parsing code that contained this regular expression:

# the first capture is the left quote
# the second capture is the string content
# the third capture is the right quote
METHOD_CAPTURE = /Module\.method\(\s*(['"])(.+?)(['"])\s*\)/

This regexp is matching the string contents of a particular method call. It captures three pieces of information, mentioned in the comments.

This code is not self-documenting. We have three comments explaining the captures, and a regexp we must parse in wetware.

Furthermore, numerical indexes are difficult to track and modify in complicated regexps. PCRE supports named captures; denoted in Ruby by (?<name>pattern).

To make the comments superfluous, let's refactor using the following:

  1. Use named capture groups
  2. Use interpolation to give descriptive names to common components
  3. Don't capture needlessly (in our case, the captured quote characters are not used)
  4. Prefer [] over escaping (personal preference)
quote_character = %q|['"]|
optional_whitespace = "\s*"

METHOD_CAPTURE = /Module[.]method[(]#{optional_whitespace}#{quote_character}(?<string_contents>.+?)#{quote_character}#{optional_whitespace}[)]/

# #match returns an object or nil
matches = 'Module.method("some string")'.match(METHOD_CAPTURE)

# if an object, access captures by name:
matches[:string_contents] # "some string"

You can tailor how many named expressions/variables to use based on the complexity of the regexp.

Copy current file path relative to project root

I already knew about copying the current file path to the clipboard by using Shift+Cmd+C . The problem with this approach is that it copies the absolute path, for example, /Users/arturo/src/cool_project/lib/module/my_file.rb. This is not ideal if you are planning on sending this path to someone else or for some document you are writing.

A better option is to use RubyMine's Action Copy Reference which by default is bound to Shift+Alt+Cmd+C. This copies the current file path relative to the project, for example, lib/module/my_file.rb

To summarize:

Copy Paths Action

  • Default shortcut: Shift+Cmd+C
  • Example text to clipboard: /Users/arturo/src/cool_project/lib/module/my_file.rb

Copy Reference Action

  • Default shortcut: Shift+Alt+Cmd+C
  • Example text to clipboard: lib/module/my_file.rb

Thanks to Jordan N. for the tip!

Force push safely using --force-with-lease

We periodically force push feature branches when we rebase them.

To do this safely, I first check manually to see if my pair has pushed any commits I don't yet have in my local branch.

But there's an easier and safer way to do this. The --force-with-lease option will fail if there are upstream changes not yet merged.

It will work smoothly for standard rebasing situations, but protect against any inadvertent destructive force pushes.

Thanks to Jason K for sharing this tip with me!

Finding Where a Method is Defined

One great thing about Ruby is how flexible it is. Although sometimes it can be hard to determine where a method definition comes from.

One useful technique to pull out in just this circumstance is the source_location method.

For example, suppose you see a call to the quantity method in a spec and you wonder where its definition comes from. Do some puts debugging by adding this line:

puts method(:quantity).source_location

Lambda argument passing shorthand

Suppose that I have a Ruby lambda like so:

greeting = -> name { "Hello #{name}" }

The conventional way of calling this lambda is like so:

greeting.call("Ned") # "Hello Ned"

However, for those of you dreading having to type in call (hello, JavaScript developers), you can use this syntactic sugar instead:

greeting["Ned"]
greeting.("Ned")

Source: https://stackoverflow.com/questions/18774139/how-works-with-lambdas

UPDATE

I am now a sad panda to learn that this shorthand syntax is not recommended in the ruby-style-guide: https://github.com/bbatsov/ruby-style-guide/issues/205 https://github.com/bbatsov/ruby-style-guide/blob/master/README.md#proc-call

It's still a cool learning for me to know that this syntax exists in the first place, though.

FactoryGirl identifiers as symbols not strings

Why is FactoryGirl.create(:my_object) better than FactoryGirl.create("my_object")?

Symbols are immutable objects that are stored by the Ruby interpreter as a numeric ID (an implementation detail, the design of Ruby is flexible for different storage mechanisms).

Strings, on the other hand, take up a memory footprint as large as the number of characters in the string. Using symbols will thus take up less memory and potentially be faster because the same address in memory will be used.

If you have n instances of the same string in your code, Ruby will use O(n) memory to store all those strings, however, if you have n instances of the same symbol in your code, Ruby will use O(1) memory to do the same lookup.

Further reading: https://bugs.ruby-lang.org/issues/7792#note-58

This TIL came courtesy of a discussion with Evan and later on Arturo about best practices in writing test code, but shared here because it's broadly applicable and the FactoryGirl example is just one use case.

Z-Index Equivalent in SVG

To mimic the z-index CSS property in SVG, add the SVG elements to the page in the reverse order that you expect their z-positioning to be set. The subsequent elements added are placed on top of previous elements.

For example, if I were using the React SVG charting library Victory and I wanted my chart lines to be stacked on top of my chart area shading, I will add them to my component like so:

<VictoryChart>
  <VictoryArea ... />
  <VictoryLine ... />
</VictoryChart>

Combine all ES6 generator values into an array

The ES6 spread operator can be applied to an iterable to combine all its results into one single array. A trivial use case for this is to merge extra elements into an existing array (ie, [...existingArray, 2, 3]).

This usage of the spread can be applied to a Generator to combine all the results of the calls to next() into one array. This serves as syntactic sugar to replace needing to use a for-of loop to do the same operation. Here's an example (illustrative purposes only, ignore that this is not the best way to solve this problem):

function* evenNumbersGenerator(maxNum) {
  for (let i = 0; i <= maxNum; i += 1) {
    if (i % 2 == 0) {
      yield i;
    }
  }
}

...

const evenNumbersTo100 = [...evenNumbersGenerator(100)];

Side Learning: Generator functions cannot be declared as an arrow function, because they have to be declared as a non-method function.

Surround <g> around array of React SVG components

It is a typical practice when writing a React component that renders a list/array of components to surround these components around a <div> tag. This is because React does not directly support rendering arrays of components.

This practice will not work if the React components will deep-render SVG elements instead of HTML markup. The solution instead will be to wrap the array of SVG-based child components around <g> tags (which stands for group in SVG).

https://www.smashingmagazine.com/2015/12/generating-svg-with-react/

Exclusion using File Masks

When using Find in Path.. functionality to find a word across multiple files, file masks can be used to match certain types of files. For example, using *.rb will only look through Ruby files. On the other hand, if you want to exclude Ruby files instead, you can add an ! at the front (i.e. !*.rb).

Here are other useful examples/combinations:

all files excluding spec tests: !*spec.rb

all Ruby files excluding spec tests: *.rb,!*spec.rb

Add have_selector() matcher to RSpec Request Specs

If you are used to writing controller specs, you are probably comfortable with the `have_selector matcher. However, in request specs this matcher is not available. By default, you can only do text search inside the request body which leads to brittle assertions.

You can add the have_selector matcher by updating your RSpec config to include the Capybara matchers on request specs as well.

RSpec.configure do |config|

config.include Capybara::RSpecMatchers, type: :request

end

Then you can write more confident Request specs by using assertions like expect(response.body).to have_selector('ul li', text: 'List content here!')

Stop a docker-compose container without removal

Suppose you need to stop your docker-compose container but you don't want to remove the container. For example, this container runs your database, so removing the container would mean that you would also lose all your data.

Don't use docker-compose down. This will remove your container and you will have rebuild your database from scratch. Sad panda.

Instead, use docker-compose stop. You can then restart the container and have all the data back that you had before.

Resources:

Search DOM by selector in Chrome Inspector

Problem

I want to select a DOM element by CSS selector on my React-generated web page for debugging purposes. In this case, I am trying to test out CSS selectors to be used in my Capybara acceptance test.

Solution

Use jQuery NO, DON'T DO THAT!

A neat feature of the Chrome Web Inspector is that I can search an entire page by CSS Selector, without needing to litter my code with debugger statements. Just open up the Elements tab and then press CMD-F (on Mac) to open up a search bar. I can now type whatever CSS Selector that I want and view the results that match. I can quickly test different selectors out, so that I can verify that I am writing my Capybara test accurately.

Source

An Improvement to the Behaviour of the Git Pager

First, capture your current git pager settings (in case you want to go back):

git config --list | grep core.pager

Second, configure your new and improved git pager settings:

git config --global core.pager "less $LESS --tabs=2 -RFX"
--tabs=2: Is just right for displaying Ruby diffs

-R: Repaint the screen, discarding any buffered input
-F: Causes less to exit if a file is less than one screens worth of data
-X: Leave file contents on screen when less exits.

If you want to get even fancier consider diff-so-fancy.

Bulk Upsert through PostgreSQL 9.5+

Warning: This only works for PostgreSQL 9.5+


Given the following:

  1. a users table:

    • id
    • name
    • created_at
    • updated_at
  2. users table only has 1 user with values:

    • id: 1
    • name: Alejandro
    • created_at: '2010-10-10 10:00:00.000000'
    • updated_at: '2010-10-10 10:00:00.000000'

You can upsert using the following SQL query:

INSERT INTO
  users(id, name, created_at, updated_at)
VALUES
  (1, 'Alexander', NOW(), NOW()),
  (2, 'Belle', NOW(), NOW())
ON CONFLICT (id)
  DO UPDATE SET
    name=EXCLUDED.name,
    updated_at=NOW()
;

Results:

  1. User(id=1) will be renamed from Alejandro to Alexander. The updated_at value will be set to current time.
  2. User(id=2) will be inserted to users table with name = Belle, and both created_at and updated_at will be set to current time.

Chrome: Inspecting DOM elements that require focus

Using Chrome Dev Tools, I occasionally want to inspect an element that requires focus - for example, inspecting a selected date in a date selector.

Problem

As soon as I click the dev tools window, the element loses focus and I can no longer inspect in with the desired state.

Undesirable solution

On occasion when I've run into this scenario, I've placed a breakpoint or debugger statement in the JavaScript function that would be called when focus is lost. The problem with this is that it takes time and I need to locate the appropriate place in code.

Better solution

When in the desired state - for example, with the current date selected - pressing F8 will pause JavaScript execution. I can then inspect the DOM in the desired state.