Episode #469 - June 3rd, 2014

Posted about 1 month back at Ruby5

This week we talk about the brand new RSpec 3 and Git 2, but also how to use bower-rails instead of JavaScript gems, JSON responses with PostgreSQL, and the quirks of Ruby serialization & enumeration.

Listen to this episode on Ruby5

Sponsored by Codeship

Codeship is a hosted Continuous Deployment Service that just works. Set up Continuous Integration in a few steps and automatically deploy when all your tests have passed. Codeship has great support for lots of languages and test frameworks. It integrates with GitHub and BitBucket. You can start with their free plan. Setup only takes 1 minute. You can find them on codeship.io/ruby5 and remember check out their great blog.
Codeship

RSpec 3

Whether you test-drive or not, you should be excited about the release of RSpec 3 yesterday. Myron Marston — the project maintainer — wrote a humongous and deliciously detailed blog post about all these Notable Changes. First, RSpec 3.0 adds better support for Ruby 2.0 features like keyword arguments and Module prepending. That said they dropped Ruby 1.8.6 and 1.9.1 support, but at this point who cares. The RSpec team provided version 2.99 which will output deprecation warnings for anything that changes in RSpec 3.0. It’s pretty great and if you’re worried that your build logs will be littered with deprecations, you can configure RSpec to dump those warnings into a separate file. before(:each) has been aliased to before(:example) and before(:all) to before(:context) in order to make the scope of those hooks more explicit. Every method in the RSpec DSL now yields the RSpec example object instead of exposing an `example` method that could interfere with your own specs. This version also brings an eagerly awaited Zero Monkey Patching mode which should silence one of the biggest criticisms of RSpec: that it monkey patched the Object class with tons of RSpec-specific methods. You can now use expect(object).to equal something, which to me reads quite well and allows for cleaner specs because it makes the expectation part of an example painfully obvious. Zero monkey patching also extends to rspec-mocks, so you now allow(object).to receive(:methodname).and_return(value). Same thing for stubs. You can even expose the RSpec DSL globally in order to avoid monkey patching Ruby’s `main` and Module to call the describe method for example.
RSpec 3

Git 2.0.0

Felipe Contreras, took the time to decipher the Git developers’ cryptic prose to figure out what changed in Git 2.0.0 and why you should care. Instead of pushing all branches that exist locally and on your remote, Git now defaults to “simple” pushing by only dealing with the branch currently checked out. `git add` now defaults to also staging removed files so no need to add the uppercase `A` flag to force it to add all changes. `git add` with no arguments also has more predictable behavior now and will add anything that was modified within the repo.
Git 2.0.0

bower-rails

In the JavaScript world, Bower seems to be the prefered package manager so why not use Bower inside your Rails app instead? This is something the bower-rails gem let’s you do. If you’re not a fan of JSON you can use bower-rails’ own Ruby DSL which even allows you to use the familiar group method from Bundler’s Gemfile. Oh, and just like Bundler, you can declare dependencies stored on Bower’s repository, any public Git repository, or even with a simple GitHub user/repo format. The gem comes with a bunch of rake tasks that allow you to: install, update, and list dependencies as you need to.
bower-rails

Avoid Rails when Generating JSON responses with PostgreSQL

In “Avoid Rails when generating JSON responses with Postgres” Dan McClain shows you all the steps that Rails has to typically go through to get data from Postgres and into your custom JSON format. Then he shows you how to craft a huge Postgres query that will generate pure JSON much quicker than Rails. Dan also created a new PostgresEXT-Serializers gem. This gem monkey patches ActiveModel Serializers and then everytime you try to serialize an ActiveRecord Relation it will take over and push the work down to Postgres. Only caveat is this is a VERY new library, so use with caution.
Avoid Rails when Generating JSON responses with PostgreSQL

Ruby Serialization & Enumeration

It was refreshing to see Xavier Shay from the Square team write about dealing with a weird serialization error with ActiveSupport. In the blog post titled Ruby Serialization & Enumeration, he praises the transparency of Ruby’s libraries, mentions how easy it is to pry them open, jump inside and twiddle stuff around to figure out what’s going wrong. co: Yeah, if you’re never used debugger or pry to jump inside of some of the gems that you use every day, this post shows how useful it can be. That, and it forces you to read more code written by other potentially more skilled developers.
Ruby Serialization & Enumeration

Sponsored by Top Ruby Jobs

If you're looking for a top Ruby job or for top Ruby talent, then you should check out Top Ruby Jobs. Top Ruby Jobs is a website dedicated to the best jobs available in the Ruby community.
Top Ruby Jobs

Sponsored by Ruby5

Ruby5 is released Tuesday and Friday mornings. To stay informed about and active with this podcast, we encourage you to do one of the following:

Thank You for Listening to Ruby5

Episode #468 - May 30th, 2014

Posted 2 months back at Ruby5

Understanding the magic of routes in Rails, a simple rest-client, using PostGIS with Google Maps, setting up SSL with the latest toys, an examination of Rails vs. Sinatra, and how to get your developers blogging all in this episode of the Ruby5!

Listen to this episode on Ruby5

Sponsored by New Relic

New Relic is _the_ all-in-one web performance analytics product. It lets you manage and monitor web application performance, from the browser down to the line of code. With Real User Monitoring, New Relic users can see browser response times by geographical location of the user, or by browser type.
This episode is sponsored by New Relic

Magical Routes

Routing in Rails...let me count the ways. The URL helpers are very flexible and this blog posts walks you through the different parts, their options, and when to use them.
Magical Routes

REST Client

Probably the simplest REST client for Ruby.
REST Client

PostGIS and Google Maps

This two part blog series walks you through using PostGIS with Rails and Google Maps!
PostGIS and Google Maps

SSL for Rails with Heroku and DNSimple

Setting up SSL doesn't have to be a hassle if you're using the right services. Check out this blog post from thoughtbot to see what a wonderful world it can be!
SSL for Rails with Heroku and DNSimple

Rails vs. Sinatra

Which do you chooose? Rails or Sinatra? Unfortunately for us it is never quite that simple. This blog post from Engine Yard gives a good explanation of the differences in getting started with the two frameworks.
Rails vs. Sinatra

How to Get Developers to Write a Blogpost

Been wanting to write a blog post but letting fear, uncertainty, and doubt get in the way? Check out this post from Netguru to get over yourself.
How to Get Developers to Write a Blogpost

iOS Text Kit Basics

Posted 2 months back at GIANT ROBOTS SMASHING INTO OTHER GIANT ROBOTS - Home

In the iOS 7 SDK, Apple gave developers programmatic access to Text Kit, an advanced text layout system that lets you easily display and edit rich text in your applications. Although these capabilities are new to iOS, they’ve existed in other contexts (OS X since its first release, and OpenStep before that) for nearly two decades, in what’s called the Cocoa text system. In fact, if you’ve used OS X at all, there is a near 100% chance that you’ve run apps built with the Cocoa text system.

However, for iOS developers, who often are not steeped in the details of OS X development, the details of using the supplied text layout system are new, and may seem mysterious at first. I intend to help you understand the basics of how this works, and see how you can add rich text features to your own apps.

The simplest thing

Let’s start off by making the simplest possible app that shows off some of what Text Kit can do. In Xcode, create a new project using the Single View Application template, and name it Simple Text View. Select Main.storyboard, use the Object Library to find a UITextView object, and drag it out to fill the view of the available view controller; you’ll see blue guidelines appear and the whole thing snap into place when it’s properly centered. Then use the Attributes Inspector to change the text view’s Text attribute from Plain to Attributed. What this does is tell the text view to allow rich text by using an attributed string. An attributed string, which is represented in iOS by the NSAttributedString class, is simply a string that has some attached metadata describing its attributes. This metadata may contain any number of ranges of characters, each with its own set of attributes. For example, you could specify that starting at the fifth character, the next six characters are bold, and that starting at the tenth character, the next five characters are italicized; In that case, the tenth character would be both bold and italicized. In effect,

0123456789ABCDEF

However, plenty of rich text content is created not by programmatically specifying ranges and attributes, but by users working in an editor that lets them create rich text. That’s a use case that is fully supported by UITextView starting in iOS 7.

UITextView in Interface Builder

To prove this, use the Attributes Inspector to modify parts of the “Lorem ipsum” text that the view contains by default. Use the controls in the inspector to change some fonts, adjust paragraph alignment, set foreground and backgroud colors, whatever you want. When you hit cmd-R to run the app in the iOS Simulator or on a device, you’ll see that all the formatting changes you made show up on the device. You can tap to edit the text at any point, and the formatting that applies where the cursor is will carry on to new characters you type, just as you’d expect from any word processor application.

The innards

So far, so good. Even better, it turns out that a few other popular UIKit classes, namely UILabel and UITextField, also allow the use of attributed strings in iOS 7. This means that if you just want to display some rich text in a single rectangular box, you’re all set. Just put a properly configured UILabel where you want to show your rich text, and you’re done! This simple task was remarkably hard to accomplish before iOS 7, so right there we’ve made a huge leap.

But, what if you want to do more? There are certain kinds of layout tricks that none of the UIKit classes can do on their own, out of the box. For example, if you want to make text flow around a graphic, or make a single string fill up one rectangle before spilling into another (as in the case of multiple columns), you’ll have to do more. Fortunately, the innards of Text Kit, which are used by UITextView and the rest, are at your disposal in the form of the NSTextStorage, NSLayoutManager, and NSTextContainer classes. Let’s talk about these one by one:

  • NSTextStorage is actually a subclass of NSMutableAttributedString, which itself is a subclass of NSAttributedString. It adds some functionality that is useful for dealing with a user editing text, and nothing more.
  • NSTextContainer is an abstract description of a two-dimensional box that text could be rendered into. Basically, this class is little more than a glorified size. It contains a few parameters for describing how text should behave when rendered within a box of its size, and that’s about it.
  • NSLayoutManager is the real brains of the operation. It knows how to take an NSTextStorage instance, and layout all the characters it contains into the virtual boxes described by one or more NSTextContainers.

A class like UITextView uses these components to do all its text layout. In fact, UITextView has three properties called textStorage, textContainer, and layoutManager for just this purpose. When UITextView wants to draw its content, it tells its layoutManager to figure out which glyphs (the graphical representations of the characters it contains) from its textStorage can fit within its textContainer, then it tells the layoutManager to actually draw those glyphs at a point inside the text view’s frame. So you see that the design of UITextView itself is inherently limited to a single rectangle. In order to get a feel for how these innards work, I’ll now show you a UIView subclass that will display rich text in multiple columns, a trick that UITextView really can’t pull off in its current form.

Create TBTMultiColumnTextView

In your open Xcode project, create a new subclass of UIView called TBTMultiColumnView. Like UITextView, this class will have textStorage and layoutManager properties. Unlike UITextView, it will keep track of multiple independent text containers and multiple origins for drawing rectangles. The first thing you should do is create a class extension at the top of the file, containing the following properties:

@interface TBTMultiColumnTextView ()

@property (copy, nonatomic) NSTextStorage *textStorage;
@property (strong, nonatomic) NSArray *textOrigins;
@property (strong, nonatomic) NSLayoutManager *layoutManager;

@end

Besides the NSTextStorage and NSLayoutManager instances, we’re also going to maintain an array of origins, each corresponding to an NSTextContainer. We don’t have to hang onto the text containers themselves, because the layout manager keeps its own list, which we can access.

Now, let’s get started with the methods for this class. First, override viewDidLoad as shown here:

- (void)awakeFromNib {
    [super awakeFromNib];
    self.layoutManager = [[NSLayoutManager alloc] init];

    NSURL *fileURL = [[NSBundle mainBundle] URLForResource:@"constitution"
                                             withExtension:@"rtf"];
    self.textStorage = [[NSTextStorage alloc] initWithFileURL:fileURL
                                                      options:
                        @{NSDocumentTypeDocumentAttribute:NSRTFTextDocumentType}
                                           documentAttributes:nil
                                                        error:nil];
    [self createColumns];
}

This method is pretty straightforward. It starts off by creating a layout manager, which we’ll use every time we need to draw this object’s content. Then we read the contents of an RTF file, which we’ve included in our project, into an NSTextStorage instance. Our project contains an RTF file that contains the U.S. constitution, but you can use any RTF document you have at hand. Since this object will need to be redrawn any time the text storage changes, we implement the setter, like this:

- (void)setTextStorage:(NSTextStorage *)textStorage {
    _textStorage = [[NSTextStorage alloc] initWithAttributedString:textStorage];
    [self.textStorage addLayoutManager:self.layoutManager];
    [self setNeedsDisplay];
}

Note that we have a special way of making a new copy of the object that’s passed in. As it turns out, just sending copy to an instance of NSTextStorage actually returns an instance of an immutable parent class (just like you’d expect with, say, an NSMutableString). That’s why we take the step of explicitly creating a new instance based on the received parameter.

At the end of awakeFromNib, we called the createColumns method, which is where most of this class’s work really happens. It looks like this:

- (void)createColumns {
    // Remove any existing text containers, since we will recreate them.
    for (NSUInteger i = [self.layoutManager.textContainers count]; i > 0;) {
        [self.layoutManager removeTextContainerAtIndex:--i];
    }

    // Capture some frequently-used geometry values in local variables.
    CGRect bounds = self.bounds;
    CGFloat x = bounds.origin.x;
    CGFloat y = bounds.origin.y;

    // These are effectively constants. If you want to make this class more
    // extensible, turning these into public properties would be a nice start!
    NSUInteger columnCount = 2;
    CGFloat interColumnMargin = 10;

    // Calculate sizes for building a series of text containers.
    CGFloat totalMargin = interColumnMargin * (columnCount - 1);
    CGFloat columnWidth = (bounds.size.width - totalMargin) / columnCount;
    CGSize columnSize = CGSizeMake(columnWidth, bounds.size.height);

    NSMutableArray *containers = [NSMutableArray arrayWithCapacity:columnCount];
    NSMutableArray *origins = [NSMutableArray arrayWithCapacity:columnCount];

    for (NSUInteger i = 0; i < columnCount; i++) {
        // Create a new container of the appropriate size, and add it to our array.
        NSTextContainer *container = [[NSTextContainer alloc] initWithSize:columnSize];
        [containers addObject:container];

        // Create a new origin point for the container we just added.
        NSValue *originValue = [NSValue valueWithCGPoint:CGPointMake(x, y)];
        [origins addObject:originValue];

        [self.layoutManager addTextContainer:container];
        x += columnWidth + interColumnMargin;
    }
    self.textOrigins = origins;
}

This method is honestly a little longer than we’d like, but for this example it does the job. This method may need to be called multiple times, whenever the view’s coordinates are adjusted (such as when the device rotates), so we need to make sure it can run multiple times without ending up in a weird state. So, it starts off by removing any old text containers that may be attached to the layout manager. It does this because the whole point of this method is to create a fresh set of text containers, and having old ones lying around will only give us grief. This method then calculates appropriate text container sizes depending on the view’s size and some hard-coded values for the number of columns and the amount of margin that should appear between columns. Finally it creates and configures a number of containers and and equal number of points (wrapped in NSValue objects).

Next we’re going to make use of all those containers and points we just created. The drawRect: method tells the layout manager to finally draw its content into each text container. It looks like this:

- (void)drawRect:(CGRect)rect {
    for (NSUInteger i = 0; i < [self.layoutManager.textContainers count]; i++) {
        NSTextContainer *container = self.layoutManager.textContainers[i];
        CGPoint origin = [self.textOrigins[i] CGPointValue];

        NSRange glyphRange = [self.layoutManager glyphRangeForTextContainer:container];

        [self.layoutManager drawGlyphsForGlyphRange:glyphRange atPoint:origin];
    }
}

All we do here is loop over all available text containers and origin points, each time asking the layout manager which glyphs it can fit into the container, then telling the layout manager to draw those glyphs at the origin point.

That’s just about all we need. In order to make things work after device rotation, however, we need to do one more thing. By overriding layoutSubviews, which is called when the view rotates, we can make sure that the columns are regenerated for the new size:

- (void)layoutSubviews {
    [super layoutSubviews];
    [self createColumns];
    [self setNeedsDisplay];
}

That’s all we need to make this class draw rich text in two columns, and automatically adjust for changes in view geometry. To see this in action, go back to the storyboad and follow these steps:

  • Remove the UITextView you added at the start.
  • Find a UIView in the object library, drag it into the view and make it fill the view completely.
  • Use the Identity Inspector to change this object’s class to TBDMultiColumnView.
  • To make sure the view’s geometry changes along with its superview (e.g. when the device rotates), add constraints from the view to its superview for top, bottom, leading, and trailing space. This is most easily accomplished by clicking the Pin button at the bottom of Interface Builder’s editing area, and selecting each of the four red, dashed-line symbols surrounding the little square (which represents the selected view). That sounds complicated, but once you see it, you’ll get it.

Once you’ve taken those final steps, you can build and run in the simulator or on a device, and see your multicolumn display in all its glory!

Multi Column Text View running on iOS
Simulator

Closing remarks

This class demonstrates a technique for creating a view that lets rich text flow across multiple columns in just a few lines of code. But we’re really just scratching the surface here. Besides flowing across multiple rectangles, Text Kit will let you do plenty of other things, including drawing text inside the path of an arbitrary shape, making text flow around other paths, and more. You can learn more about thse techniques by looking at Apple’s iOS Text Kit Overview, as well as their Mac documentation for the Cocoa text system, which is where much of Text Kit’s functionality originated.

How to Share a Session Between Sinatra and Rails

Posted 2 months back at GIANT ROBOTS SMASHING INTO OTHER GIANT ROBOTS - Home

As Rails developers, we run into Sinatra apps all the time: gems such as Resque which expose a dashboard via Sinatra, legacy Sinatra apps that run alongside a main Rails app, and Sinatra APIs embedded within a Rails app, to name a few examples. Here’s a common problem: how do you share authentication between the apps?

It would be really convenient to be able to do something like this in our Sinatra app:

get '/dashboard' do
  if session[:user_id].present?
    redirect to('/')
  else
    # set up and render dashboard
  end
end

Both Rails and Sinatra are Rack-based, which makes them play surprisingly well together. They can be combined in two ways: via Rack::Builder or via the Rails routes.

Rack::Builder

This method treats Rails as just another Rack app. It creates a middleware stack and mounts the apps at particular urls

# config.ru
map '/api' do
  run MySinatraApp.new
end

map '/' do
  run MyRailsApp::Application.new
end

The standard way to handle authentication in Rails is via a session that is stored in the client’s browser via a cookie. This cookie is base64 encoded in Rails 3.x and encrypted in Rails 4.x. In order to read and write from the session, Rails uses a few middlewares. They (along with the other middlewares that come by default with Rails) can be seen by running rake middleware.

  • ActionDispatch::Cookies
  • ActionDispatch::Session::CookieStore
  • Other middlewares

In order for the Sinatra app to be able to read/write from the Rails session, it needs to have those two middlewares in its stack. The middleware needs to know the name of the cookie that the session is stored in. Finally, the middleware also needs to know the secret token used for signing and encrypting the cookie

# config.ru
map '/api' do
  use Rack::Config do |env| do
    env[ActionDispatch::Cookies::TOKEN_KEY] = MyRailsApp::Application.config.secret_token
  end
  use ActionDispatch::Cookies
  use ActionDispatch::Session::CookieStore, key: '_my_rails_app_session'
  run MySinatraApp.new
end

map '/' do
  run MyRailsApp::Application.new
end

Rails routes

In the previous approach, both the Sinatra and Rails apps were first-class citizens loaded via config.ru. An easier approach is to load all the Sinatra apps via the Rails router. This automatically gives them access to the middlewares loaded (and configured) by Rails.

MyRailsApp::Application.routes.draw do
  mount MySinatraApp.new => '/api'
end

This works because the HTTP request travels through the Rails middleware stack before reaching the router which then sends it to the proper app. When using config.ru, the request is immediately routed to either the Sinatra app or the Rails app so we need to manually add the middleware in front of the Sinatra app.

Which approach to take?

Mounting a Sinatra app via the Rails routes is the standard way to embed a Sinatra app within a Rails app. Since they both share the same middleware stack, you get shared sessions for free. However, if you need a custom middleware stack for your Sinatra app then the Rack::Builder approach is the way to go.

Further reading

Learn more about Rails and Rack

Phusion Passenger 4.0.44 released

Posted 2 months back at Phusion Corporate Blog


Phusion Passenger is a fast and robust web server and application server for Ruby, Python, Node.js and Meteor. Passenger takes a lot of complexity out of deploying web apps, and adds powerful enterprise-grade features that are useful in production. High-profile companies such as Apple, New York Times, AirBnB, Juniper, American Express, etc are already using it, as well as over 350.000 websites.

Phusion Passenger is under constant maintenance and development. Version 4.0.44 is a bugfix release.

Phusion Passenger also has an Enterprise version which comes with a wide array of additional features. By buying Phusion Passenger Enterprise you will directly sponsor the development of the open source version.

Recent changes

Version 4.0.43 has been skipped because a compilation problem on OS X Mountain Lion was found soon after the gem was pushed. The changes in 4.0.34 and 4.0.44 combined are as follows.

  • The issue tracker has now been moved from Google Code to Github. Before version 4.0.44 (May 29 2014, commit 3dd0964c9f4), all issue numbers referred to Google Code. From now on, all issue numbers will refer to Github Issues.
  • On Ruby, fixed nil being frozen on accident in some cases. See issue #1192.
  • Introduced a new command passenger-config list-instances, which prints all running Phusion Passenger instances.
  • Introduced a new command `passenger-config system-metrics, which displays metrics about the system such as the total CPU and memory usage.
  • Fixed some compilation problems caused by the compiler capability autodetector.
  • System metrics such as total CPU usage and memory usage, are now sent to Union Station in preparation for future features.

Installing or upgrading to 4.0.44

OS X OS X Debian Debian Ubuntu Ubuntu
Heroku Heroku Ruby gem Ruby gem Tarball Tarball

Final

Fork us on Github!Phusion Passenger’s core is open source. Please fork or watch us on Github. :)

<iframe src="http://ghbtns.com/github-btn.html?user=phusion&amp;repo=passenger&amp;type=watch&amp;size=large&amp;count=true" allowtransparency="true" frameborder="0" scrolling="0" width="170" height="30"></iframe><iframe src="http://ghbtns.com/github-btn.html?user=phusion&amp;repo=passenger&amp;type=fork&amp;size=large&amp;count=true" allowtransparency="true" frameborder="0" scrolling="0" width="170" height="30"></iframe><iframe src="http://ghbtns.com/github-btn.html?user=phusion&amp;type=follow&amp;size=large&amp;count=true" allowtransparency="true" frameborder="0" scrolling="0" width="190" height="30"></iframe>

If you would like to stay up to date with Phusion news, please fill in your name and email address below and sign up for our newsletter. We won’t spam you, we promise.



Workflows for Writing Migrations With Rollbacks in Mind

Posted 2 months back at GIANT ROBOTS SMASHING INTO OTHER GIANT ROBOTS - Home

thoughtbot’s dotfiles include an alias mapping migrate to

rake db:migrate db:rollback && rake db:migrate

It is also a good practice in our workflow to use the migrate alias in place of rake db:migrate. Let’s explore what this command does and why we recommend it.

Reversibility

rake db:migrate db:rollback will run any pending migrations and then attempt to roll back those migrations. If the migration and rollback are successful (signified by &&), rake db:migrate will then run the migration again. If the command is not successful, an error will be thrown. In this way we can be confident our migrations' down commands are syntactically valid (no typos) and logically valid (no invalid castings of values, for example).

Beyond having a short alias in place of a multi-word rake command, ensuring that each migration we write is reversible is very handy for iterative development locally and for dreaded production rollbacks.

An Exception

One time when we break this guideline is when we explicitly require an irreversible migration because the transformation is destructive. In the special circumstances when this behavior is required, the down command should raise an ActiveRecord::IrreversibleMigration exception as stated by the docs. As a result, a rollback is impossible and we’ll run rake db:migrate instead of migrate.

What’s next

We have found having a frictionless way of running migrations in both directions has saved us lots of time and headaches.

If you’d like to learn more about handling irreversible migrations check out the following resources:

Happy migrating!

Writing a Domain-Specific Language in Ruby

Posted 2 months back at GIANT ROBOTS SMASHING INTO OTHER GIANT ROBOTS - Home

A Domain-Specific Language, or DSL, is “a programming language of limited expressiveness focused on a particular domain”. It makes tasks in its domain easier by removing extraneous code for a particular task and allowing you to focus on the specific task at hand. It also helps other people read the code, because the purpose of the code is so clear.

Here’s a little Internal DSL in Ruby:

Smokestack.define do
  factory User do
    name "Gabe BW"
    pet_name "Toto"
  end
end

user = Smokestack.build(User)
puts user.name == 'Gabe BW'  # true
puts user.pet_name == 'Toto' # true

other_user = Smokestack.build(User, name: "Bob")
puts other_user.name == 'Bob'      # true
puts other_user.pet_name == 'Toto' # true

Let’s go over each part and how it works.

Set up

First, let’s define User and Post classes that we’ll be using in our factory:

class User
  attr_accessor :name, :pet_name
end

class Post
end

We’ll be referring to these throughout the post.

Identifying method calls

When I first looked at code like Smokestack.define above, I had a hard time identifying where methods were being called. Let’s add parentheses:

Smokestack.define do
  factory(User) do
    name("Gabe B-W")
    pet_name("Toto")
  end
end

That’s better. Now we can see that Smokestack.define takes a block, and the factory method takes a class, like User, and a block. But where is the factory method coming from?

instance_eval

To find out, we need to look at the instance_eval instance method, available on every class. According to the docs:

Evaluates a string containing Ruby source code, or the given block, within the
context of the receiver (obj). In order to set the context, the variable self is
set to obj while the code is executing, giving the code access to obj’s instance
variables.

Here’s an example:

class DefinitionProxy
  def factory(factory_class)
    puts "OK, defining a #{factory_class} factory."
  end
end

definition_proxy = DefinitionProxy.new
definition_proxy.instance_eval do
  factory User
  factory Post
end

That code prints out this:

OK, defining a User factory.
OK, defining a Post factory.

The factory User and factory Post are evaluated in the context of the definition_proxy instance. That means that factory User in the definition_proxy.instance_eval block is actually calling definition_proxy.factory(User).

Now let’s add it to Smokestack:

module Smokestack
  def self.define(&block)
    definition_proxy = DefinitionProxy.new
    definition_proxy.instance_eval(&block)
  end
end

Smokestack.define is now the entry point for our DSL. It takes a block, then evaluates that block in the context of a DefinitionProxy instance.

Registering Factories

Now that our code sort of works, let’s register factories. Factories aren’t helpful unless we can refer to them, and to do that we need a central registry. The simplest registry is a hash that maps factory classes to factories.

The following code gives us Smokestack.registry:

module Smokestack
  @registry = {}

  def self.registry
    @registry
  end
end

Let’s change the factory method to register factories when they’re declared:

class DefinitionProxy
  def factory(factory_class)
    factory = lambda { puts "OK, creating a #{factory_class}." }
    Smokestack.registry[factory_class] = factory
  end
end

Instead of printing out a message immediately, we wrap it in a lambda. This means that we can store that lambda in the registry, and call factories whenever we like after registering them:

Smokestack.define do
  factory User
end

Smokestack.registry[User].call # => "OK, creating a User."
Smokestack.registry[User].call # => "OK, creating a User."

Diving Deeper

Now we can declare that a factory exists, but it’s not really a factory yet. It doesn’t actually initialize objects. Let’s look at the original code again:

factory User do
  name "Gabe BW"
  pet_name "Toto"
end

We want that code to declare a factory that does the following:

user = User.new
user.name = "Gabe BW"
user.pet_name = "Toto"
return user

Like Factory Girl, we’ll assume that:

  • factory User refers to the User class
  • The User class has setter methods for every attribute in the factory (e.g. name=)

Each factory might have different setter methods (e.g. pet_name=), so we’ll use method_missing to handle every case.

Let’s take a stab at it:

class Factory < BasicObject
  def initialize
    @attributes = {}
  end

  attr_reader :attributes

  def method_missing(name, *args, &block)
    attributes[name] = args[0]
  end
end

class DefinitionProxy
  def factory(factory_class, &block)
    factory = Factory.new
    if block_given?
      factory.instance_eval(&block)
    end
    Smokestack.registry[factory_class] = factory
  end
end

DefinitionProxy#factory now passes its block to a Factory instance, then stores the Factory instance in the registry. If there’s no block (i.e. if block_given? evaluates to false), then the factory does not evaluate the block, but is still put in the registry. Here’s a case where we have no block, because Post has no attributes:

Smokestack.define do
  factory Post
end

Factory inherits from BasicObject, which is a class with very few methods defined. It’s great for use in metaprogramming like this, where you want every instance method call to trigger method_missing.

We now have all of the Smokestack.define DSL working, with factories and a registry to map factory names to stored factories. Let’s add Smokestack.build.

Smokestack.build

Smokestack.build(User) needs to do the following:

  • Grab the user factory
  • Set attributes on the user, with optional overrides
  • Return the user

To get the attributes, we can grab factory.attributes from the user factory in the registry. Let’s have Smokestack.build take an optional second parameter, overrides, which allows people to pass custom values.

Here’s the code:

module Smokestack
  def self.build(factory_class, overrides = {})
    instance = factory_class.new

    # Set attributes on the user
    factory = registry[factory_class]
    attributes = factory.attributes.merge(overrides)
    attributes.each do |attribute_name, value|
      instance.send("#{attribute_name}=", value)
    end

    # Return the user
    instance
  end
end

Putting it all together

Here’s what we ended up with:

module Smokestack
  @registry = {}

  def self.registry
    @registry
  end

  def self.define(&block)
    definition_proxy = DefinitionProxy.new
    definition_proxy.instance_eval(&block)
  end

  def self.build(factory_class, overrides = {})
    instance = factory_class.new
    factory = registry[factory_class]
    attributes = factory.attributes.merge(overrides)
    attributes.each do |attribute_name, value|
      instance.send("#{attribute_name}=", value)
    end
    instance
  end
end

class DefinitionProxy
  def factory(factory_class, &block)
    factory = Factory.new
    factory.instance_eval(&block)
    Smokestack.registry[factory_class] = factory
  end
end

class Factory < BasicObject
  def initialize
    @attributes = {}
  end

  attr_reader :attributes

  def method_missing(name, *args, &block)
    @attributes[name] = args[0]
  end
end

Let’s run it through its paces:

Smokestack.define do
  factory User do
    name "Gabe BW"
    pet_name "Toto"
  end
end

user = Smokestack.build(User)
puts user.name
#=> "Gabe BW"
puts user.pet_name
#=> "Toto"

other_user = Smokestack.build(User, name: 'Bob')
puts other_user.name
#=> "Bob"
puts other_user.pet_name
#=> "Toto"

Neat.

How could this be made better?

The use of a class directly (factory User) looks out-of-place if you’re familiar with Rails idioms or Factory Girl. To make this more Rails-y, we’d use a symbol like factory :user. To make this work, we can use plain Ruby or ActiveSupport:

# Plain Ruby
Object.const_get(:user.capitalize) #=> User

# ActiveSupport
:user.capitalize.constantize #=> User

Further Reading

For more examples of DSLs, check out factory_girl or the Rails routes.

Finding the perfect house using open data

Posted 2 months back at Encytemedia - Home

1283d6a2014211e3a98422000aa80fc9_7

My childhood backyard.

Growing up in rural Mississippi had its perks. Most days my brother and I would come home from school, grab a snack from the fridge, and head outside to fish in the pond tucked behind the tree line or play basketball with the neighborhood kids. It was very much a community where everyone knew everyone. I had known many of the kids from my graduating class since second grade and my parents knew their parents since highschool and earlier.

As beautiful as my hometown was, it was, like many small towns, economically depressed and void of all but the necessities. As I grew older, I became frustrated by this. We had one small grocery store, one stop light, two movie rental places and not a single fast food restaurant. We had no book stores, no electronic stores, no big-box stores and only a couple of places to grab a bite to eat.

Truth be told, the gas station (one of those big ones, forever known as “The BP” long after a name change) was where we picked up most of our take out. When highway 72 was expanded to four lanes, a nearby gas station was converted to a “super” station. It was packed with a pizza place, fresh sub sandwiches, and the best chicken strips that have ever graced the space below a heat lamp. It was the community watering hole.

The lack of access eventually wore on me. As I started to grow my design skills (my Hail Mary escape from factory work), I would hear of my peers in larger cities going out to eat, to the movies, or just having a beer at a nearby bar. Beer, by the way, was illegal where I grew up. Not just the consumption of it, the mere possession of it.

6307658831_df66e3f10d_b

Portland - Oregon by Patrick M. License CC BY-NC-SA 2.0

By 2007, after a couple of years on the outskirts of Memphis, TN, I had finally had enough and convinced my wife to move to Portland, OR. We knew very little about Portland at the time. In fact, we knew so little about the Pacific Northwest, we moved in the dead of winter, in a sports car, driving through the Cascade mountain range. It’s not exactly something I’m proud of; a hilariously ill-conceived cross-country trip.

When we moved to Portland we decided we wanted to be in the center of it all. There was so much life around us; so much happening relative to our rural upbringing. I wanted to be as close to Downtown as I could be so I could go as often as I liked.

We eventually settled on the Pearl District. A relatively new residential development that was previously occupied by a rail yard. Finally, I would have the access that I once craved. Almost anything I wanted was a short walk or streetcar ride away. All that I wished for growing up, I would have.

8bb23018889a11e18cf91231380fd29b_7

Fast forward 7 years and we’re still in the Pearl District. We’ve added a member to our family who now desires access to the things I had while growing up. He wants a yard to play in, a basketball goal and a proper house where he can get excited without disturbing our neighbors.

It’s an interesting scenario. The Pearl District and Downtown aren’t exactly teaming with affordable single family homes and the further you move out of the city center, generally the less access you have to the many things a dense urban area has to offer. But, in reality, I only wished for a couple of things out of a new location.

The journey begins

After thinking about the problem, I decided to list out a set of criteria for a location I would want to live. Other factors will eventually come into play, but I wanted to narrow down the city into “target zones”—that is, zones that meet a set of defined criteria.

  • Walking distance to a grocery store: Living across the street from a grocery store has spoiled me.
  • Walking distance to a rail stop: This will allow me to get to other locations in the city without a car relatively quickly. One could argue the bus system is just as good, but I would argue that it isn’t and I much prefer rail.

I defined walking distance as ~5 blocks, but ~10 blocks is still a pretty sane distance. I want to be close to a grocery store and close to a MAX or Streetcar stop. Unfortunately, none of the real estate applications I tried had a feature like this so I decided to create what I needed using open data that I had already been working with for some time now.

Gathering the data

This section makes heavy use of GDAL and PostGIS. Both of which can be installed using homebrew on OSX.

We’ll need 3 open datasets.

After downloading the data, we’ll want to reproject the building dataset to EPSG:4326 so that all of the data shared the same projection. EPSG:4326 (WGS84) is a common projection and the projection of the other two datasets so I went with that.

ogr2ogr -t_srs EPSG:4326 -f "ESRI Shapefile" building-footprints.shp  Building_Footprints_pdx.shp

Note: EPSG:2913, the original projection of the building dataset, is probably the more accurate choice if we were concerned with a high level of precision.

Now we need to create a PostGIS-enabeld Postgres database

createdb portland
psql -c "create extension postgis" -d portland

Finally, we need to import the datasets to our freshly created Postgres database. See the shp2pqsql docs for an explanation of the flags used. Essentially we want to import as latin1 (there are some encoding errors in the building dataset), force 2d geometry and create an index on the geometry column.

shp2pgsql -W "latin1" -t 2D -I -D -d -s 4326 building-footprints.shp building_footprints | psql -d portland
shp2pgsql -W "latin1" -t 2D -I -D -d -s 4326 osm-polygons.shp osm_polygons | psql -d portland
shp2pgsql -W "latin1" -t 2D -I -D -d -s 4326 trimet-rail-stops.shp trimet_rail_stops | psql -d portland

After we have the data imported into Posgtres, we can begin to find target geometries (buildings) that meet the criteria we set. The first thing we want to do is find the zones around all supermarkets using st_expand. Our units are decimal degrees and 0.0045 is about the desired distance of ~5 blocks. We’re not too worried about being a little off here.

select st_expand(geom, 0.0045) as zone, 5 as score from osm_polygons where osm_polygons.shop='supermarket'

zones

At this point, we have large rectangle geometries. As you can tell from the image above, some buildings lie in overlapping zones. We want to score those buildings for every zone they intersect with. In similar fashion, we want to find the zones around rail stops and public parks.

The next thing we want to target individual buildings instead of merely drawing a large box around a zone. We can find all buildings that intersect a zone using st_intersects.

select * from supermarket_zones inner join buildings on st_intersects(supermarket_zones.zone, buildings.geom) where buildings.subarea='City of Portland'

screen shot 2014-05-24 at 11 42 14 am

Finally, we want to group identical geometries, sum the score and stuff the target buildings into a new table. We don’t necessarily need to add the target buildings to a new table, but continuously running these queries across the entire building set can be slow.

select sum(score) as rank, gid, geom into target_homes from target_buildings group by 2, 3;

Here’s what everything looks like combined which can be run using psql -f score-buildings.sql -d portland.

<script src="https://gist.github.com/Caged/d9b988485b813b14c69b.js"> </script>

Styling the results

Mapbox has a great crash course on TileMill. I highly recommend you check it out if you’re unfamiliar with it.

The last major thing we need to do is to visualize the results on a map. For this, I’ll use the open source editor Tilemill by Mapbox. This step is pretty straight forward since we’ve already done the hard work of extracting and scoring the buildings we’re interested in. We only need to supply Tilemill with the name of the table we stored our target homes in.

screen shot 2014-05-24 at 11 54 05 am

Finally, let’s fill each building with a color based on its score using CartoCSS.

#homes {
  [rank >= 5] {
    polygon-fill: #ea97ca;
  }

  [rank >= 10] {
    polygon-fill: #3581ac;  
  }

  [rank >= 15] {
    polygon-fill: #4dac26;
  }

   [rank >= 20] {
    polygon-fill: #a9bb29;
  }
}

We can add more layers to help give some context to our results. Here’s what I ended up with after adding layers for rail lines, rail stops and supermarkets.

screen shot 2014-05-24 at 12 04 49 pm

And that’s it. Now I have a good idea of locations I can check out in my quest to find a house nearby a supermarket and rail line. Nothing like quickly grabbing a beer for a backyard barbecue and a little game of basketball. And hey, when the Trail Blazers play? I’ll just walk a few blocks and hop on the MAX.

Episode #467 - May 23rd, 2014

Posted 2 months back at Ruby5

Some new stuff(Rspec3 rc1, ActiveJob), some cool stuff(Devise-two-factor, Camcorder), and some educational stuff (Teaching kids of Pis, Weirich on Exceptions) in this RubyLoco-powered edition of Ruby5!

Listen to this episode on Ruby5

This episode is sponsored by New Relic

Brought to you by NewRelic
This episode is sponsored by New Relic

ActiveJob

Active Job is a framework for declaring jobs and making them run on a variety of queueing backends. In just a few days, it has gone from a neat idea to a functional job abstraction on top of 8 Ruby Job queue libraries.
ActiveJob

devise-two-factor

Devise-two-factor is a minimalist extension to Devise which offers support for two-factor authentication
devise-two-factor

inch pages

If you are a gem developer or maintain a library you probably already use badges in your README to show that your tests are passing and your code isn't a horrible mess in need of refactoring. Now you can also show that you documented your project properly.
inch pages

camcorder

Need to have VCR-like functionality for more than just http? Wait no more. This gem allows you to record arbitrary method invocations from arbitrary objects.
camcorder

Kids and Pis

Last fall I volunteered at my kids school and taught over 200 kids the ‘hour of code curriculum’. I’m trying to get together a summer program for about 15 kids around 5th grade, giving them raspberry pis, support, and ideas on fun stuff to do. I’m using Ruby5 as a soapbox to find others doing similar things. If you’re interested in collaborating as teachers and doing something in your area, reach out on twitter (@bokmann)
 Kids and Pis

Active Record Soup

Once upon a time there was a small but prosperous village...
Active Record Soup

Weirich on Exceptions

Writes Avdi Grim, "Back in 2011 I was doing research for the talk that became Exceptional Ruby, and Jim Weirich was nice enough to let me pick his brain on the topic. I was reminded of this email today, and thought I’d share it."
Weirich on Exceptions

Working Effectively with Unit Tests

Posted 2 months back at Jay Fields Thoughts

Unit Testing has moved from fringe to mainstream, which is a great thing. Unfortunately, as a side effect developers are creating mountains of unmaintainable tests. I've been fighting the maintenance battle pretty aggressively for years, and I've decided to write a book that captures what I believe is the most effective way to test.

From the Preface

Over a dozen years ago I read Refactoring for the first time; it immediately became my bible. While Refactoring isn’t about testing, it explicitly states: If you want to refactor, the essential precondition is having solid tests. At that time, if Refactoring deemed it necessary, I unquestionably complied. That was the beginning of my quest to create productive unit tests.

Throughout the 12+ years that followed reading Refactoring I made many mistakes, learned countless lessons, and developed a set of guidelines that I believe make unit testing a productive use of programmer time. This book provides a single place to examine those mistakes, pass on the lessons learned, and provide direction for those that want to test in a way that I’ve found to be the most productive.
The book does touch on some theory and definition, but the main purpose is to show you how to take tests that are causing you pain and turn them into tests that you're happy to work with.

For example, the book demonstrates how to go from...

looping test with many (built elsewhere) collaborators
.. to individual tests that expect literals, limit scope, explicitly define collaborators, and focus on readability
.. to fine-grained tests that focus on testing a single responsibility, are resistant to cascading failures, and provide no friction for those practicing ruthless Refactoring.
As of right now, you can read the first 2 chapters for free at https://leanpub.com/wewut/read

I'm currently ~25% done with the book, and it's available now for $14.99. My plan is to raise the price to $19.99 when I'm 50% done, and $24.99 when I'm 75% done. Leanpub offers my book with 100% Happiness Guarantee: Within 45 days of purchase you can get a 100% refund on any Leanpub purchase, in two clicks. Therefore, if you find the above or the free sample interesting, you might want to buy it now and save a few bucks.

Buy Now here: https://leanpub.com/wewut

SSL for Rails with Heroku and DNSimple

Posted 2 months back at GIANT ROBOTS SMASHING INTO OTHER GIANT ROBOTS - Home

SSL certificates can be intimidating but Heroku and DNSimple make the process easy. The following steps should take us less than 15 minutes.

Buy the SSL certification from DNSimple

Buy a wildcard certificate from DNSimple. The wildcard (*) lets us use the same certificate on staging, production, and any other future subdomains (api, etc.).

Prepare the SSL certificate

Follow the wildcard certificate instructions to get .pem, .crt, and .key files prepared.

Follow these instructions to complete .key preparation, provision the SSL addon from Heroku, and add the certificate to Heroku:

heroku certs:add server.crt server.key

Replace it with:

heroku certs:add *.{pem,crt,key}

Otherwise, we might see an error like:

Updating SSL Endpoint myapp.herokussl.com for [heroku-app]... failed
 !    Internal server error.

Get SSL endpoint from Heroku

Run:

heroku certs

This provides us the correct end point for the SSL enabled domain. This is a domain that looks like tokyo-2121.herokussl.com.

Add Heroku SSL endpoint to DNSimple

Next, go to our DNSimple dashboard and update/add the CNAME record for the SSL enabled domain to point to (e.g.) tokyo-2121.herokussl.com.

Prepare Rails app

Make a one-line configuration change in our staging and production environment config files within our Rails app:

# config/environments/{staging,production}.rb
config.force_ssl = true

Deploy that change.

Now, if users type “ourdomain.com”, they should be redirected to “https://www.ourdomain.com” and our browser’s URL bar should display its appropriate indicator (perhaps a green lock) declaring the SSL certificate is valid.

What’s next?

Read our production checklist to see a full list of things, including SSL, that should be done before an application goes live.

Episode #466 - May 20th, 2014

Posted 2 months back at Ruby5

Unexpected new Ruby, plenty of SMTP, Discovery Tests and their mocks, heroes building ROM, Windows longing for ExecJS, Napybaras, and dangerous :nodocs: this week on Ruby5.

Listen to this episode on Ruby5

Sponsored by RailsLTS

With the release of Rails 4, support for Rails 2.3 and Rails 3.0 has ended. Security vulnerabilities are no longer patched for these versions. Rails LTS offers a solution for mission critical applications by providing security patches for old versions of Rails.
This episode is sponsored by RailsLTS

Ruby 1.9.3-p547 released

Last week, Ruby 1.9.3­p547 was released. As the release announcement explains, there is one exception to the security ­only maintenance phase that 1.9.3 is currently in, and that’s critical regressions. Apparently some Ruby users on Ubuntu 10.04 LTS noticed that when their system had an old version of OpenSSL, a segfault was possible when using the get method on Net::HTTP, and this release fixes that prevents the segfault. Only affected users are invited to upgrade. ���
Ruby 1.9.3-p547 released

Email failover with MultiSMTP

Harlow Ward wrote in to let us know about a small library from Michael Choi and his blog post on the HotelTonight engineering blog covering Rails email failover with multi­SMTP support. Using the Mail gem, MultiSMTP gives your app multiple SMTP server configuration support with failover. With multiple SMTP servers configured ­like SendGrid, Mandrill, or Google ­you get multiple host redundancy and very likely geographical and service redundancy.
Email failover with MultiSMTP

Mock Objects in Discovery Tests

The virtue and value of mocks has been under siege for the past few weeks as DHH and others attacked the construct for enabling bad behavior when testing. Justin Searls, who I discovered with his great Breaking Up With Your Test Suite talk at Ancient City Ruby this year, created a great screencast in which he shows how useful mocks can be in what he calls Discovery Tests. He describes only using mocks to the extent he needs them in order to specify the contract between a subject's dependencies. The screencast is quite thorough and provides a lot of concrete examples. I think whether you agree with him or not, it’s rare enough to be able to witness another developer’s design habits at play, that you should take the time to watch this. He also mentions Gary Bernhardt’s Test Isolation Is About Avoiding Mocks post which is long, but quite worth the read, as well.
Mock Objects in Discovery Tests

Help Us Build ROM

Piotr Solnica, maintainer of ROM — the Ruby Object Mapper library — put together a post where he describes the current state of ROM, the purpose, the foundation, where it’s been, the current ecosystem, and most importantly, instructions on how to get started contributing to the project. Because the project has been going on for so long, there is a lot of history and experimentation. There’s also a large number of libraries and concepts floating around. Things like mutant for mutation testing, memoizable for method return value memoization and adamantium to create immutable objects. So, rather than have to re­-explain all of this knowledge for each developer who wants to get started, he distilled it into one page.
Help Us Build ROM

ExecJS is looking for a new Windows-friendly maintainer

Josh Peek, the current maintainer of the ExecJS gem (which the Asset Pipeline depends on) announced on Twitter yesterday that he’s looking for a more active maintainer for the project, especially someone who cares about Windows support.
ExecJS is looking for a new Windows-friendly maintainer

Napybara

George Mendoza wrote in to let us know about a Capybara extension library that he’s created and released, called Napybara. It's a Capybara extension which adds a lightweight DSL for defining Capybara helpers that are easy to abstract, compose, and introspect. An example of this are for nested reference support for selecting your page inputs and elements. Basically, rather than just working with element names or whatever, with Napybara, you can "dot-­reference" page objects by tag name or class to get all the way down to what you’re after. Rather than maybe doing within scopes or something, you can now just reference elements more directly with something like "testpage.form.row­1.text_field". You can find by Ruby objects or selectors, you can easily determine element existence, it works with RSpec and it is extensible. Check it out on GitHub.
Napybara

:nodoc: means tread lightly

Zachary Scott wrote an interesting piece of documentation for Rails last week, covering method visibility. While the Ruby core team marks methods that people shouldn’t use directly as private, on the Rails core team some internal methods are indeed public but they’re marked with a :nodoc: comment. A lot of people do ingenious stuff with internal methods like arel_table and end up getting bit whenever they are changed, renamed or removed without notice from the Rails core team because that’s exactly what people should expect.
:nodoc: means tread lightly

Project Retrospective: Reserve A Game

Posted 2 months back at GIANT ROBOTS SMASHING INTO OTHER GIANT ROBOTS - Home

Reserve A Game

Earlier this year, Boston startup Reserve a Game came to thoughtbot to design their product: a way for people to reserve time at local public tennis courts. Many in our office are familiar with the disappointment of showing up to the Boston Common courts after work, only to find a long line to play. For frequent tennis players, this becomes less of a slight annoyance and more of daily problem. At a time when most everything can be reserved (tables at a restaurant, seats for a movie), it seemed like a great idea, but first we needed to test our assumptions.

Here’s a look at our process, from design sprint to launch:

The Problem

The experience of playing tennis on public courts is frustrating. The challenge of finding an open court, uncertainty about court availability, and the potential of having to wait, get in the way of playing the game.

The Product

What does it need to be? What does it need to provide? Who is it for? We had to eliminate a lot of feature ideas, even good ones, to settle on searching and reserving as the main jobs to be done in the application. Our biggest challenge was to meet the needs of both tennis players who would reserve courts, and cities that would adopt this service. For an early-stage startup, it can be a challenge to balance user needs with sales. In this case, it was clear that the founders valued user experience above all, so we charged ahead, hoping that if tennis players would use the product, cities would want to adopt it.

The design sprint wasn’t easy, but it was worth it. We had a done a lot of work before we came to thoughtbot, but this process helped us to put a framework to our concepts and whittle our options down to the best user flow possible for players. We also discovered what we all felt was the best design to ensure a great experience on both mobile and desktop.

Brent Colson, Founder, Reserve a Game

The Critical Path

What tasks does a person need to be able to do with this product? After diverging for a day to sketch the user flow individually, we came together to draw the critical path as a group. This drawing served as the basis for our prototype.

Testing and Learning

We interviewed tennis players and watched them click through the prototype. These conversations validated our assumption that avid tennis players would, in fact, pay for the convenience of a reservation. However, using this app needed to be easier than just showing up and waiting in line.

Some of our assumptions turned out to be false. For example, we assumed people wouldn’t care about the specific court they reserved in a facility. We were wrong. While some people didn’t care, the most avid players (our target users) noted that they often had a preference, and would appreciate the option to choose. Our prototype had focused on selecting any available court in a facility, rather than choosing a specific court. We now knew we needed to add court selection back to the top of our feature list.

User testing did two main things for us. First, our assumptions went through the ringer and some proved to be false, allowing us to pivot in minor ways to save us big money down the road. Second, it proved to be another validation of just how much need there is for our product. Most testers were surprised by how easy the process was and told us they would definitely use the service. It was music to our ears…

Brent Colson, Founder, Reserve a Game

The Development Process

Over the course of 200+ git commits, we built the MVP in time for the spring season in Boston. The design sprint helped us to understand our assumptions and risks up front and gave us a clear direction. With many potential problems having already been addressed, we moved quickly through development. Daily standups, weekly retrospectives and constant communication kept our team focused on delivering the right product.

I thought I knew agile development before we started working with thoughtbot, but their expertise and process helped me grow tremendously in my own ability to manage these types of projects. They helped me to constantly challenge assumptions and find better, or simpler ways to build our product. In the end, we built the right product, which wasn’t necessarily how we envisioned it before we started with thoughtbot.

Brent Colson, Founder, Reserve a Game

If you want to learn more about our process, take a look at our design sprint methodology.

Reserve a Game has now launched their service in the Boston area. They are looking for creative people, including designers and developers, to join their team to help create the future of community sporting services. If you are interested, please get in touch with Brent Colson.

Weighing in on Long Live Testing

Posted 2 months back at Jay Fields Thoughts

DHH recently wrote a provocative piece that gave some views into how he does and doesn't test these days. While I don't think I agree with him completely, I applaud his willingness to speak out against TDD dogma. I've written publicly about not buying the pair-programming dogma, but I hadn't previously been brave enough to admit that I no longer TDD the vast majority of the time.

The truth is, I haven't been dogmatic about TDD in quite some time. Over 6 years ago I was on a ThoughtWorks project where I couldn't think of a single good reason to TDD the code I was working on. To be honest, there weren't really any reasons that motivated me to write tests at all. We were working on a fairly simple, internal application. They wanted software as fast as they could possibly get it, and didn't care if it crashed fairly often. We kept everything simple, manually tested new features through the UI, and kept our customer's very happy.

There were plenty of reasons that we could have written tests. Reasons that I expect people will want to yell at me right now. To me, that's actually the interesting, and missing part, of the latest debate on TDD. I don't see people asking: Why are we writing this test? Is TDD good or bad? That depends; TDD is just a tool, and often the individual is the determining factor when it comes to how effective a tool is. If we start asking "Why?", it's possible to see how TDD could be good for some people, and bad for DHH.

I've been quietly writing a book on Working Effectively with Unit Tests, and I'll have to admit that it was really, really hard not to jump into the conversation with some of the content I've recently written. Specifically, I think this paragraph from the Preface could go a long way to helping people understand an opposing argument.

Why Test?

The answer was easy for me: Refactoring told me to. Unfortunately, doing something strictly because someone or something told you to is possibly the worst approach you could take. The more time I invested in testing, the more I found myself returning to the question: Why am I writing this test?

There are many motivators for creating a test or several tests:
  • validating the system
    • immediate feedback that things work as expected
    • prevent future regressions
  • increase code-coverage
  • enable refactoring of legacy codebase
  • document the behavior of the system
  • your manager told you to
  • Test Driven Development
    • improved design
    • breaking a problem up into smaller pieces
    • defining the "simplest thing that could possibly work"
  • customer approval
  • ping pong pair-programming
Some of the above motivators are healthy in the right context, others are indicators of larger problems. Before writing any test, I would recommend deciding which of the above are motivating you to write a test. If you first understand why you're writing a test, you'll have a much better chance of writing a test that is maintainable and will make you more productive in the long run.

Once you start looking at tests while considering the motivator, you may find you have tests that aren't actually making you more productive. For example, you may have a test that increases code-coverage, but provides no other value. If your team requires 100% code-coverage, then the test provides value. However, if you team has abandoned the (in my opinion harmful) goal of 100% code-coverage, then you're in a position to perform my favorite refactoring: delete.
I don't actually know what motivates DHH to test, but if we assumed he cares about validating the system, preventing future regressions, and enabling refactoring (exclusively) then there truly is no reason to TDD. That doesn't mean you shouldn't; it just means, given what he values and how he works, TDD isn't valuable to him. Of course, conversely, if you value immediate feedback, problems in small pieces, and tests as clients that shape design, TDD is probably invaluable to you.

I find myself doing both. Different development activities often require different tools; i.e. Depending on what I'm doing, different motivators apply, and what tests I write change (hopefully) appropriately.

To be honest, if you look at your tests in the context of the motivators above, that's probably all you need to help you determine whether or not your tests are making you more or less effective. However, if you want more info on what I'm describing, you can pick up the earliest version of my upcoming book. (cheaply, with a full refund guarantee)

Rails Is Not Dead

Posted 2 months back at Luca Guidi - Home

A few years ago, my lead develop of the time, told me: “Beware of the coupling that you’re introducing in your models”. My answer was: “Hey, you don’t know what you’re talking about, this is ActiveRecord”.

I was an unexperienced developer fascinated by the innovation that Rails introduced. After all, my technology was able to get rid of all that configurations, and all that boring stuff from the past.

- Patterns?
- I don't need them. I have the Holy Grail: MVC.
- Interfaces?
- Are you kidding me? This isn't Java, it's Ruby!

We all have been there. We were recovering from the consequences of the New Economy economy bubble burst. A new wave of technologies was raising: AJAX, Rails, and the Web 2.0. All was exciting, we felt like we’d learned from the past mistakes. We were creating a new way to sell software, we needed to be agile, fast and pragmatic.

All that thinking about the architecture looked like an unnecessary aftermath of the enterprise legacy.

Fast forwarding to today, after years spent on several projects, countless hours staring at a monitor, helping startups, banks, broadcasting and highway companies, non-profit organizations, large and small Open Source projects, I can confess one thing: I was wrong.

Rails has the undeniable credit to have changed the way we do web development. It has lowered the entry level so much, that even people without a background as programmers have been able to create a successful business. But this had a cost: technical debt.

I don’t blame Rails for this, as we shouldn’t blame TDD for writing damaged code. We write it, we generate legacy while writing it. We take merits when it’s good, we’re to blame when it isn’t.

But honestly, I don’t get one thing: why half of the Ruby community is so scared to talk about better code?

I have my own opinions about software, that now are diverging from Rails. I’m creating a web framework to introduce new ideas and rethink architectures. I hope to remove the pain points that have been a problem for my direct experience as a programmer.

And you know what? I might be wrong, but don’t be afraid to talk with me. Don’t you recognize this is diversity too? I don’t claim to be right like the leaders of this community think they are. I don’t think that the ideas that I had ten years ago are still valid, like they do.

The current leaders are behaving like those old politicians who say that global warming is a scam: they get defensive because their world is criticized. They keep saying to not worry about, that the problem doesn’t exist, but it does.

Rails is not dead. Debating about things such as the hexagonal architecture isn’t an assault to the framework, but a way to evolve as a community. If they feel under attack, we have a problem.

Please speak up.