New Features in Ruby 2.4

By John Backus on July 20, 2016

Faster regular expressions with Regexp#match?

Ruby 2.4 adds a new #match? method for regular expressions which is three times faster than any Regexp method in Ruby 2.3:

Regexp#match?:  2630002.5 i/s
  Regexp#===:   872217.5 i/s - 3.02x slower
   Regexp#=~:   859713.0 i/s - 3.06x slower
Regexp#match:   539361.3 i/s - 4.88x slower
Expand benchmark source

When you call Regexp#===, Regexp#=~, or Regexp#match, Ruby sets the $~ global variable with the resulting MatchData:

/^foo (\w+)$/ =~ 'foo bar'      # => 0
$~                              # => #<MatchData "foo bar" 1:"bar">

/^foo (\w+)$/.match('foo baz')  # => #<MatchData "foo baz" 1:"baz">
$~                              # => #<MatchData "foo baz" 1:"baz">

/^foo (\w+)$/ === 'foo qux'     # => true
$~                              # => #<MatchData "foo qux" 1:"qux">

Regexp#match? returns a boolean and avoids building a MatchData object or updating global state:

/^foo (\w+)$/.match?('foo wow') # => true
$~                              # => nil

By skipping the global variable Ruby is able to avoid work allocating memory for the MatchData.

New #sum method for Enumerable

You can now call #sum on any Enumerable object:

[1, 1, 2, 3, 5, 8, 13, 21].sum # => 54

The #sum method has an optional parameter which defaults to 0. This value is the starting value of a summation meaning that [].sum is 0.

If you are calling #sum on an array of non-integers then you need to provide your own initial value:

class ShoppingList
  attr_reader :items

  def initialize(*items)
    @items = items

  def +(other)*items, *other.items)

eggs   ='eggs')          # => #<ShoppingList:0x007f952282e7b8 @items=["eggs"]>
milk   ='milks')         # => #<ShoppingList:0x007f952282ce68 @items=["milks"]>
cheese ='cheese')        # => #<ShoppingList:0x007f95228271e8 @items=["cheese"]>

eggs + milk + cheese                       # => #<ShoppingList:0x007f95228261d0 @items=["eggs", "milks", "cheese"]>
[eggs, milk, cheese].sum                   # => #<TypeError: ShoppingList can't be coerced into Integer>
[eggs, milk, cheese].sum( # => #<ShoppingList:0x007f9522824cb8 @items=["eggs", "milks", "cheese"]>

On the last line an empty shopping list ( is supplied as the initial value.

New methods for testing if directories or files are empty

In Ruby 2.4 you can test whether directories and files are empty using the File and Dir modules:

Dir.empty?('empty_directory')      # => true
Dir.empty?('directory_with_files') # => false

File.empty?('contains_text.txt')   # => false
File.empty?('empty.txt')           # => true

The File.empty? method is equivalent to which is already available in all supported Ruby versions:'contains_text.txt')  # => false'empty.txt')          # => true

Unfortunately these methods are not available for Pathname yet.

Extract named captures from Regexp match results

In Ruby 2.4 you can called #named_captures on a Regexp match result and get a hash containing your named capture groups and the data they extracted:

pattern  = /(?<first_name>John) (?<last_name>\w+)/
pattern.match('John Backus').named_captures # => { "first_name" => "John", "last_name" => "Backus" }

Ruby 2.4 also adds a #values_at method for extracting just the named captures which you care about:

pattern = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/
pattern.match('2016-02-01').values_at(:year, :month) # => ["2016", "02"]

The #values_at method also works for positional capture groups:

pattern = /(\d{4})-(\d{2})-(\d{2})$/
pattern.match('2016-07-18').values_at(1, 3) # => ["2016", "18"]

New Integer#digits method

If you want to access a digit in a certain position within an integer (from right to left) then you can use Integer#digits:

123.digits                  # => [3, 2, 1]
123.digits[0]               # => 3

# Equivalent behavior in Ruby 2.3: # => [3, 2, 1]

If you want to know positional digit information given a non-decimal base, you can pass in a different radix. For example, to lookup positional digit information for a hexadecimal integer you can pass in 16:

0x7b.digits(16)                                # => [11, 7]
0x7b.digits(16).map { |digit| digit.to_s(16) } # => ["b", "7"]

Improvements to the Logger interface

The Logger library in Ruby 2.3 can be a bit cumbersome to setup:

logger1 =
logger1.level    = :info
logger1.progname = 'LOG1'

logger1.debug('This is ignored')'This is logged')

# >> I, [2016-07-17T23:45:30.571508 #19837]  INFO -- LOG1: This is logged

Ruby 2.4 moves this configuration to Logger’s constructor:

logger2 =, level: :info, progname: 'LOG2')

logger2.debug('This is ignored')'This is logged')

# >> I, [2016-07-17T23:45:30.571556 #19837]  INFO -- LOG2: This is logged

Parse CLI options into a Hash

Parsing command line flags with OptionParser often involves a lot of boilerplate in order to compile the options down into a hash:

require 'optparse'
require 'optparse/date'
require 'optparse/uri'

config = {}

cli = do |options|
    options.define('--from=DATE', Date) do |from|
      config[:from] = from

    options.define('--url=ENDPOINT', URI) do |url|
      config[:url] = url

    options.define('--names=LIST', Array) do |names|
      config[:names] = names

Now you can provide a hash via the :into keyword argument when parsing arguments:

require 'optparse'
require 'optparse/date'
require 'optparse/uri'

cli = do |options|
    options.define '--from=DATE',    Date
    options.define '--url=ENDPOINT', URI
    options.define '--names=LIST',   Array

config = {}

args = %w[
  --from  2016-02-03
  --names John,Daniel,Delmer

cli.parse(args, into: config)

config.keys    # => [:from, :url, :names]
config[:from]  # => #<Date: 2016-02-03 ((2457422j,0s,0n),+0s,2299161j)>
config[:url]   # => #<URI::HTTPS>
config[:names] # => ["John", "Daniel", "Delmer"]

Faster Array#min and Array#max

In Ruby 2.4 the Array class defines its own #min and #max instance methods. This change dramatically speeds up the #min and #max methods on Array:

     Array#min:       35.1 i/s
Enumerable#min:       21.8 i/s - 1.61x slower
Expand benchmark source

Simplified integers

Until Ruby 2.4 you had to manage many numeric types:

# Find classes which subclass the base "Numeric" class:
numerics = ObjectSpace.each_object(Module).select { |mod| mod < Numeric }

# In Ruby 2.3:
numerics # => [Complex, Rational, Bignum, Float, Fixnum, Integer, BigDecimal]

# In Ruby 2.4:
numerics # => [Complex, Rational, Float, Integer, BigDecimal]

Now Fixnum and Bignum are implementation details that Ruby manages for you. This should help avoid subtle bugs like this:

def categorize_number(num)
  case num
  when Fixnum then 'fixed number!'
  when Float  then 'floating point!'

# In Ruby 2.3:
categorize_number(2)        # => "fixed number!"
categorize_number(2.0)      # => "floating point!"
categorize_number(2 ** 500) # => nil

# In Ruby 2.4:
categorize_number(2)        # => "fixed number!"
categorize_number(2.0)      # => "floating point!"
categorize_number(2 ** 500) # => "fixed number!"

If you have Bignum or Fixnum hardcoded in your source code that is fine. These constants now point to Integer:

Fixnum  # => Integer
Bignum  # => Integer
Integer # => Integer

New arguments supported for float modifiers

#round, #ceil, #floor, and #truncate now accept a precision argument

4.55.ceil(1)     # => 4.6
4.55.floor(1)    # => 4.5
4.55.truncate(1) # => 4.5
4.55.round(1)    # => 4.6

These methods all work the same on Integer as well:

4.ceil(1)        # => 4.0
4.floor(1)       # => 4.0
4.truncate(1)    # => 4.0
4.round(1)       # => 4.0

Case sensitivity for unicode characters

Consider the following sentence:

My name is JOHN. That is spelled J-Ο-H-N

Calling #downcase on this string in Ruby 2.3 produces this output:

my name is john. that is spelled J-Ο-H-N

This is because “J-Ο-H-N” in the string above is written with unicode characters.

Ruby’s letter casing methods now handle unicode properly:

sentence =  "\uff2a-\u039f-\uff28-\uff2e"
sentence                              # => "J-Ο-H-N"
sentence.downcase                     # => "j-ο-h-n"
sentence.downcase.capitalize          # => "J-ο-h-n"
sentence.downcase.capitalize.swapcase # => "j-Ο-H-N"

New option to specify size of a new string

When creating a string you can now define a :capacity option which will tell Ruby how much memory it should allocate for your string. This can help performance as Ruby can avoid reallocations as you increase the size of the string in question:

   With capacity:    37225.1 i/s
Without capacity:    16031.3 i/s - 2.32x slower
Expand benchmark source

Fixed matching behavior for symbols

Ruby 2.3’s Symbol#match returned the match position even though String#match returns MatchData. This inconsistency is fixed in Ruby 2.4:

# Ruby 2.3 behavior:

'foo bar'.match(/^foo (\w+)$/)  # => #<MatchData "foo bar" 1:"bar">
:'foo bar'.match(/^foo (\w+)$/) # => 0

# Ruby 2.4 behavior:

'foo bar'.match(/^foo (\w+)$/)  # => #<MatchData "foo bar" 1:"bar">
:'foo bar'.match(/^foo (\w+)$/) # => #<MatchData "foo bar" 1:"bar">

Multiple assignment inside of conditionals

You can now assign multiple variables within a conditional:

branch1 =
  if (foo, bar = %w[foo bar])

branch2 =
  if (foo, bar = nil)

branch1 # => "truthy"
branch2 # => "falsey"

You probably shouldn’t do that though.

Exception reporting improvements for threading

If you encounter an exception within a thread then Ruby defaults to silently swallowing up that error:

puts 'Starting some parallel work'

thread = do
    sleep 1

    fail 'something very bad happened!'

sleep 2

puts 'Done!'
$ ruby parallel-work.rb
Starting some parallel work

If you want to fail the entire process when an exception happens within a thread then you can use Thread.abort_on_exception = true. Adding this to the parallel-work.rb script above would change the output to:

$ ruby parallel-work.rb
Starting some parallel work
parallel-work.rb:9:in 'block in <main>': something very bad happened! (RuntimeError)

In Ruby 2.4 you now have a middle ground between errors being silently ignored and aborting your entire program. Instead of abort_on_exception you can set Thread.report_on_exception = true:

$ ruby parallel-work.rb
Starting some parallel work
#<Thread:0x007ffa628a62b8@parallel-work.rb:6 run> terminated with exception:
parallel-work.rb:9:in 'block in <main>': something very bad happened! (RuntimeError)

Hidden Complexity in Ruby Land

By John Backus on January 6, 2016

Ruby makes it easy to write concise code. This is a benefit of the language and the ecosystem. Matz focuses on “making programs succinct” and Rails boasts that it lets you build “in a matter of days” what used to take months.

Concise code can have a dark side. Convenient interfaces can tuck away complexity and side effects that might surprise you later. Brevity in software comes at the cost of diligence both from developers and reviewers. It is especially important to understand how your abstractions work and the business rules they implicitly handle.

Moving Fast

Imagine you are adding a new feature to your Ruby on Rails web application. This feature breaks down into three small tasks:

The current user JSON looks like this

  "status": "success",
  "data": {
    "name": {
      "first": "Edmond",
      "last": "O'Connell"
    "address": {
      "street1": "53236 Camilla Light",
      "street2": null,
      "city": "Pierceville",
      "state": "NJ",
      "country": "United States"

To integrate with the API you create three simple classes with ActiveModel::Model:

class User
  include ActiveModel::Model

  attr_accessor :address, :name

class Name
  include ActiveModel::Model

  attr_accessor :first, :last

class Address
  include ActiveModel::Model

  attr_accessor :street1, :street2, :city, :state, :country

To extract the user data you use the new #dig method introduced in Ruby 2.3:
  name:'data', 'name')),
  address:'data', 'address')))

Finally, you add a current_country view helper method and create a new view partial:

module UserHelper
  def current_country
    return 'Unknown' unless current_user
<div id="user-welcome">
  <% if current_user %>
    <span>Welcome back <%= %>!</span>
  <% end %>

  <div id="user-welcome-flag">
    <%= image_tag("/imgs/flags/#{current_country}.png") %>

Breaking Things

A few weeks pass and you find out that some pages rendered the message “Welcome back !” and a broken image in place of the flag. The internal API encountered its own error and returned

  "status": "error",
  "message": "Internal server error"

Oddly enough this did not break your code:

response = { 'status' => 'error', 'message' => 'Internal server error' }

name    = response.dig('data', 'name')    # => nil
address = response.dig('data', 'address') # => nil

user =, address:            # => #<Name:0x0011910412163>
user.address         # => #<Address:0x0011910412163>      # => nil # => nil

Feeling a bit embarrassed by the bug you reflect on how you could prevent similar issues in the future:

What if the internal API renames the country field to country_code? That would also silently break the view. Can I only avoid these cryptic bugs by being vigilant about every external dependency?


The features in Ruby and Rails which let you write concise code can also let you cut corners. Consider our Name class and how the corresponding response data was originally extracted:

class Name
  include ActiveModel::Model

  attr_accessor :first, :last

module ResponseHandler
  def self.extract_name(response)'data', 'name'))

Let’s rewrite Name without ActiveModel or attr_accessor:

class Name
  # Inlined from Active Model source
  def initialize(params={})
    params.each do |attr, value|
      self.public_send("#{attr}=", value)
    end if params


  def first

  def first=(first)
    @first = first

  def last

  def last=(last)
    @last = last

Imagining our code like this is instructive. It seems like three questions are now immediately obvious

Let’s throw out #dig and instead handle each edge case manually.

module ResponseHandler
  def self.extract_name(response)
    return unless response.key?('data')
    return if     response['data'].empty?['data']['name'])

Expanding this method highlights three distinct outcomes which are each important to consider. The original code properly handled a valid user object but overlooked two important edge cases:

1. API error handling when response['data'] is nil

return unless response.key?('data')

This happened when the internal API encountered an error. This condition should instead result in our application notifying the end user of an error.

2. Alternate behavior when a user is not returned

return if response['data'].empty?

This corresponds to the following JSON

  "status": "success",
  "data": {}

This might mean that the current user has not yet logged in. It could also be a buggy response.

Depending on how robust you expect the internal API to be you might want to handle this case independently as well. If this is invalid state then the response handler should raise an error. If it is valid state and you want to handle cases where the user is not logged in then there should be a separate Guest class independent of the User class.

Both of these options are better than implicitly assuming this condition never happens. Once the code embedding your assumption is deployed it is too easy to forget and unknowingly introduce a silent regression in the future.


Ruby certainly makes it easy to write concise code. The question then is how do you reap these benefits without cutting corners accidentally? At BlockScore we have a few practices which help us write better Ruby.

1. Strict and simple dependencies

Active Model’s initializer is permissive and this led to surprising behavior. Consider the benefit of a strict alternative like anima:

# Test cases
valid_arguments  = { first: 'John', last: 'Doe'                  }
missing_argument = { first: 'John'                               }
extra_argument   = { first: 'John', last: 'Doe', nickname: 'Jim' }

# With Active Model
class Name
  include ActiveModel::Model

  attr_accessor :first, :last
end  # => #<Name:0x0011910412163 @first="John", @last="Doe"> # => #<Name:0x0011910412163 @first="John">   # => NoMethodError: undefined method `nickname=`              # => #<Name:0x0011910412163>                   # => #<Name:0x0011910412163>

# With Anima
class Name
  include, :last)
end  # => #<Name first="John" last="Doe"> # => Anima::Error: Name attributes missing: [:last]   # => Anima::Error: Name attributes missing: [], unknown: [:nickname]              # => NoMethodError: undefined method `keys'                   # => ArgumentError: wrong number of arguments (given 0, expected 1)

2. Meticulous code review

An inconspicuous line of code like'data', 'name'))

can encode multiple important code paths. With Ruby it is especially important to visualize the equivalent “expanded” code.

3. Static analysis

Tools like reek and rubocop are great for learning how to write better code. Reek might point out a design issue before you notice it. Rubocop now goes way beyond style: the next release will include eight new cops for helping you catch bad performing code.

4. Mutation testing

Mutation testing helps me write better Ruby. It sniffs out dead code, helps me find missing tests, and generally helps me think about the assumptions I’ve made.

New Features in Ruby 2.3

By John Backus on November 13, 2015

Yesterday ruby 2.3-preview1 was released. This update brings several new additions to core classes in ruby as well as some new syntax. Here are a few of the new additions coming in ruby 2.3:

Extract values with Array#dig and Hash#dig

The new #dig instance methods provide concise syntax for accessing deeply nested data. For example:

user = {
  user: {
    address: {
      street1: '123 Main street'

user.dig(:user, :address, :street1) # => '123 Main street'

results = [[[1, 2, 3]]]

results.dig(0, 0, 0) # => 1

Both of these methods will return nil if any access attempt in the deeply nested structure returns nil:

user.dig(:user, :adddresss, :street1) # => nil
user.dig(:user, :address, :street2) # => nil

Grep out the inverse of a pattern with Enumerable#grep_v

This method is the inverse of the Enumerable#grep method. The grep method and its inverse provide several powerful ways to filter enumerables:

Filtering by regular expression

friends = %w[John Alain Jim Delmer]

j_friends = friends.grep(/^J/)   # => ["John", "Jim"]
others    = friends.grep_v(/^J/) # => ["Alain", "Delmer"]

Filtering by types

items = [1, 1.0, '1', nil]

nums   = items.grep(Numeric)   # => [1, 1.0]
others = items.grep_v(Numeric) # => ['1', nil]

Fetching multiple values with Hash#fetch_values

Sometimes Hash#fetch is a better choice than Hash#[] when you want to write more strict code. You can also access multiple values from a hash using Hash#values_at, but there wasn’t a strict equivalent to values_at until ruby 2.3:

values = {
  foo: 1,
  bar: 2,
  baz: 3,
  qux: 4

values.values_at(:foo, :bar)    # => [1, 2]
values.fetch_values(:foo, :bar) # => [1, 2]

values.values_at(:foo, :bar, :invalid)    # => [1, 2, nil]
values.fetch_values(:foo, :bar, :invalid) # => KeyError: key not found: :invalid

Positive and negative predicates for Numeric#positive? and Numeric#negative?

Numeric values now have predicate methods that check if the subject is positive or negative. This can be useful if you want to filter an enumerable:

numbers = (-5..5) # => [1, 2, 3, 4, 5] # => [-5, -4, -3, -2, -1]

Hash superset and subset operators Hash#<=, Hash#<, Hash#>=, and Hash#>

These methods lets you compare hashes to see if they are subsets or proper subsets of each other. For example:

small     = { a: 1                }
medium    = { a: 1, b: 2          }
large     = { a: 1, b: 2, c: 3    }
different = { totally: :different }

{ a: 1, b: 2 } > { a: 1 }             # => true
{ a: 1 } > { a: 1 }                   # => false
{ b: 1 } > { a: 1 }                   # => false
{ a: 1, b: 2 } < { a: 1, b: 2, c: 3 } # => true

Convert a hash to a proc with Hash#to_proc

Now you can use a hash to iterate over an enumerable object:

hash = { a: 1, b: 2, c: 3 }
keys = %i[a c d] # => [1, 3, nil]

Honestly, I can’t think of a use case for this yet.

Ruby 2.3 will introduce new syntax for accessing deeply nested objects safely without accidentally triggering a dreaded NoMethodError on nil. The syntax looks like this:

require 'ostruct'


where each instance of &. is similar to ActiveSupport’s Object#try method. Basically, if a nil value is encountered, then each method call will not be attempted and instead the nil value will be returned immediately.

Experimental frozen string pragma

You’ve probably heard that strings will be frozen by default in ruby 3. Ruby 2.3 lets you specify a pragma which enables this by default:

$ ruby -v
ruby 2.3.0preview1 (2015-11-11 trunk 52539) [x86_64-darwin14]
$ cat default.rb
# frozen_string_literal: false

puts "Hello world".reverse!
$ ruby default.rb
dlrow olleH
$ cat enabled.rb
# frozen_string_literal: true

puts "Hello world".reverse!
$ ruby enabled.rb
enabled.rb:3:in `reverse!': can't modify frozen String (RuntimeError)
  from enabled.rb:3:in `<main>'

Alternatively, you can also enable and disable this using the command line argument --enable=frozen-string-literal

Further reading

You can read about other new features, performance improvements, compatibility issues, and more here. Remember that this is still a preview of ruby 2.3 and some things might be subject to change.

How to write better code using mutation testing

By John Backus on October 29, 2015

Abstract syntax tree

When developers talk about “test coverage” they are typically talking about how many lines of code are executed by their test suite. This is a simple calculation: what percentage of our code was run by our tests? We don’t want to accidentally break our code later so having strong test coverage is important.

Mutation testing is not an alternative to line coverage. While line coverage asks “what percentage of our code is run by our tests,” mutation testing asks “what code can I change without breaking your tests?” Mutation testing tools answer this question by applying and testing small modifications to your application.

This post explores how asking “what changes don’t break my tests?” can benefit more than just test coverage. Using a ruby mutation testing tool called mutant, I’ll introduce and reflect on two separate code examples to demonstrate how mutation testing helps you improve both your tests and your code itself.

Mutant keeps your tests honest

Consider this script for looking up users who tweeted ‘“I really enjoy #pizza”’:

require 'twitter'

class Tweeters
  def recent
    query.first(3).map do |tweet|


  def query'"I really enjoy #pizza"')

  def api_client do |config|
      config.consumer_key        = ENV['TWITTER_CONSUMER_KEY']
      config.consumer_secret     = ENV['TWITTER_CONSUMER_SECRET']
      config.access_token        = ENV['TWITTER_ACCESS_TOKEN']
      config.access_token_secret = ENV['TWITTER_ACCESS_TOKEN_SECRET']

puts if __FILE__ == $0

To illustrate the difference between “line coverage” and “mutation coverage” consider this intentionally bad test:

require 'simplecov'

require 'tweeters'
require 'rspec'

RSpec.describe Tweeters do
  it 'returns results' do
    expect( be(nil)

Now if I run this test:

$ rspec -I. -rpizza_spec.rb

Finished in 0.94429 seconds (files took 1.38 seconds to load)
1 example, 0 failures

Coverage report generated for RSpec to /dev/coverage. 15 / 15 LOC (100.0%) covered.

My test passed with 100% coverage.

If I run this test again with mutant and instruct it to only mutate the recent instance method then I see the following summary:

Mutations:       36
Kills:           19
Coverage:        52.78%
See full output

This tells me that my recent method actually has 52.78% mutation coverage! This means that mutant found 36 ways it could change my method and only 19 of those changes resulted in my test failing.

Mutant shows me what my tests missed. For example, here are three of the nineteen mutations my tests did not catch:

 def recent
-  query.first(3).map do |tweet|
-    "@#{tweet.user.screen_name}"
-  end
+  self

 def recent
   query.first(3).map do |tweet|
-    "@#{tweet.user.screen_name}"
+    nil

 def recent
   query.first(3).map do |tweet|
-    "@#{tweet.user.screen_name}"
+    "@#{tweet.user}"

Again, the test for this script was intentionally bad, but the difference in results is important. All my test did was assert that my recent method did not return null. This assertion did technically exercise 100% of the code though so the line coverage tool is reporting 100% coverage. Mutant quickly showed me that it could make my method return self, [nil, nil, nil], and ['@#<Twitter::User:0x1>', '@#<Twitter::User:0x2>', '@#<Twitter::User:0x3>'] without breaking my tests.

The takeaway here is not that line coverage is bad. You can write good tests without mutant. Instead, think of mutation testing as an x-ray for your tests. Running mutant on new code can help you double check that your tests are covering everything you care about. Mutant can also be a powerful tool when conducting a code review. It is easy to see roughly which methods are tested, but it can be hard to spot what that original author might have overlooked.

Mutant helps you write more robust code

Imagine you are tasked with creating an endpoint in your company’s internal API which does two tasks:

A few hours later you write the following code

class UsersController < ApplicationController
  # Looks up GET param `user_id` and returns user
  # @return [User]
  # @api public
  def show
    render json:[:user_id].to_i)
  rescue UserFinder::RecordNotFound => error
    render json: { error: error.to_s }

  # Finds users created after date specified in GET param `after`
  # @return [Array<User>] list of users
  # @api public
  def created_after
    after = Date.parse(params[:after])
    render json:

Along with this code you write some unit tests for the different edge cases you expect your controller to handle:

$ rspec --format documentation users_controller_spec.rb

  returns a user when given a valid id
  renders JSON error when given an invalid id

  returns multiple users given an early date
  excludes users created before date and includes users after
  renders empty array when date is in the future

Finished in 0.00433 seconds (files took 0.23881 seconds to load)
5 examples, 0 failures

You deploy your new features and move on to your next task. Later, you find out that the front end team reported a bug in your API. Apparently every request they make returns

  "error": "Could not find User with 'id'=0"

That same day you find out that the marketing team thinks your “new users” endpoint doesn’t work either. Apparently they sometimes get empty results when they shouldn’t. You end up spending the day debugging for your co-workers and eventually figure out what they were doing wrong.

To the front end developer you explain

The API expects the parameter user_id but you specified id. My code ends up getting nil when it tries to get the user_id parameter which is coerced 0 which explains why you always got that error.

moving on to the marketing team you explain

You need to write your dates in the format "YYYY-MM-DD". The problem was when you were searching things like “last December” which ruby parses as December of this year.

What if we ran mutant on this code before shipping it? Running mutant on UsersController we see the following alive mutations:

 def created_after
-  after = Date.parse(params[:after])
+  after = Date.iso8601(params[:after])

 def created_after
-  after = Date.parse(params[:after])
+  after = Date.parse(params.fetch(:after))

 def show
-  render(json:[:user_id].to_i))
+  render(json:[:user_id])))
 rescue UserFinder::RecordNotFound => error
   render(json: { error: error.to_s })

 def show
-  render(json:[:user_id].to_i))
+  render(json:
 rescue UserFinder::RecordNotFound => error
   render(json: { error: error.to_s })

Mutant is helping me reduce the side effects that my application will permit. These four mutations eliminate subtle bugs which produce misleading errors and incorrect output.

1. Requiring parameters with Hash#fetch


In both actions before we used Hash#[] which implicitly returns nil if the specified key is not present. Hash#fetch on the other hand will raise an error if the specified key is not present. As a result, mutant makes me think about the use case where an implementer of the API does not provide an expected parameter.

2. Better type coercion with Kernel#Integer


In UsersController#show we called #to_i on our user_id parameter. This ended up coercing nil into 0 which made our final error message more confusing. #to_i will do its best to coerce any input, but this is often not what we want:

nil.to_i     # => 0
'hello'.to_i # => 0

Mutant replaces this with Kernel#Integer which is more strict:

Integer(nil)     # => TypeError: can't convert nil into Integer
Integer('hello') # => ArgumentError: invalid value for Integer(): "hello"

3. Rejecting invalid dates with Date.iso8601


In UsersController#created_after we called Date#parse which tries to parse any string it thinks could be a date. This sounds handy, but in practice it often can be a subtle source of bugs since all it really needs to see are two adjacent numbers or three letters which could be a month abbreviation:

# Seems useful!
Date.parse('May 1st 2015')      # => #<Date: 2015-05-01>
Date.parse('2015-05-01')        # => #<Date: 2015-05-01>

# Never mind
Date.parse('Maybe not a date')  # => #<Date: 2015-05-01>
Date.parse('I am 10 years old') # => #<Date: 2015-10-10>

Ruby has many more specific date parsing methods. In this case mutant found that iso8601 still works with the tests cases we specified:

# Actually useful!
Date.iso8601('2015-05-01')        # => #<Date: 2015-05-01>
Date.iso8601('May 1st 2015')      # => invalid date (ArgumentError)
Date.iso8601('Maybe not a date')  # => invalid date (ArgumentError)
Date.iso8601('I am 10 years old') # => invalid date (ArgumentError)

Each mutation was better fit for the use case in question. The replacement methods were more likely to throw errors when given unexpected input. Knowing this during the development cycle causes me to handle these edge cases since I don’t want an exception to go uncaught and produce an application error. Even if I do forget to cover one of these use cases though the alternative is still preferable: an exception is thrown in production instead of weird behavior silently degrading my app’s quality for months. I know about the error the first time a user triggers it instead of the first time a user complains.

Add mutant to your workflow

Mutant is a powerful tool for improving your code. At BlockScore we try to reach 100% mutation coverage before code is shipped to production. You don’t have to aim for 100% coverage though to start benefiting from tools like mutant. Simply running mutant against your codebase and seeing what it can change should help you better understand what tests you are missing and what code could be improved.

Words to avoid in your YC application

By Chris Morton on October 13, 2015

BlockScore in Y Combinator S14

I have been through YC twice, including with BlockScore, an identity verification and KYC compliance company from the Summer 2014 batch, and have informally helped many with their applications. A common thread among the applications is the use of words which detract from the meaning that people are trying to convey.

Words to avoid

Remember, the best YC application is one where an unrelated party can understand what you do and how well you have done it in the fewest words possible. The following words can detract from your message:

Buzzwords If the Silicon Valley show didn’t put you off of these words, nothing will. revolutionize, disrupt, synergy, innovate, groundbreaking, world-class, unique, advanced, cutting edge, exclusive, unique, advanced, superior, platform, leverage
Snake oil Even though YC now accepts companies where these words could be true, it’s best to try not to describe potential with trite terms. once in a lifetime, game changer, magic, best of breed, pioneering
Diluters In most cases there are better, more succinct words that could be used that are more specific to your situation. super, very, awesome, really, literally, basically, definitely, golden, amazing, honestly, obviously, great
Informal You can keep a light tone without resorting to informal language. lol, haha, btw, 😀
Offensive It can be easy to accidentally offend - do your best to remember your audience. Swearing probably isn’t justifiable. You can use your imagination!
Tropes Everyone has rockstar developers. Explain why your team is great in other words - these are meaningless! ninja, rockstar, guru
Distractors State your accomplishments and plans with confidence. These words only distract from your point. kind of, sort of, much, just

Make sure to do one final pass to remove any extraneous language. If it isn’t essential, remove it. Brevity and conciseness are more pleasing than wordiness. A good example was someone saying that they “started working towards launching a pilot beta.” The extra words made them sound tentative. I suggested they say “pilot planned for November.”

The same advice applies to your video too. Keep it simple and don’t go overboard; just be normal and follow the advice.

After you submit your application

YC will accelerate your journey but don’t let it be the arbiter of your future. Regardless of whether you get into YC, focus on metrics: user growth, revenue growth, and generating profit. I see many founders pause and then stumble after applying to YC. Don’t let that happen to you.

There is still time to apply

As Sam and PG have mentioned, it isn’t too late to apply. Some of the best YC companies are last minute applicants.

Good luck!

Additional resources

YC application

PG’s guide on how to apply to YC

Sam Altman’s AMA on HN

3 non-obvious ways to improve your YC application by Payable

Try BlockScore for freeReal-time identity verification and due diligence.

Why we open source our terms of service

By Alain Meier on October 9, 2015

Terms of service is on GitHub

Most people don’t read terms of service. For some products, it’s not a huge deal - but for ones like ours, it’s imperative that our customers understand what they’re agreeing to. It’s easy to obfuscate your terms of service and update it on a whim forcing your customers to manage their own copies of past terms and create their own red-lined comparisons.

We at BlockScore want to take a different approach to our public contracts. We believe that the burden of contractual clarity is on the seller, not the buyer, so we maintain all of our most important contracts, like our terms of service and privacy policy, in a version controlled repository on GitHub. Not only does this allow customers to track changes that occurred since they signed up, but it also gives them the ability to understand how and why our contracts have evolved to become what they are today.

Our industry, the identity information space, has very complex and stringent regulations. As a result, our contracts and those of our competitors can be difficult to keep track of. We hope that by putting our standard contract online in an easy to understand, versioned format we will be able to help our customers save money on legal overhead. When your customers better understand what you expect of them, they are also better able to comply with your requirements.

We don’t believe that our industry is unique. Many companies can benefit from having more open and transparent contracts. At its most basic level, version controlling your company’s terms of service requires very little work but pays dividends for your customers.

Plans for the future

At the moment, we work with our lawyer to draft new versions of our contracts and then upload the new version in one commit. In the future, we would like to be able to break each change down into its own individual commit affording us the ability to explain every change that occurs. Of course this requires more resources and time, so it will remain something to aspire to for now.

You can read the latest version of our terms on our website.

Try BlockScore for freeReal-time identity verification and due diligence.

New regulations for e-cigarette and vaping compliance under TX SB97

By Chris Morton on October 8, 2015

Vaping and e-cigarette age verification

Vaping and e-cigarettes have become popular and are starting to encounter similar regulation that has controlled tobacco sales. For instance, Texas passed TX SB97 to extend Health and Safety Code, Title 2, Subtitle H, 161.453 beyond tobacco to include vaping and e-cigarettes.

Companies that are either based in Texas or service Texas residents must now verify the age, date of birth, and address of purchasers starting October 1, 2015. While some sellers have temporarily suspended selling to Texas residents, BlockScore can quickly help you comply with this and similar regulations being enacted in other jurisdictions.

Here is the pertinent text from 161.453 referenced in TX SB97:

(a) A person may not mail or ship cigarettes in connection with a delivery sale order unless before mailing or shipping the cigarettes the person accepting the delivery sale order first:

(1) obtains from the prospective customer a certification that includes:

(A) reliable confirmation that the purchaser is at least 18 years of age; and

(B) a statement signed by the prospective purchaser in writing and under penalty of law:

(i) certifying the prospective purchaser’s address and date of birth;

(ii) confirming that the prospective purchaser understands that signing another person’s name to the certification is illegal, that sales of cigarettes to an individual under the age prescribed by Section 161.082 are illegal under state law, and that the purchase of cigarettes by an individual under that age is illegal under state law; and

(iii) confirming that the prospective purchaser wants to receive mailings from a tobacco company;

(2) makes a good faith effort to verify the information contained in the certification provided by the prospective purchaser under Subdivision against a commercially available database

BlockScore is the simplest way to comply with the requirement to verify age, birth date, and address using a commercially available database as stated above. In your checkout flow, you can collect the required information, submit it to BlockScore, and get a response back from BlockScore in under a second.

As with any compliance program, make sure that you check with your attorney and comply with the other provisions in TX SB97 and 161.453.

Try BlockScore for freeReal-time identity verification and due diligence.

Selecting an ID verification provider

By Chris Morton on March 11, 2015

Selecting an ID verification provider

There are many factors to selecting an ID verification provider. This post goes through the important points to consider.


The amount of time required to engage, negotiate, implement, and verify varies dramatically between providers. Here are the questions to ask.

The time between finding BlockScore and going live can be as short as one day. Legacy providers have rigid business processes that can take up to six months.


The cost of implementing, deploying, and operating an ID verification solution varies dramatically between solutions. The hidden costs of the solution can add up to be significantly more than anticipated. Here are some questions to ask.

BlockScore offers simple, transparent, inclusive pricing with no setup or monthly fees. See the BlockScore pricing page for more information.


The complexity and time to implement a solution varies dramatically between identity verification providers. Here are some questions to ask.

BlockScore provides freely available client libraries, documentation, and a production-equivalent test environment. When you are ready for live access, submit a request and usually get approved within one day. If you only need occasional verifications, our dashboard has a simple graphical interface to perform verifications with zero programming required.

Remaining in compliance

Verifying someone’s identity is the first step, but how do you ensure that customers do not show up on any watchlists now and in the future? Here are the questions to ask.

BlockScore provides a comprehensive watchlist scanning service for US and international watchlists. The service performs initial scans and perpetual rescans at designated intervals to ensure that your business remains in compliance.


As your business expands internationally, you need an ID verification provider that covers the countries in which you expand. Here are the questions to ask.

BlockScore covers many countries throughout the world and never charges for international verifications where no data is available.


Upfront, transparent pricing

Freely available documentation

Simple contract terms

Comprehensive coverage

Try BlockScore for freeReal-time identity verification and due diligence.

New dashboard now available

By Alain Meier on January 14, 2015

For the past few months, we have been working on an improved dashboard experience. All BlockScore businesses will now see it once they login. Though there are dozens of improvements, here are some highlights:

New dashboard homepage

One of our most requested features, search, is now available on the top bar of every page. You can now search universally for all people, companies and candidates and then drill down into specific results using the sidebar.

We have also added the ability to search past results directly using the API. You can read more about how to do that in our documentation.

Brand new interface

The new dashboard now shares the same look and feel as the rest of the BlockScore systems. It is now much easier to find what you are looking for, and we have vastly improved the signup experience and applying for live access. Common actions like verifying new people can now be done right from the dashboard homepage.

Manage candidates

Our comprehensive watchlist scanning system, Candidates, is now accessible from the dashboard. View your searches and any watchlist hits that may have occurred.

Address autocomplete

We have made using the dashboard to verify users easier than ever before by automatically filling in country subdivisions (like states, provinces and cantons) as well as cities once you enter a postal code.

Activity feed

The new dashboard homepage includes an activity feed that helps you stay on top of what is happening in your business.

Support for international documents

The person verification forms now supports all of the forms of documentation that we support on our API.

Comprehensive verification details

After verifying a person or company, we now display all of the details regarding the verification results as well as icons to indicate whether this response is good, bad or neutral.

We hope you enjoy the improvements. If you have any feedback, please message us at There is a lot more to come in the following weeks!

Try BlockScore for freeReal-time identity verification and due diligence.

Using BlockScore in an app

By Chris Morton on December 8, 2014

BlockScore can be easily implemented in apps. As with any good system design, there are some important points to ensure user data is protected. This post goes through the basics of how to use BlockScore ID verification in an app.

The first step is to design a form to collect the required identity information from your user in your app. From that form, identity information needs to be sent to your server. Always use encrypted channels to communicate between your app, server, and external service providers such as BlockScore. Never store identity information in the app. We also recommend not storing personally identifiable information (PII) on your server because BlockScore can safely store it for you.

The next step is to send the identity information from your server to BlockScore using either our RESTful HTTP API or a client library for your server platform. Many client libraries are available on the BlockScore Github repository. Within a second of sending the information from your server to BlockScore, you will receive a response with valid/invalid, details about the matching pieces of information, and a token to access information about that verification in the future. As mentioned, in lieu of storing the identity information on your server, this token can be used to retrieve identity information from BlockScore.

Once BlockScore has responded with a valid status to your server, store the token in the user’s record. If an invalid status is returned, you may permit the user to retry the verification. We recommend that you limit the number of times the user may retry the verification. A common rate is two verifications per 24 hour period.

BlockScore provides an API key to communicate with our web service. All requests must including this API key. Because this key is also used to retrieve past verification information, it should never be used outside of your server. Never use or store your BlockScore API key on your app.

Optionally, you may request a question set to ensure the person submitting the identity information is the owner of the identity. See BlockScore documentation on implementing question sets.

For app developers with little server development experience, services like Parse provide an easy way to run the necessary server software to support your apps.

Try BlockScore for freeReal-time identity verification and due diligence.
Older articles ›