I recently read a blurgh post about the interesting, quirky aspects of lambdas in Ruby.
One feature that stood out to me was lambdas’ ability to stand in where hashes would normally be used.
This functionality is made possible because, in Ruby, lambdas can be called in any of the following ways:
1 2 3 4 5
The third way is the bridge between lambdas and the concept of “computed hashes”. I searched for a definition of computed hash, but didn’t find much consensus. The working definition for this post would be something like:
A hash object whose values can be initialized (read: computed) at runtime based on logic declared elsewhere in the program.
Putting It Together: An Example
When might the use of computed hashes, i.e. lambdas, be a favorable replacement to a normal hash?
Let’s say you’re writing tests for your program and you want to add a degree of “fuzz testing”. As an example, perhaps one of your classes is initialized with
last_name attributes (note the
initialize method expects to receive a
Hash-like argument as input in sticking with Rails convention), and then generates a
slug to be used for query string parameters elsewhere in your application:
1 2 3 4 5 6 7 8 9 10 11 12
Now let’s generate an instance of the
Person class to make sure everything looks OK:
1 2 3 4
This checks out. Our
slug method is pretty dumb, but let’s say it becomes more complex: we amend
slug to handle duplicates. As it stands, “Arthur MacCormack” and “Art MacNulty” will have the same slug and so are not uniquely identifiable by their slug.
The point of interest here is NOT the logic you end up implementing to make
slug more unique. What’s of interest is how you can fuzz test whatever logic you end up implementing throughout your test suite.
Faker + Computed Hash = Fuzz Testing
Faker is a great library for generating random data, which I most typically use in conjunction with FactoryGirl to generate instances of my models (that is, the Ruby classes that represent the domain I’m modelling in the application).
Let’s see how we can utilize a computed hash to improve the degree of fuzz testing in my unit tests:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
1 2 3
And, voilà, we can initialize
Person instances using our
randomizer (which is in fact a lambda, and not a hash):
1 2 3 4 5 6 7 8
Need to generate pseudo-random instances of your classes in order to utilize fuzz testing across your test suite? Try initializing your instances using a computed hash, which in Ruby can be implemented using a lambda and
call-ing it using the hash accessor
Hash# that you’re used to seeing.