-
Ruby Protip: Build objects using each_with_object
January 20, 2011 by kfaustino comments
In Ruby 1.9, a class that includes Enumerable will inherit a method called
each_with_object. This method allows you to iterate a given block for each element with an object you specify. Once the iteration is complete,each_with_objectwill return the object you passed into it.We can save ourselves one line of code by using
each_with_objectoverinjectwhen building enumerable objects such as a hash. This is becauseeach_with_objectdoes not require the object we are building to be explicitly returned at the end of the provided block. This does not mean theinjectmethod shouldn’t be used. When you need to perform calculations on a collection of items and would like to return the result, such as a sum,injectis perfect.Example: Creating a hash of HTML status codes from an Array
-
Ruby ProTip: meta-programming with eval’s other other parameters
January 5, 2011 by nickmulder comments
Lets ignore the good vs evil side of eval and focus on making the times you do use it better.
Consider the following class:
Although this is a contrived example, using method missing to create dynamic methods is a somewhat common patter in ruby land. This Foo class will create methods on demand if they happen to be standard US metasyntactic variables.
Given this Foo class living in foo.rb we can do this in irb:
Lets quickly review this output for those of us who are not meta-programming veterans. We create an instance of our Foo class and store it in a local variable, foo. We then call the method bar, it doesn’t exist so method_missing creates it for us. (Note the puts line in the code and output.) The second call to foo.bar simply returns the string since the method exits as it was created during the first call to bar by method_missing. Same is true with the baz method call. Hopefully it’s clear why foo.asdf raised a method missing exception…
What happens if we had made a mistake in our dynamically created method?
Notice the typo ‘emd’ on line 11. Here is the error and stack trace we get if we had tried to use this class with the typo:
The first line ‘SyntaxError: (eval):3’ isn’t very helpful at all. With this small example it is easy enough to figure out where the syntax error is coming from, but if you where trying to debug a dynamic block of code that was created in some other random file/class and passed around to be executed somewhere else it could be a little hard to track down where the bug originated.
If you check out the ruby docs you will find most versions (if not all) of eval take a few optional parameters. These optional parameters are a file name and a line number. They serve as a reference point for the stack trace when an error happens inside of the eval. Here is our foo example with the optional parameters passed into the eval:
__FILE__ returns the name of the file it is being called from, and __LINE__ returns the line number it is being called from. The line parameter should be the first line of the eval’d code, thus the + 1. The syntax with the «-EOM is a little strange, it simply is a place holder for the here document that follows.
Here is the output of the updated foo.rb file:
Now the stack trace in the error message points us straight to our problem.
If you use evals, use the __FILE__, __LINE__ + 1 parameters.
-
Introduction to BDD
October 28, 2010 by nickmulder comments
What is BDD“BDD focuses on obtaining a clear understanding of desired software behaviour through discussion with stakeholders. It extends TDD by writing test cases in a natural language that non-programmers can read. Behavior-driven developers use their native language in combination with the ubiquitous language of domain driven design to describe the purpose and benefit of their code. This allows the developers to focus on why the code should be created, rather than the technical details, and minimizes translation between the technical language in which the code is written and the domain language spoken by the business, users, stakeholders, project management, etc.” — Wikipedia
For history on BDD check out Dan North’s blog post Introducting BDD.
Rails 3 & BDD
Lets setup a sandbox app to play with:
The -T tells rails to create the project without TestUnit.
Lets add some gems to the Gemfile:
There are probably newer versions of Rails, Rspec-Rails and Remarkable out there, so check out the github repo to make sure you are using the latest versions.
Now that we have our Gemfile lets install some gems with bundler:
Assuming everything went well we can install rspec into our rails project with:
This will setup a /spec directory in your project with a spec_helper.rb file which sets up the environment for running specs. It will also create a autotest directory with a discover.rb file which helps the autotest tool decide which files to reload.
You can test the setup by running the following:
Rake spec is the bit we are interested in. Currently we don’t have any specs but at least we know its all running properly.
I recommend installing a few extra gems to better the BDD experience. Colored is a gem which will get some nice red/green/yellow colours going in your terminal window. Autotest is a great tool that will continually run your specs for you as you edit your code. The autotest/discovery.rb file will make help autotest to rerun the specs for the files you edit in your rails project. You can also install autotest-growl if you have growl installed. After installing the gems you have to add two files to your home directory .autotest and .rspec.
Here is the command to install the gems, and the contents of the two files you should create in your home directory:
Our First Spec
Lets create our first spec. You can name it what ever you like, but make sure it ends with _spec.rb. Add the file to your spec directory and copy the following into it:
This example isn’t very interesting, but it should already run; You can start up ‘autotest’ or run ‘rake spec’ to see the example run. You should see output similar to this:
Rspec/BDD has this great concept of ‘Pending’ examples. The idea is when you start out to write a new feature you start by writing all the requirements for the feature as pending examples. Once you get into this workflow the pending examples work as a todo list and helps to keep you on track to implementing that new feature.
To implement a pending example simply give it a block:
This example still isn’t very interesting, but it is at least an example now. Autotest or ‘rake spec’ should now be showing you something like this:
You should also have seen some green ‘love’ if you are running autotest with growl.
RSpec Expectations
Inside of your examples you simply state expectations. IE. The output of this method call should equal this string, or this array should have n items.
As it says our second example “should do something”. BDD uses this kind of language to be descriptive as well to help the example to stay on task. Our second example is doing something with the should method. Rspec has two very simple methods that we can call on any object to state our expectations. They are should and should_not.
Here is a second example for our spec which shows them in action:
Our first expectation in this example says “an empty strings class should be String”. Our second expectation says “an empty strings class should not be Integer”. Running this we should get a green (passing) example.
RSpec Matchers
These Expectations, should and should_not are useless with out Matchers. The power of RSpec is in its matchers. We have already seen the simplest matcher in the arsenal, ==. The == matcher simple ensures the left side of the expectation is equal to the right side. If it is equal you get a pass, if it is not equal you get a failure. == can be used with either should or should_not. Avoid using != use ‘should_not ==’ instead.
There are many more Matchers that come with RSpec, and you can always add your own. Here are just some of the simpler Matchers:
There is plenty of info on these and all the other standard Matchers in RSpecs Docs. Most of these do exactly what you would expect them to. Lets create a few other examples to take them for a test drive:
Running all these examples we should see the following output:
Notice we have this nice nested structure. This came from the —pretty option we put in our .rspec file in the home directory. In addition to testing out the Matchers we also used another concept in RSpec. context is a great way to group together related examples.
If these Matchers are all new this is a great time to play around in this spec and see what some of the other ones do. If things are not working as expected just go back to the docs and try to figure out where things went wrong. If you have questions hop on IRC and drop us a line in the #torontoruby channel.
This is the first in a series of posts on the topic of BDD. Next up we will be implementing a simple model BDD style.
This post is a summary of a talk given at TorontoRB on BDD.
-
Toronto Life Cover
October 21, 2010 by jeffbrenner comments
It’s been an exciting month for Nulayer.We announced a partnership with Score Media, we moved into an incredible new office space, and to top it all off, Peter and I were featured on the cover of November issue of Toronto Life.
We’re honoured to be in this article alongside several really great Toronto tech companies. Many of the entrepreneurs and companies in the article have experienced great success, and being among them inspires our whole team to keep pushing forward and challenging ourselves.
What excites us about this story is its suggestion that these companies are turning Toronto into the next Silicon Valley. While I’m not a huge fan of being compared to the juggernaut that is the Valley, I couldn’t agree more that Toronto is turning into a technology hotbed. Being immersed in the community, I can’t help but notice the great energy and confidence that is flowing. I believe Toronto will emerge as a leader in fostering great start ups over the next three years. I know that our entire team is proud and determined to make sure Nulayer is going to be one of the companies leading this charge.
We’d also like to extend a big thanks to Daniel Ehrenworth, the talented photographer who snapped this amazing picture of us. Also, just to clarify, I’m not taller than Peter. I’m mid jump in the pic.
