Today I Learned

ins8s

60 posts about #ruby

Create Listing Of All Middleman Pages

Middleman is a handy tool for quickly throwing together a bunch of static pages with layout and templating help at the ready. Once you have a handful of pages up and running, you’ll probably want a way to quickly navigate to them. You can add a quick listing of all the pages with a couple helpers provided by Middleman.

<ul>
  <% sitemap.resources.each do |resource| %>
    <li><%= link_to(resource.path, resource.path) %></li>
  <% end %>
</ul>

The sitemap.resources variable will contain a list of all the resources that get processed and served by the Middleman app. The link_to helper makes it easy to turn those into links.

Because resources includes images and other assets, you may want to filter down to just html files which could look something like the following:

<ul>
  <% sitemap.resources
       .select { |resource| resource.path =~ /html$/ }
       .each do |resource|
  %>
    <li><%= link_to(resource.path, resource.path) %></li>
  <% end %>
</ul>

Just add the snippet to whatever page you’d like the page listing to appear on.

Use dotenv In A Non-Rails Project

Up to now I’ve only used dotenv in a Rails context. It can just as easily be used in a plain old Ruby project.

Install the non-Rails version of the gem.

$ gem install dotenv

Then add the following lines wherever you want dotenv included and loaded. In my case, I want it pulled in as part of my RSpec setup in spec_helper.rb.

require 'dotenv'
Dotenv.load

Your environment variables declared in .env are now accessible via fetches against the ENV object.

ENV.fetch('my_env_var')

Ins And Outs Of Pry

When executing commands during a Pry session, you’ll see an incrementing number for each prompt as you enter each statement. These numbers can be used to look up the inputs and outputs of each statement executed during the session. The statements and their results are made available in the array-like _in_ and _out_ objects.

[1] pry(main)> :one
=> :one
[2] pry(main)> 1 + 1
=> 2
[3] pry(main)> ["t", "h", "r", "e", "e"].join
=> "three"
[4] pry(main)> _in_.to_a
=> [nil, ":one\n", "1 + 1\n", "[\"t\", \"h\", \"r\", \"e\", \"e\"].join\n"]
[5] pry(main)> _out_.to_a
=> [nil, :one, 2, "three", [nil, ":one\n", "1 + 1\n", "[\"t\", \"h\", \"r\", \"e\", \"e\"].join\n"]]
[6] pry(main)> _out_[2]
=> 2
[7] pry(main)> _in_[2]
=> "1 + 1\n"

source

Chaining Multiple RSpec Change Matchers

It can be handy to use RSpec’s change matchers to determine if some method or process creates a new record.

expect{ Registration.create(attrs) }.to change{ User.count }.by(1)

But what if we are testing a method that creates a couple different records in the system?

RSpec allows us to chain together change matchers with and. Consider this additional contrived example.

expect {
  Project.generate(attrs)
}.to change{ Project.count }.by(1).and \
     change{ User.count }.by(1)

In addition to keeping our tests tight and concise, this approach gives some pretty nice output on failure.

If we were just beginning our implementation with a failing test, we’d see a multi-part failure like the following.

Failure/Error:
  expect {
    Project.generate(attrs)
  }.to change{ Project.count }.by(1).and \
       change{ User.count }.by(1)

     expected result to have changed by 1, but was changed by 0

  ...and:

     expected result to have changed by 1, but was changed by 0

Rerun Only Failures With RSpec

After running a big test suite, I may have a bunch of output on the screen including the results of a couple test failures. I like to bring the context of the test failures front and center and make sure they are consistent test failures (not flickering failures). Instead of copying and pasting each failure, I can rerun rspec in a way that executes only the test cases that failed.

$ rspec --only-failures

This feature requires that you set a file for RSpec to persist some state between runs. Do this in the spec/spec_helper.rb file. For example:

RSpec.configure do |config|
  config.example_status_persistence_file_path = "spec/examples.txt"
end

See more details here.

h/t Brian Dunn

Use A Case Statement As A Cond Statement

Many languages come with a feature that usually takes the name cond statement. It is essentially another way of writing an if-elsif-else statement. The first conditional in the cond statement to evaluate to true will then have its block evaluated.

Ruby doesn’t have a cond statement, but it does have a case statement. By using a case statement with no arguments, we get a cond statement. If we exclude arguments and then put arbitrary conditional statements after the when keywords, we get a construct that acts like a cond statement. Check out the following example:

some_string = "What"

case
when some_string.downcase == some_string
  puts "The string is all lowercase."
when some_string.upcase == some_string
  puts "The string is all uppercase."
else
  puts "The string is mixed case."
end

#=> The string is mixed case.

source

Or Operator Precedence

What’s the difference between || and or in Ruby?

Let’s look at an example to find out. First, let’s start with some boolean variables:

> a, b = false, true
=> [false, true]

Now, let’s try the different or operators:

> a || b
=> true
> a or b
=> true

Cool, they seem to work as expected.

Finally, let’s capture the result in a variable:

> c = a or b
=> true
> c
=> false

But why is c false and not true? Operator precedence. The assignment operator (=) takes precedence over the or operator causing c to be assigned to the value of a (false) before or’d with b.

source

Require Entire Gemfile In Pry Session

Want to experiment in a pry session with some of the gems in your project’s Gemfile? You can quickly require all the gems for your project using Bundler’s #require method.

Just require bundler itself and then execute Bundler.require. Everything will be loaded in.

> require 'bundler'
=> true
> Bundler.require
=> [Gem::Dependency.new("devise", Gem::Requirement.new([">= 0"]), :runtime),
 Gem::Dependency.new("rails", Gem::Requirement.new(["= 4.2.5"]), :runtime),
 Gem::Dependency.new("pg", Gem::Requirement.new(["~> 0.15"]), :runtime),
...

String Interpolation With Instance Variables

When using regular variables with string interpolation in Ruby, they must be wrapped in curly braces (e.g. "This is a #{variable}"). With instance variables (and class and global variables) you can just use the octothorp followed directly by the variable.

Here is an example of this in action:

class Person
  def initialize(name)
    @name = name
  end

  def whoami
    puts "I am #@name"
  end
end

bob = Person.new("bob")
#=> #<Person:0x007fdaf3291618 @name="bob">

bob.whoami
# I am bob

This is a handy shortcut, but may affect readability and/or result in an interpolation error at some point. Your mileage may vary.

h/t Josh Davey

Edit Previous Parts Of The Pry Buffer History

Each line of Ruby you enter into a Pry session is recorded with a number in the buffer history. Pry keeps this buffer history so that you can recall parts of it for editing and subsequent execution.

If you use the edit command by itself, Pry will open the previous Ruby statement in your default editor. But what if you want to edit a statement from a while back? Or even a series of statements?

Use the --in flag with edit either specifying a single record in the buffer history or a range of records.

$ pry
[1] pry(main)> puts "Hello"
Hello
=> nil
[2] pry(main)> puts "World"
World
=> nil
[3] pry(main)> puts "People"
People
=> nil
[4] pry(main)> edit --in 1..2
Hello
World
=> nil

Up And Down With Integers

Ruby’s Integer class comes with an #upto and a #downto method. Both of these methods can be used to iterate from one number up or down to, respectively, another number.

Let’s count to 3

> 1.upto(3) { |x| puts x }
1
2
3

This of course can easily and perhaps more idiomatically be accomplished with a range and the #each method (e.g. (1..3).each { |x| puts x }.

We cannot, however, simulate the #downto method with a range (at least, not very cleanly). So, if you need to count down to something, this is going to be the cleanest and clearest way.

> 5.downto(2) { |x| puts x }
5
4
3
2

The return value for both methods is always the integer we started with.

Running A Single MiniTest Example

Consider the following MiniTest file:

# test_stuff.rb
require 'minitest/autorun'

class TestStuff < MiniTest::Unit::TestCase
  def test_first_thing
    assert_equal 4, (2 * 2)
  end

  def test_second_thing
    assert_equal 9, (3 * 3)
  end
end

If we want to run all the tests in this file, we can do so with:

$ ruby test_stuff.rb

But what if we want to run a specific test? We can target a single MiniTest example with the --name flag and the name of that example. We can do something like the following:

$ ruby test_stuff.rb --name test_second_thing

source

Fail

The fail method is synonymous with raise in Ruby. Consider the following code snippet:

def is_odd?(num)
  num.odd?
rescue
  fail StandardError, 'you cannot use odd on this'
end

> is_odd?(1)
#=> true
> is_odd?('hello')
#=> StandardError: you cannot use odd on this

Nevertheless, I believe the raise method is preferred to the fail method.

source

h/t Dorian Karter

Are They All True?

There is a method on Enumerable that allows you to check against everything in a collection. This is the all? method. For instance, if you want to check if an array of values are all truthy, you can call it without arguments:

> [true, 1, ''].all?
# true
> [true, false, true].all?
# false

You can also pass it a block which is helpful if you want to check an attribute or method on a collection of objects, like so:

> employees.all?(&:salaried?)
# true
> [1,2,3,4,5].all?(&:odd?)
# false

If You Detect None

The Enumerable#detect method, which is synonymous with #find, can be given an optional argument, ifnone, that is called when nothing in the array meets the conditional in the block. Though I am not sure how this is practically useful and cannot find an example of it in use, this contrived example illustrates how it works.

# without the fallback behavior
> [2,4,6,8].detect { |x| x.odd? }
=> nil

# with a proc as an argument
> [2,4,6,8].detect(->{0}) { |x| x.odd? }
=> 0

The last example can also be written as:

> [2,4,6,8].detect(->{0}, &:odd?)
=> 0

And if you want to be really explicit:

> [2,4,6,8].detect(ifnone=->{0}, &:odd?)
=> 0

Show Public Methods With Pry

Open up a pry session and use the -m flag with the ls command to show just the public methods for an object.

> ls -m :hello
Comparable#methods: <  <=  >  >=  between?
Symbol#methods:
  <=>  as_json      empty?    length              slice     to_sym
  ==   capitalize   encoding  match               succ      upcase
  ===  casecmp      id2name   next                swapcase
  =~   downcase     inspect   pretty_print_cycle  to_proc
  []   duplicable?  intern    size                to_s

source

Defaulting To Frozen String Literals

The cold never bothered me anyway.

The release of Ruby 2.2 introduced the ability to freeze string literals, making them immutable. With the release of Ruby 2.3, strings can be frozen by default without the use of #freeze. By adding the following magic comment at the top of a file

# frozen_string_literal: true

all string literals will default to frozen. That means that all string literals in that file are immutable, cannot be modified. This gives the Ruby interpreter some performance gains due to reduced object allocation.

This is the issue that introduced it.

Returning With Sequel

The sequel gem is a database toolkit that allows you to interact with most databases. PostgreSQL has support for composite primary keys, but sequel, which is supposed to return the id of newly inserted records, isn’t sure what to return when faced with a composite primary key. You can get around this by telling sequel exactly what should be returned using the #returning method. For instance, get it to return just the id of the new record:

DB[:floors].returning(:id).insert(hotel_id: 4, id: 1, ...)
# [{id: 1}]

To get it to return both parts of composite key:

DB[:floors].returning(:id, :hotel_id).insert(hotel_id: 4, id: 1, ...)
# [{id: 1, hotel_id: 4}]

Rendering ERB

If you have a string that contains ERB templating, you can quickly generate the resulting string with the following code snippet:

require 'erb'

some_template_string = <<-TEXT
The top
<% 5.times do |i| %>
Item <%= i + 1 %>
<% end %>
The bottom
TEXT

puts ERB.new(some_template_string).result

This will print the following to stdout:

The top
Item 1
Item 2
Item 3
Item 4
Item 5
The bottom

source

Who Are My Ancestors?

Ruby’s Module class provides the #ancestors method. This method allows you to determine the ancestors (parents, grandparents, etc.) of a given class.

> 5.class.ancestors
=> [Fixnum, Integer, Numeric, Comparable, Object, PP::ObjectMixin, Kernel, BasicObject]
> Array.ancestors
=> [Array, Enumerable, Object, PP::ObjectMixin, Kernel, BasicObject]
> Class.ancestors
=> [Class, Module, Object, PP::ObjectMixin, Kernel, BasicObject]
> BasicObject.ancestors
=> [BasicObject]

Pass A Block To Count

Ruby’s Enumerable module comes with the method #count for determining how many items are in an array or hash.

> [1,2,3].count
=> 3
> {a: 1, b: 2}.count
=> 2

The #count method has a trick up its sleeve though. It can take a block with a predicate that returns true or false. It essentially acts like #select returning the count rather than the array subset itself.

> [1,2,3].count { |x| x.odd? }
=> 2
> {a: 1, b: 2}.count { |(x,y)| y < 0 }
=> 0

Safe Navigation Operator

With the release of Ruby 2.3, the safe navigation operator (&.) is now available. This addition to the Ruby language allows you to collapse all those pesky nil checks into the accessor call they are guarding. Consider this snippet of common Ruby code:

if user && user.authenticate(params[:password])
  # proceed with logged in user
end

With the safe navigation operator, the predicate can now be collapsed:

if user&.authenticate(params[:password])
  # proceed with logged in user
end

If user is nil, then the predicate will evaluate to false and the body of the if-statement will be passed over.

Source

Comparing Arrays In RSpec

Among its many built-in matchers, RSpec includes a set of array matchers. One of the array matchers is match_array which compares two arrays independent of ordering. This is handy if you need to check that a resulting array matches your expectations when ordering is unimportant and not necessarily deterministic. It can be used like so:

expect([1,2,3]).to match_array([3,2,1])

This expectation is met, the test will pass.

Colorful Output With MiniTest

Ruby’s MiniTest is a minimal testing framework that you can easily drop-in to any Ruby project. For those used to using RSpec with it’s fancy red/green output, MiniTest can be a little disappointing. It prints boring, uncolored text to the screen that lacks visual feedback. Fortunately, red and green coloring can be added with minitest/reporters.

Update your Gemfile:

gem 'minitest-reporters'

Then require and configure minitest-reporters in your testing setup file (e.g. test/test_helper.rb):

require 'minitest/reporters'
Minitest::Reporters.use! [Minitest::Reporters::DefaultReporter.new(:color => true)]

You can now enjoy that Red, Green, Refactor cycle.

Construct A Constant From A String

Ruby’s Module.const_get can be used to look for and retrieve the constant for a given name.

This can be used to construct a class name

> Object.const_get("Math")
#=> Math
> Object.const_get("Math")::PI
#=> 3.141592653589793

It can also be used to reference a constant

> Object.const_get("Math::PI")
#=> 3.141592653589793

You can even be more specific if you’d like

> Math.const_get("PI")
#=> 3.141592653589793

Symbols are valid as well

> Math.const_get(:PI)
#=> 3.141592653589793

Zero Padding

Ruby makes zero-padding strings to a fixed length easy with String#rjust.

> "1234".rjust(6, "0")
=> "001234"
> "123456".rjust(6, "0")
=> "123456"

In the same way, you can pad zeros on the other side of the string with String#ljust.

> "12".ljust(4, "0")
=> "1200"
> "".ljust(4, "0")
=> "0000"

h/t Dillon Hafer

Replace The Current Process With An External Command

Ruby’s Kernel#exec method can be used to run an external command. What differentiates it from executing commands with the likes of back ticks or %x[] is that instead of forking a child process, it replaces the current process.

For instance, the following ruby script, when executed, will replace itself with an irb session.

Kernel.exec('irb')

The external command will even benefit from the existing environment. For example, if I set the following environment variable

$ export GREETING=hello

and then execute a file containing

Kernel.exec('echo $GREETING')

I can expect to see hello printed to stdout.

Invoking Rake Tasks Multiple Times

I have a rake task, build, that builds a single record for development purposes. I want a supplemental rake task, build:all, that builds a bunch of different records. To keep things dry, build:all should just invoke build a number of times.

namespace :build do
  task :all do
    predefined_list.each do |data|
      Rake::Task["build"].invoke(data)
    end
  end
end

This doesn’t work though. No matter how many items are in the list, the build task only seems to get run once. This is because by default tasks can only be invoked once in a given context. To get around this, the task needs to be reenabled after each invocation.

namespace :build do
  task :all do
    predefined_list.each do |data|
      Rake::Task["build"].invoke(data)
      Rake::Task["build"].reenable
    end
  end
end

Uncaught Exceptions In Pry

You are fiddling around with some code in a pry session trying to familiarize yourself with how it all works. You suddenly execute a statement that results in an uncaught exception. You’d like to take a closer look at the exception. Pry makes this easy by exposing the _ex_ variable which points to the last uncaught exception.

Try it out in a pry session:

> class MyError < StandardError; end
=> nil
> def do_stuff; raise MyError, "Something bad happened"; end
=> :do_stuff
> do_stuff
MyError: Something bad happened
from (pry):2:in `do_stuff'
> _ex_
=> #<MyError: Something bad happened>

Assoc For Hashes

Ruby’s Hash class comes with a method, assoc, which is good for grabbing both the key and value from a hash. If the given key matches it returns a two element array with the key and value.

> stuff = {a: 1, b: 2, c: 3}
=> {a: 1, b: 2, c: 3}
> stuff.assoc(:c)
=> [:c, 3]

If a key is used that doesn’t exist in the hash, then it simply returns nil.

> {}.assoc(:c)
=> nil

Rake Only Lists Tasks With Descriptions

Rake describes the -T flag as

Display the tasks (matching optional PATTERN) with descriptions, then exit.

And rake -T does just exactly that. It lists all the tasks with descriptions. Any rake task that you define without a desc will not be included.

Consider the following rake task definitions

desc 'foobar does this and that'
task :foobar do
  puts 'this and that'
end

task :foobaz do
  puts 'not so much'
end

This is what I get when listing the rake tasks filtered by foo

$ rake -T foo
rake foobar  # foobar does this and that

The foobar task (which has a description) is listed, but foobaz is not.

A hack of sorts to get around this is to use the -P flag which will end up listing all tasks even if they do not have a description (rake -P | grep 'foo').

Next And Previous Floats

The Float class has two interesting methods for stepping forward or backwards through the numbers that can actually be represented by floats. This is handy since floats are not evenly spaced.

Use #next_float to go forward

> 2.0
=> 2.0
> _.next_float
=> 2.0000000000000004
> _.next_float
=> 2.000000000000001
> _.next_float
=> 2.0000000000000013
> _.next_float
=> 2.0000000000000018

Use #prev_float to go backwards

> 2.0
=> 2.0
> _.prev_float
=> 1.9999999999999998
> _.prev_float
=> 1.9999999999999996
> _.prev_float
=> 1.9999999999999993
> _.prev_float
=> 1.9999999999999991

I cannot think of any practical use cases, but it is fun to know they are there if you need them.

Double Splat To Merge Hashes

One way of merging two hashes is with #merge:

> h1 = {a: 1, b: 2}
=> {:a=>1, :b=>2}
> h2 = {c: 3, d: 4}
=> {:c=>3, :d=>4}
> h1.merge(h2)
=> {:a=>1, :b=>2, :c=>3, :d=>4}

You can also use double splats for a slightly more concise approach:

> h1 = {a: 1, b: 2}
=> {:a=>1, :b=>2}
> h2 = {c: 3, d: 4}
=> {:c=>3, :d=>4}
> {**h1, **h2}
=> {:a=>1, :b=>2, :c=>3, :d=>4}

This works particularly well when you want to expand an existing hash into a hash you are creating on the fly:

> h1 = {a: 1, b: 2}
=> {:a=>1, :b=>2}
> {c: 3, d: 4, **h1}
=> {:c=>3, :d=>4, :a=>1, :b=>2}

`undef_method` And The Inheritance Hierarchy

As the docs state, Ruby’s undef_method

prevents the current class from responding to calls to the named method.

This means you can do some weird things to the inheritance hierarchy. I’ll use the following code example to illustrate.

class Phone
  def ring
    puts 'brrrrriiing'
  end
end

class Smartphone < Phone
  def ring
    puts 'boop beep boop'
  end
end

class Iphone < Smartphone
end

smartphone = Smartphone.new
iphone = Iphone.new

smartphone.ring
#=> boop beep boop
iphone.ring
#=> boop beep boop

Everything works as expect. Now, I’ll use undef_method.

class Smartphone
  undef_method(:ring)
end

smartphone.ring
#=> NoMethodError: undefined method `ring' for #<Smartphone:0x007fd0a20b7960>
iphone.ring
#=> NoMethodError: undefined method `ring' for #<Iphone:0x007fd0a20b7938>

Not only have instances of Smartphone been prevented from responding to ring, but any subclasses of Smartphone that call ring will get tripped up when traversing the inheritance hierarchy in search of a definition of ring.

Editing Code In Pry

Pry provides an enhanced REPL experience for Ruby. One of the enhancements it provides is the ability to open your preferred editor within a pry session. This makes it easy to compose and edit multi-line blocks of code.

Try it out by typing edit within a pry session. Once you are ready, you can save the file which will prompt pry to interpret the contents of your file within the context of the pry session.

Listing Local Variables

In Ruby 2.2, the binding object gives us access to a method #local_variables which returns the symbol names of the binding’s local variables. We can see this in action with

def square(x)
  puts binding.local_variables.inspect
  x.times do |a|
    puts binding.local_variables.inspect
  end
  z = x * x
  puts binding.local_variables.inspect
  z
end
square(2)

which results in

[:x, :z]
[:a, :x, :z]
[:a, :x, :z]
[:x, :z]
=> 4

source

Question Mark Operator

Ruby has a question mark (?) operator that works like so

> ?a
=> "a"
> ?\s
=> " "
> ??
=> "?"
> ?a + ?b + ?c
=> "abc"

It essentially creates single character strings. At least in Ruby 1.9+ it does. In versions of Ruby before 1.9, the ? operator could be used to get the ascii character code of the operand character.

h/t Josh Davey

source

Percent Notation

Ruby has many uses for the % character. One of the more obscure uses is as a notion for custom delimited strings. Use the percent notation with a non-alphanumeric character to surround a string.

> %=Jurassic Park=
=> "Jurassic Park"
> % Ghostbusters 
=> "Ghostbusters"

It even works with balanced characters

> %(The Goonies)
=> "The Goonies"

This is useful for defining a string that has both types of quotes

> %[That'll be the "day"]
=> "That'll be the \"day\""

It’s also useful for creating horribly obfuscated code

> %=what===%?what?
=> true

h/t Josh Davey

FactoryGirl Sequences

FactoryGirl sequences are often used inline for unique values such as emails:

factory :user do
  sequence(:email) { |n| "person#{n}@example.com" }
end

However, a sequence can be defined on its own

FactoryGirl.define do
  sequence :email do |n|
    "person#{n}@example.com"
  end
end

That means it can be invoked outside the context of a factory

> FactoryGirl.generate :email
=> "person1@example.com"
> FactoryGirl.generate :email
=> "person2@example.com"

Or it can be used as a shared sequence across multiple factories

factory :customer do
  ...
  email
end

factory :admin do
  ...
  email
end