Skip to main content

Benjamin Oakes

Photo of Ben Oakes

Hi, I'm Ben Oakes and this is my geek blog. Currently, I'm a Ruby/JavaScript Developer at Liaison. Previously, I was a Developer at Continuity and Hedgeye, a Research Assistant in the Early Social Cognition Lab at Yale University and a student at the University of Iowa. I also organize TechCorridor.io, ICRuby, OpenHack Iowa City, and previously organized NewHaven.rb. I have an amazing wife named Danielle Oakes.

Filtering for the API category. Clear

Explanation of the Shadow DOM and Web Components

by Ben

Explanation of the Shadow DOM and Web Components – YouTube.

Today I Learned: You can unlink a file and still use it

by Ben

Unlink after creation

On POSIX systems, it’s possible to unlink a file right after creating it, and before closing it. This removes the filesystem entry without closing the file handle, so it ensures that only the processes that already had the file handle open can access the file’s contents. It’s strongly recommended that you do this if you do not want any other processes to be able to read from or write to the Tempfile, and you do not need to know the Tempfile’s filename either.

From Ruby’s Tempfile documentation. In Ruby/POSIX parlance, unlink means delete, so this was surprising to me.

All about to_h in Ruby 2.0

by Ben

I gave a talk at ICRuby today about Ruby 2.0, partially as a learning experience for myself. I hadn’t done much with Ruby 2.0 before, and I had fun learning more about what to expect. If you’d like to see what I presented, my slides are available.

A lot of what I showed about Ruby 2.0 was a pretty standard overview, but I paid special attention to to_h. I ended up doing some research that I haven’t seen written up elsewhere, and thought I should share it as a blog post as well.

What’s to_h?

It’s a new convention for retrieving a Hash representation of an object. When I was first learning Ruby in 2008, I remember expecting to_h to exist after learning about to_s for String and to_a for Array. In concept, it’s similar to serializable_hash in Rails as well. I’m happy to see this become a part of core Ruby.

What can I do with it?

Now that there’s an official method for getting the “Hash version” of an object, you can start to use it in your methods when using a Hash makes things easier, or you’d like to duck type.

Since to_h is now a part of Ruby’s core and std-lib, I thought I’d see how it’s used.

A quick word about the examples: we tend to use panda and bamboo as metasyntactic variables at Continuity Control, partially because of the great Jonathan Magen. Plus, they’re fun compared to plain old foo and bar.

Core

Searching ruby-doc.org core gave:

…and a handful of aliases called to_hash, which were also present in 1.9.

Here’s what they do:

ENV.to_h                 # => {"TERM"=>"xterm", "SHELL"=>"/bin/bash", ...}
{ panda: 'bamboo' }.to_h # => {:panda=>"bamboo"}
nil.to_h                 # => {}

s = Struct.new(:panda, :bamboo).new
s.to_h                   # => {:panda=>nil, :bamboo=>nil}

Std-lib

Searching ruby-doc.org std-lib gave:

I don’t have any examples for the latter 3, but OpenStruct#to_h is easy to demonstrate:

require 'ostruct'
os = OpenStruct.new(panda: 'bamboo')
os      # => #<OpenStruct panda="bamboo">
os.to_h # => {:panda=>"bamboo"}

Any gotchas?

Not everything about to_h works the way I’d expect.

Arrays

This doesn’t work:

%w(panda bamboo).to_h # => NoMethodError: undefined method `to_h'

I might have expected behavior like this:

Hash['panda', 'bamboo'] # => {"panda"=>"bamboo"}

That would be especially nice, since then you could convert back and forth from Array to Hash:

{ panda: 'bamboo' }.to_a.to_h # => NoMethodError: undefined method `to_h'

…but alas, that’s just not how it works. However, we can try to convince matz otherwise.

Something I found by accident: I screwed up Hash[] the first time and got a bunch of new warnings on STDERR.

Hash[['panda', 'bamboo']]
# (irb):5: warning: wrong element type String at 0 (expected array)
# (irb):5: warning: ignoring wrong elements is deprecated, remove them explicitly
# (irb):5: warning: this causes ArgumentError in the next release

In Ruby 1.9.3, it would print no warnings and simply return {}.

JSON

I also was hoping JSON would take advantage of to_h, since it’s now a part of Ruby’s stdlib.

require 'json'
JSON.generate(ENV)
# /usr/local/lib/ruby/2.0.0/json/common.rb:223:in `generate': only generation of JSON objects or arrays allowed (JSON::GeneratorError)
# from /usr/local/lib/ruby/2.0.0/json/common.rb:223:in `generate'
# from tmp/talk_code.rb:3:in `<main>'

I would have expected something like this:

require 'json'
# NOTE: This doesn't actually work this way.  Blog skimmers take notice!
JSON.generate(ENV) # => "{\"TERM\":\"xterm\",\"SHELL\": ...

Fortunately, you can do this:

require 'json'
JSON.generate(ENV.to_h) # => "{\"TERM\":\"xterm\",\"SHELL\": ...

…but that feels like an excellent use of to_h that should have been a part of JSON.

Enough complaining! Show something useful.

Duck typing is probably the most useful use case I can think of. It’s a good alternative to Hash[] in some cases as well.

to_h

Here’s a simple example. Let’s say I have a method called eat:

def eat(diet)
  "A panda eats #{ diet[:eats] }"
end

…but I want to make sure the diet that is passed in is treated like a Hash. That’s possible now:

def eat(diet)
  "A panda eats #{ diet.to_h[:eats] }"
end

# It works with a Hash
panda_diet = { eats: 'bamboo' }
eat(panda_diet) # => "A panda eats bamboo"

# ...a Struct
panda_diet = Struct.new(:eats).new('shoots and leaves')
eat(panda_diet) # => "A panda eats shoots and leaves"

# ...or even nil
eat(nil) # => "A panda eats "

Hash()

One other addition I noticed (but haven’t seen mentioned elsewhere) is the new Hash() method. It’s kind of like Array() or String() in Ruby 1.9.3 and below. These methods let you coerce values, in a sense.

Here’s an example using Array:

def eat_up(foods)
  # Turns anything into an `Array`:
  #
  #     nil        => []
  #     'bamboo'   => ['bamboo']
  #     ['bamboo'] => ['bamboo']
  #
  Array(foods).each do |food|
    puts eat(eats: food)
  end
end

eat_up(nil)
# [no output]
eat_up('bamboo')
# A panda eats bamboo
eat_up(['bamboo', 'shoots and leaves'])
# A panda eats bamboo
# A panda eats shoots and leaves

That’s actually very useful behavior; a lot of annoying type and error checking just goes away. Ever since I first saw Avdi Grimm present it, I’ve found many uses for it.

The good news is, you can now do something similar with Hash()

def eat(diet)
  diet = Hash(diet)
  "A panda eats #{ diet[:eats] }"
end

panda_diet = { eats: 'bamboo' }
eat(panda_diet) # => "A panda eats bamboo"
eat(nil) # => "A panda eats "

If used in the right situation, that might just be as useful as Array().

But strangely enough, Hash() doesn’t work exactly like to_h:

Hash([]) # => {}

Hash(OpenStruct.new)
# TypeError: can't convert OpenStruct into Hash
#     from (irb):100:in `Hash'
#     from (irb):100
#     from /usr/local/bin/irb:12:in `<main>'

I don’t currently have an explanation, but unless you need specific behavior from Hash(), you may prefer to use to_h.

Slightly less contrived examples

Flexible constructor

If you have a use case for it, to_h could make constructors more flexible:

class Panda
  def initialize(params)
    params = params.to_h

    @name = params[:name]
    @age = params[:age]
    @weight = params[:weight]
  end
end

Flexible constructor with OpenStruct

Or even use an OpenStruct instead, if you’d like:

require 'ostruct'

class Panda
  def initialize(params)
    params = OpenStruct.new(params.to_h)

    @name = params.name
    @age = params.age
    @weight = params.weight
  end
end

OpenStruct conversion

If you felt like it, you could even refactor that into this:

require 'ostruct'

# Convert to an `OpenStruct`
def OpenStruct(hash_like)
  OpenStruct.new(hash_like.to_h)
end

env = OpenStruct(ENV)
env.TERM # => 'xterm'

Reusable to_h definition

You could even parameterize how to define to_h:

# Related to my concept of `to_h` back in 2010: https://github.com/benjaminoakes/snippets/blob/master/ruby/to_h.rb
module ConversionHelper
  def pick(*methods)
    h = {}
    methods.each { |m| h[m] = send(m) }
    h
  end
end

class Panda
  include ConversionHelper

  attr_reader :name, :age

  def initialize(params)
    params = OpenStruct.new(params.to_h)

    @name = params.name
    @age = params.age
    @weight = params.weight
  end

  def to_h
    # Pandas are sensitive about their weight, after all...
    pick(:name, :age)
  end
end

I haven’t decided whether the last few ideas would actually be useful in practice, but these are the types of things that Hash() and to_h open up for Rubyists.

VRAPI2.NO_EMAIL_OR_POSTAL_ADDRESS_PROVIDED

by Ben

I ran into an error with the VerticalResponse API today, and to my surprise there were no results when searching on Google, Bing, or DuckDuckGo. Not even in the VerticalResponse documentation!

Your search - VRAPI2.NO_EMAIL_OR_POSTAL_ADDRESS_PROVIDED - did not match any documents.

The error was:

A general API error occurred: "VRAPI2.NO_EMAIL_OR_POSTAL_ADDRESS_PROVIDED" - "no email or postal address was provided, but at least one is required"

I tracked it down to a call to editListMember, which I guessed didn’t include the email_address in member_data. After adding it, the error message has gone away.

At any rate, there will now be a result if someone else searches for the error message. :)

Is there a boolean literal in SQLite?

by Ben

From my question on StackOverflow (CC BY-SA 3.0):

I know about the boolean column type, but is there a boolean literal in SQLite? In other languages, this might be true or false. Obviously, I can use 0 and 1, but I tend to avoid so-called “magic numbers” where possible.

From this list, it seems like it might exist in other SQL implementations, but not SQLite. (I’m using SQLite 3.6.10, for what it’s worth.)

Constants in MATLAB

by Ben

From my question on StackOverflow (CC BY-SA 3.0):

I’ve come into ownership of a bunch of Matlab code and have noticed a bunch of “magic numbers” scattered about the code. Typically, I like to make those constants in languages like C, Ruby, PHP, etc. When googling this problem, I found that the “official” way of having constants is to define functions that return the constant value. Seems kludgey, especially because Matlab can be finicky when allowing more than one function per file.

Is this really the best option?

I’m tempted to use / make something like the C Preprocessor to do this for me. (I found that something called mpp was made by someone else in a similar predicament, but it looks abandoned. The code doesn’t compile, and I’m not sure if it would meet my needs.)