Today I Learned

18 posts by alistairmckinnell

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

A More Succinct Way to Update Model Attributes

Instead of model.update_attributes! you can use this shorter form: model.update!

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.

Changing Your iterm2 Profile Programmatically

Change your iterm2 profile to Production with this command:

echo -e “\033]50;SetProfile=Production\a

Create a function to make it easier to switch profiles:

function iterm_profile {
  if [[ -z $1 ]]; then
    profile="Default"
  else
    profile=$1
  fi

  echo -e "\033]50;SetProfile=$profile\a"
}

I use this feature to let me know I am working on the Rails migration.

Source

Speed Up Bundler

It turns out that you can speed up Bundler if you increase parallelization.

$ bundle config --global jobs 8

On OS X you can use the sysctl command to determine the jobs setting appropriate for your hardware:

$ sysctl hw.ncpu
hw.ncpu: 4

I'm using number of cores times two. Works for me. YMMV.

Speeding Up Rake Command Completion

The speed of rake command completion is determined by the startup time of your Rails app.

If your Rails app is slow to startup, the oh-my-zsh rake-fast plugin will make rake command completion tolerable again.

Edit your zsh configuration file:

plugins=(... rake-fast ...)

After refreshing your shell instance issue the following command:

$ rake_refresh

Take a deep breath. Enjoy fast rake command completion.

OS X Command Line

I love being able to use Alfred as a kind of GUI command line...

..and I also like using the command line to get things done. I just discovered all sorts of new things that I can do from the command line from this GitHub repo.

For example, to show Wi-Fi Connection History:

defaults read \
  /Library/Preferences/SystemConfiguration/com.apple.airport.preferences | \
  grep LastConnected -A 7

Creating More than One Instance with FactoryGirl

In some test fixtures I need to create an array of instances . FactoryGirl provides the create_list method for exactly this purpose.

To create four shipments on an outbound trailer:

FactoryGirl.create_list(:shipment, 4, outbound_trailer: trailer)

In the example above, create_list returns an array containing the newly created shipments.

Convenient Git Command to Discard Local Changes

In order to discard all local commits on a branch, that is, to make the local branch identical to the upstream of the branch, run:

git reset --hard @{u}

where @{u} is the short form of @{upstream} and denotes the upstream branch.

Prefer sort_by to sort when providing a block

Prefer the sort_by method over the sort method whenever you provide a block to define the comparison.

Common form:

line_adds.sort { |x, y| x.elements["ItemRef/ListID"].text <=> 
  y.elements["ItemRef/ListID"].text }

Preferred form:

line_adds.sort_by { |x| x.elements["ItemRef/ListID"].text }

For small collections both techniques have similar performance profiles. When the sort key is something simple like an integer there is no performance benefit from sort_by.

The performance difference is especially noticeable if the sort key is expensive to compute and/or you have a large collection to sort.

The algorithm that yields the performance benefit is known as the Schwartzian Transform.

RSpec Matchers for Array Comparisons

Whenever you are matching arrays ask yourself two questions:

  • Is order important?
  • Am I matching a subset of the elements or all of the elements?

How I decide on a matcher:

  1. Choose between the eq and be matcher if order is important.
  2. Choose the include matcher if you want to match on a subset of the elements.
  3. Choose between the match_array and contain_exactly matcher if you want to match all elements (and order doesn't matter).

Below is an example of an improvement to a previously intermittent test. I replaced the eq matcher with the match_array matcher because I wanted to match all location_ids and order doesn't matter.

expect(location_ids).to eq([location_2.id, location_3.id])
expect(location_ids).to match_array([location_2.id, location_3.id])

The root cause of the intermittent test was that the locations were being retrieved from the database with no order specified. From the PostreSQL documentation: If sorting is not chosen, the rows will be returned in an unspecified order. The actual order in that case will depend on the scan and join plan types and the order on disk, but it must not be relied on.

Retrieving the IDs for a Model

Prefer the ids method to map(&:id) when you want to retrieve an array of model IDs.

Example

receipt.receive_orders.ids
receipt.receive_orders.map(&:id)

In the example above, using ids avoids fetching the receive orders from the database.

Rails Source

def ids
  pluck primary_key
end

zsh-autosuggestions

Fish-like fast/unobtrusive autosuggestions for zsh.

I followed the installation instructions for Oh My Zsh and works for me.

My command line life is so much sweeter.

Testing an Independent Mixin With RSpec

Objective: write a spec for the Inventory::Query mixin.

Note: the mixin is independent of the including class as it does not depend on any instance variables or instance methods.

Original Approach

class InventoryQueryTest
  include Inventory::Query
end
subject(:inventory_query) { InventoryQueryTest.new }

Preferred Approach

subject(:inventory_query) { (Class.new { include Inventory::Query }).new }

Advantage

Simpler and avoids polluting the global namespace with a test class.

Temporarily skip an RSpec example group

I knew about prefixing an RSpec example with x to skip it. I just found out that a describe or context example group can also be temporarily skipped using xdescribe and xcontext.

How did I find out? RTSL

Special bonus: the focus effect works similarly: fit, fdescribe, and fcontext.

Where Does That git Setting Come From?

Yesterday git config learnt a new --show-origin option to indicate where configuration values come from.

$ git config --show-origin user.email

Note: available in the 2.8.0 release.

Consider using the #public_send method

Prefer the #public_send method to the #send method.

result_date = date.public_send(operation, delta)

In the example above the first parameter to the #public_send method is either + or -.

Toggle Do Not Disturb

Option-click the Notification Menu icon to toggle OS X notifications. The icon is most likely in the top right hand corner of your menu bar.