Today I Learned

37 posts by evanbrodie

How to Center Vertically and Horizontally in CSS

This helpful guide teaches you everything you wanted to know about centering your HTML elements vertically and horizontally using CSS: https://css-tricks.com/centering-css-complete-guide/

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.

Repeat last substitution in VIM

Use the & motion to repeat the last substitution in VIM. IE, the most recent :s command.

Very handy in a git interactive rebase that requires every commit message to have a ticket reference changed.

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/

VIM: Move a numbered line to current cursor

Let's say I'm on line 20 and I want to move line 10 to my current line. Useful for code refactoring.

How I used to do it

10G
dd
19G
p

Or:

:10d
p

The new way I'll do it

Thanks to my learnings here:

:10m .

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

Range prefix to VIM command (from current line)

When I want to execute a command in VIM over a range of lines (for example, search-replace with :s) starting from the current line, I could execute a command like so:

:.,.+10s/foo/bar/g

This reads as search-replace from the current line (.) until 10 lines after. While useful functionality, it does require quite a bit of typing to execute.

Thankfully, there is a neat little shortcut that can be used to reduce some of this type. Simply enter the number of lines that you want to change from the current line and VIM will fill in the rest in the command prompt.

For example, I need to type 11: and VIM will insert :.,.+10 into the command prompt. You can now finish off this command like needed. Do note that the line count includes the current line itself (think of this count as current line plus number of lines after).

All the different ways to lock your Mac computer

  • Using the keyboard: CTRL-SHIFT-eject
  • Using Alfred: execute the lock command
  • Using a taskbar icon from Keychain:
    • Open the app Keychain Access
    • Preferences --> Enable the option Show keychain status in menu bar
    • A lock-shaped icon will appear in the taskbar, with the option Lock Screen
  • Use Hot Corners:
    • System Preferences --> Desktop & Screen Saver --> Hot Corners button
    • Set one of the corners as Put Display to Sleep
    • Mouse into the direction of that corner (on the monitor closest to that side, for multi-monitor setups)
  • If all else fails, just hold the Power button on your keyboard for a second to put your computer to sleep

Ignore whitespace-only changes in Gitlab MRs

Problem

You are reviewing a Gitlab Merge Request (MR). It involes changes where a Ruby file is moved into or out of particular modules. This means that one or more module ... end constructs are either added or removed around the entire class, resulting in a tabbing-width change on almost every line of the file. This makes reviewing the file in the MR quite difficult, as the reviewer will need to sift through the code diff and separate out actual logic changes from whitespace-only changes.

Solution

By appending ?w=1 to the end of the URL of the MR, Gitlab will ignore all lines that only feature a whitespace change in the code diff. This means that the only changes visible will be ones with a non-whitespace change, thus allowing the reviewer to focus in on actual logic changes and not waste time reading whitespace changes.

Time to poke Gitlab EE support on this issue: https://gitlab.com/gitlab-org/gitlab-ce/issues/1393

Replacing num.times.map with Array.new(num)

Problem

I want to create an array containing objects created with an incrementing integer index parameter. For example, an array of hashes containing strings built off of the incrementing number.

Standard Solution

my_array = num.times.map do |index|
  build_hash(index)
end

BUT...rubocop didn't like this:

... C: Performance/TimesMap: Use Array.new with a block instead of .times.map

Improved Solution

The improved solution allows us to build the same array with less chained methods, thus improving readability:

my_array = Array.new(num) do |index|
  build_hash(index)
end

Mocha: Fail on any console error message

PROBLEM

I want to write a Mocha (JS) test that will fail if there is any warning printed to the console to fail. My use case to necessitate this requirement is that I want to test whether the correct prop type is passed to a React component. PropTypes exists for this purpose, but would only print out a message to the console instead of failing.

SOLUTION

Use the following code, either at the beginning of your test file or a global helper such as specHelper.js, to stub out the implementation of console.error to throw an Error and thus fail the test.

before(() => stub(console, "error", (warning) => {
  throw new Error(warning);
}));

after(() => console.error.restore());

Reference: this gist.

Run last command in BASh/ZSH (they're different)

To run the last executed command in BASH, execute the following:

!!

In ZSH, things are a little different. Using !! will only expand the command into the shell prompt. You would have to press enter again to execute it. Rather, if you want to immediately execute the last command similar to BASH, use this:

r

If you prefer for ZSH behaviour to match that of BASH, then add setopt no_hist_verify to your .zshrc file.

Ruby print to replace contents on same line

In Ruby, the print command can be used with the '\r' (carriage return) character to bring the cursor back to the beginning of the printed line, so that the next print call will replace the contents already outputted to that line. This is a very useful tool for printing status updates in a CLI script. For example:

print "#{index} done. Progress: %.2f%" % (index.to_f / items * 100).round(2) + "\r" if (index % 10) == 0

This will print and replace a line in STDOUT to report the status of a list of items being processed by a function, like so:

200 done. Progress: 15%

Typewriters still hold a lasting impact on modern-day computing!

Hotkey to switch control mode in Mac Screen Share

I use MacOS screen sharing to power pair programming sessions that I have in my development team. There are two modes for the navigator to use when observing the driver's screen (assuming that the screen being shared is of the driver): Observe Mode to disallow taking control of the screen, or a self-explanatory Control Mode.

I like being in Observe Mode as the navigator so that I don't mistakingly take control of the driver's screen and start polluting the screen with accidental key strokes. But if I ever need to switch control, I would have to then make a mouse click on the correct icon. This gets annoying if I am observing in Full Screen mode (which is almost always). I would have to exit full screen mode first in order to switch to taking control.

SOLUTION: I can instead use the CMD-ALT-X key combination to quickly switch control mode :D

Compounding expectations in Rspec and Chai

When I had multiple expectations on the same object in rspec, I would write the code like so:

expect(page).to have_content("Foo")
expect(page).to have_content("Bar")
expect(page).to have_content("Other Stuff")

You can save yourself some typing if you instead use compound expectations, which is basically the usage of the and function after the previous expectation. Doing so will allow the previous code to be writted as such:

expect(page).to have_content("Foo")
  .and have_content("Bar")
  .and have_content("Other Stuff")

The same concept also exists in the Chai JavaScript testing library (documentation):

expect(page).to.contain("Foo")
  .and.contain("Bar")
  .and.contain("Other Stuff");

Add executable flags in git file

There is support in the git add command to make a file tracked in your git repository executable. For example, let's say you added a foo.sh script to your repo but forgot to add the executable bit to its file permissions. You can now do this:

git add --chmod=+x foo.sh

One gotcha of this approach is that this will only change the permissions tracked by git, but not the actual permissions of the file on YOUR filesystem. You will still need to run chmod +x foo.sh to modify your local permissions. However, your teammates should be able to pick up the permission changes from a git pull.

Courtesy of http://stackoverflow.com/a/38285435/814576

Add extra line to git commit message from CLI

You can add extra lines to your commit messages by adding an extra -m flag to the git commit flag. This is useful if you have extra information that you want captured in your commit, but you don't want it in your commit message header. For example:

git commit -am "Updates the README with copyright information" -m "This conforms to requirements from Legal."

Will produce the following commit message:

Updates the README with copyright information

This conforms to requirements from Legal.

Now your commit message is split up into a header and a body. You can also add another -m flag for a footer.

NPM: List available custom scripts in the CLI

If you are working in the CLI on a project that uses NPM and you want to know what what custom scripts are available to you, without need to open and scroll through package.json, just simply execute:

npm run

and all your custom scripts will be outputed to the screen.

Toggle Console Tab From Chrome Inspect Tools

If you have the Inspect Tools open on your Google Chrome browser, you can toggle a Console tab to appear at the bottom of the Inspect pane by pressing Escape on your keyboard. This is very useful if you need to have another Inspect tab open at the same time as the Console, such as Source or React Dev Tools.

RubyMine Highlight for Multi-cursor Drag-and-drop

To create a Multi-cursor in RubyMine with your mouse, hold Alt while dragging your mouse up/down. This is especially useful if you want to adjust tabbing or add some extra characters on consecutive lines.

[GIT] Change capitalization of file

HOW DO I CHANGE THE NAME OF A FILE UNDER GIT CONTROL WHERE NOTHING CHANGES EXCEPT THE CAPITALIZATION OF THE LETTERS?

For example, let's say that you had a file called myfile.js and you wanted to rename it to MyFile.js. This change would not be recognized in git status and therefore cannot be committed because none of the characters actually changed. It appears that git treats files in a ignores-case way when scanning for changes. Whereas, if I added or removed any of the characters in that name, ie MyFile1.js, then git would recognize the rename.

SOLUTION

As per this Stackoverflow post, you can still commit this filename capitalization change using a git mv command. So in this example, we would want to execute this:

git mv myfile.js MyFile.js

RubyMine group search by Test and Production code

When I do code searches in RubyMine, I sometimes want to only see non-test code for various reasons, such as knowing how often a particular method is used in our code base to judge adoption level. Normally, I would have to select each directory and run a code search one at a time, or search all directories at once and carefully skip over all test code while scrolling through the list. In a Rails app, directories that contain non-test source code could include app/, domain/, lib/ and even more.

There is a better way! The RubyMine Search tab has a toggle that will let you group source code search by Production and Test code. All you have to do is press this toggle and voila!

validates_presence_of won't work with booleans

If you want to validate that a value for a particular boolean field exists (using ActiveRecord instead of null constraints from you DB), then you cannot use validates_presence_of. This is due to the way that the blank? works on an object with the value false. Instead, you will need to use this for your validation:

 validates_inclusion_of :field_name, :in => [true, false]

SEE:

http://stackoverflow.com/questions/2883823/why-does-false-invalidate-validates-presence-of http://apidock.com/rails/ActiveModel/Validations/ClassMethods/validates_presence_of

Fix Mac RubyMine Floating Window Bug

PROBLEM

On RubyMine in Mac, I want to have my RubyMine IDE in one window but have the Run display in Floating Mode appear in my secondary monitor. The issue, though, is that after I have moved the Run display into my secondary monitor, lose focus to another window, then click back into the Run display, the will suddenly JUMP to the same window as my main RubyMine IDE.

SOLUTION

The problem appears to be a conflict with a setting in Mac's Mission Control. You will need to deselect the Displays have separate spaces option in the Mission Control preferences screen, as described here.

#thanksapple

Enable Mac Keyboard Number Pad in iTerm

If you Mac keyboard's number pad is not working in iTerm, then follow the steps outlined here: http://superuser.com/a/565179/175226

Looks like the answer is to go into Preferences->Profiles->Keys
and load preset of: xterm with numeric keypad.

You will lose any default key mappings that you already set in your iTerm profile already, so you may want to do this in a brand new profile so you can bring over your old mappings to the new profile and not outright lose them like I just did.

Pinch to zoom in Mac RubyMine

PROBLEM

I am presenting some source code during a meeting on RubyMine on my Mac machine. When I plug into the projector, my display resolution becomes quite high, so all text on the projector become very small. Using CMD + does not zoom in.

SOLUTION

Instead, you will need to pinch the Mac's touchpad with two fingers to control the zoom. Pinch inwards for zoom-out and outwards for zoom-in. You will need to do this on every code tab you have open.

Thanks for the tip, Sean Kirby.

What's a "twiddle-wakka"?

I'm proud to say that I now know what a twiddle-wakka is. It is the notation ~> that we use in our Ruby-flavoured semver notation in Gemfile. Specifically, it means that the accepted version must be at the same level of the specified version. All sub-levels below the next increment of the current level are accepted. For example, ~> 2.0 means 2.0 <= VERSION < 2.1, while ~> 2.0.1 means 2.0.1 <= VERSION < 2.0.2.

Reference: http://guides.rubygems.org/patterns/

But seriously, now I know what a twiddle-wakka is. :D

Git Cherry-Pick A Merge Commit

PROBLEM

I picked up work on a topic branch that has a WIP commit. I reset the branch, fix a few lines, then committed. I noticed now that I'm 1 Ahead and 1 Behind on my branch. I should do a force push....but I forgot to! Instead, I pulled and thus created a merge commit. Ruh roh!

                 WIP
             /        \
A --- B --- C --- D --- M --- E --- F

Not only will this merge commit (empty, by the way) make our overall git history look ugly, it is also going to make rebasing off master very difficult, since we will have to resolve a conflict for all future commits (E and F). I want to keep my topic branch flat.

SOLUTION

You can escape this mess via a series of git cherry picks. The key part of this is how we applied the cherry-pick on merge commit F. We need to specify which parent to base the commit off of.

git checkout -b new_branch
git cherry-pick A
git cherry-pick B
git cherry-pick C
git cherry-pick D
git cherry-pick M -m 1
git cherry-pick E
git cherry-pick F

ActiveRecord #count versus #length

Let's say you have an ActiveRecord model with a has_many association. Ever wonder why you receive different results from #count and #length after you append to that has_many collection? Consider this rough example where Parent and Kid are ActiveRecords and Parent will has_many :kids:

parent = Parent.create!
parent.kids.create! name: 'Evan'
puts "Current length is #{parent.kids.length}"
puts "Current count is #{parent.kids.count}"

The output will be:

Current length is 0
Current count is 1

The difference in results appear to be happening because of how length() and count() compute their results. length() is only considering what is loaded into heap memory (cached), while count() will actually check what is loaded into the DB.

Here's a great blog post about the difference between the two methods, as well as size().

Oh-My-Zsh Plugins List

I feel like I just discovered the Internet when I look at this page:

https://github.com/robbyrussell/oh-my-zsh/wiki/Plugins

How to view changes from only a particular branch

git log master.., assuming your branch was based off of master. If based off of something else, use that branch name (ie, git log production..)

Courtesy of http://stackoverflow.com/a/4649377/814576

Find all commits by a particular author

Do you want to know quickly about all the commits that a single author has pushed? Easy, just run a git log command with the --author` flag, like this:

git log --author="evanb@nulogy.com"

Problems with Reusing Ruby Standard Class Names

You might want to think twice before making a class that reuses the same name of a Ruby Standard Library class. If undetected, you will get strange hard-to-debug behaviour in your app. Let's explore further with this Ruby file:

module Utils
  module String
    def self.some_useful_method
      # ...
    end
  end
end

module Utils
  module Foo
    def self.do_stuff(string)
      raise "Argument '#{string}' is not a string" unless string.is_a?(String)
      # ...
    end
  end
end

Utils::Foo.do_stuff("Hello World")

Okay, so Hello World is a String. And a String is a String, no questions asked. Right? Well...not quite.

RuntimeError: Argument 'Hello World' is not a string

Since Utils::String gets loaded by Ruby, all references to the String constant from code inside the Utils module will resolve to Utils::String. This example may seem simple and obvious, but imagine if these two classes were in separate files, even separate libraries. How would it feel like if you keep getting "string".is_a? String => false in your debugging sessions?

MORAL OF THE STORY: It probably isn't a good idea to reuse class names from the Ruby Standard Library. Naming the first module to Utils::StringUtils is likely a better idea.

Curly braces vs. do/end: Operation Precedence

Choosing whether you use { ... } or do ... end around your blocks is more than just a stylistic choice in Ruby. It also affects the way that an operation will be executed because your choice also specifies the Operation Precedence to use. In a nutshell, a block curly braces has higher precedence than a block with do/end.

Consider this example from a great Stackoverflow post:

f param { do_something() }

will execute differently than

f param do do_something() end

The former will bind the block to param, while the latter will bind the block to f. The more you know...