Posted about 1 month back at Ruby5
Signed forms, Single Table Inheritance, Sinatra assets and more, all on this episode of Ruby 5.
Listen to this episode on Ruby5
This episode is 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.
Signed Form
What if you didn’t have to worry about whitelisting form fields any more, in Rails 3 or Rails 4? The signed_form gem is a clever solution to keeping form fields and controller parameters synchronized.
RVM Package Management
Well, this is why RVM’s release manager, Michael Papis, just made a blog post about the addition of package manager integration to RVM. RVM will know how to use the system package manager to install missing libraries that it needs in order to build Ruby 2.0.
Libreconv
Richard Nystrom dropped us a line yesterday to let us know about two convenient document conversion gems he’s worked on. First there’s the libreconv gem which allows you to convert from microsoft word to PDF format.
Kristin
The Kristin gem uses pdf2htmlEX to convert PDF documents to HTML.
GPIO with Pi Piper
It used to be you had to program a microcontroller like Arduino to do any work with LEDs and motors and so on. But the low-cost Raspberry Pi computer lets you use its GPIO pins to do many of the same things. And Ruby is easy to install on the Pi. With the “pi_piper” library, you can handle GPIO input events and trigger output using Ruby.
Single Table Inheritance and HStore
Postgres’s hstore module provides you the hstore datatype, which allows you to define a column in your postgres database that contains key/value pairs, for schema-less datastorage. Joe Hirn wrote a nice blog post showing how you can use hstore with Rails to do some really nice Single Table Inheritance tricks.
Sentimental
Have a bunch of strings that you need to determine the sentiment of? Like, maybe you need to find out if some Twitter users are happy or annoyed? How about automatically analyzing their posts using the Sentimental gem? You feed Sentimental a dictionary file, and it uses those keywords to rank whether a post is positive, negative, or neutral.
Sinatra Asset Pipeline
The Sprockets library gave us the asset pipeline with Rails… compiling our CoffeeScript, SASS, and other formats… And now the sinatra-asset-pipeline gem promises to easily give you all this functionality for your Sinatra apps.
Posted about 1 month back at Jay Fields Thoughts
Confession: I really hope someone can tell me I'm doing this wrong. I can't believe there isn't an easier way.
I work with Clojure, in Emacs, almost every day. Navigating the source is usually fairly easy. If I want to navigate to a function definition, all I need to press is M-., and if I want to navigate back, M-, does the trick. This works for Clojure that I've written, as well as Clojure that lives in the libraries that I reference. That's fine the vast majority of the time, but occasionally I need to navigate to the Java source of some library I'm using. This is where I can't believe that no one else has solved this problem.* If I'm in a clj file, my cursor is on a Java class, I don't know of any way to easily navigate to the class definition.
Context: I use fig for dependency management (at work). I have my projects set to put sources in ./the-project/lib/sources; therefore, the following solution assumes the sources are in that directory. If you use Lein (for deps), I'm sure the sources are on your local drive somewhere. All you need to do is change the lisp below to point to your source dir.
Additionally, I use Lein, so I have a project.clj at the root of my project; however, there's nothing special or required about "project.clj". You could just as easily put a this.is.a.project.root file in the root of your project, and search for that file.
The following code will search the your source jars for a Java class, and open the first match that it finds (or no match, if no match is found)
<script src="https://gist.github.com/jaycfields/5272391.js"></script>
disclaimer, I'm still an emacs lisp beginner.
The previous code is pretty straightforward. Line 3 uses expand region to mark whatever Java class my cursor is currently on or near. You could type the word instead if you like, this page should help you understand how.
Line 4 and 6 find and verify where the project root lives.
Line 8 (and 9) greps for a string (the Java class) in a directory (my source dir).
Line 10 switches to the grep results.
Line 11 sleeps, waiting for the grep results to return.
Line 12 searches forward, looking for the first match.
Line 13 opens the jar of the first match.
Line 14 assigns the current point to a var named 'current-point'.
Line 15 searches forward to the end of the jar name.
Line 16 grabs the name of the jar and switches to that buffer.
Line 17 searches the jar's dired buffer for the name of the class.
Line 18 opens the first class name match.
(Line 19 lets you know if your project root could not be determined)
That's it, you can now easily find java source (with the occasional conflicting name annoyance). It's not pretty, but it gets the job done.
* I've been told that a few Java modes are good, if I can easily use those to navigate from my Clojure to Java, please leave a link to a manual I can dig into. I assume there are etags solutions, but it's not clear what the best way to go is. I'm sure there's an easy solution for navigating Java from Clojure, I'm just having a hard time finding it.
Posted about 1 month back at GIANT ROBOTS SMASHING INTO OTHER GIANT ROBOTS - Home
Episode 42: Why were you suing a website?:
This week, Ben Orenstein is joined by Peter Moldave, attorney at Gesmer Updegrove to discuss attorney client privilege, what not to do with email, the similarities between lawyers and programmers, how he got into law, his history with technology, and his time as a corporate lawyer at Apple. They also dig into how EULAs work, whether they are binding, whether you should be reading them, and how they can be enforced, software licensing, copyrights and the First-sale doctrine, patent law, software patents, and navigating the patent landscape. They also discuss how to view stock options in your startup job offer, working at startups, how to have a valuable career path, what your employer owns from your side projects or your work for them, how to manage liability in your startup, web site, app on the App Store, and side projects, the best corporate structure and much, much more.
Posted about 1 month back at
Our infrastructure has many cookbooks that aim to be
reusable, primarily through encapsulating behaviour in LWRPs. This led to an
explosion of LWRPs and sometimes the documentation didn't keep up or did just not
exist.
Chef has been evolving rapidly and many of the pain points are being
addressed by Opscode or by the community at large - which is great. However, one
pain point that is not getting easier is writing cookbook documentation. Several
threads came together last week to motivate me to change this.
-
Incorrect documentation of LWRPs contributed to an outage.
-
Mathias Lafeldt wrote a knife
plugin that generates an initial
README.md from the
metadata.rb file in a a cookbook.
-
Other languages/frameworks have tools to generate documentation from annotated source code.
So I decided to try and extend Mathias's work so that I could always regenerate
README.md from the cookbook source code.
knife cookbook doc DIR
As much as possible the plugin makes use of the same metadata as used by chef
when generating the documentation. The plugin will also scan the source files
for annotations present in comments. Users can also add fragments of markdown
into the doc/ directory to merge into the generated README.md file.
The goal is to keep the code as the authoritative source of information. The
hope is that keeping the documentation close to the code will help to maintain
it's currency.
Getting Started
Step 1
Populate the metadata.rb of your cookbook according to Opscode's
documentation. Particular
attention should be paid to documenting the recipes, attributes, platform
compatibility and cookbook requirements (i.e. depends, recommends, suggests etc).
Step 2
At the top of each cookbook, add a detailed documentation section such as;
=begin
#<
The recipe is awesome. It does thing 1, thing 2 and thing 3!
#>
=end
Step 3
In each LWRP, add detailed documentation such as;
=begin
#<
This creates and destroy the awesome service.
@action create Create the awesome service.
@action destroy Destroy the awesome service.
@section Examples
# An example of my awesome service
mycookbook_awesome_service "my_service" do
port 80
end
#>
=end
...
#<> @attribute port The port on which the HTTP service will bind.
attribute :port, :kind_of => Integer, :default => 8080
It should be noted that the documentation of the LWRP requires that the user
document the actions, using @action <action> <description> and the attributes
using @attribute <attribute> <description>. This allows meaningful
descriptions for the actions and attributes to be added to the README.
The other text will be added at the start of the LWRP documentation
except if marked with @section <heading>, in which case it will be added
to the end of the LWRP documentation.
Step 4
Finally the user should add some documentation fragments into the doc/ dir.
Most importantly you should add doc/overview.md which will replace the first
Description section of the readme. The remaining fragments will be included
at the end of the readme in lexicographic order of the filename.
Step 5
Install the plugin and run the knife command, passing the directory of the cookbook as an argument.
gem install knife-cookbook-doc
knife cookbook doc MY_COOKBOOK_DIR
Examples
For an example of a README generated by the plugin, check out the glassfish
cookbook. Unfortunately the plugin highlights the
fact that so much of the cookbook is poorly documented. However there are some LWRPs such as
glassfish_mq that have the
beginning of useful documentation.
Final Thoughts
The plugin is raw but usable now. It needs to evolve to be a more seem-less part of our workflow.
It would also be nice to see it or something more complete be adopted by the rest of chef community.
I wonder what needs to be done to build such a tool?
Posted about 1 month back at GIANT ROBOTS SMASHING INTO OTHER GIANT ROBOTS - Home
Let’s say that we have an app that makes use of image assets for icons, custom progress bars, etc. Now we want to allow users to theme the app, and these images need to conform to this new color scheme. The obvious solution is to add 1x and 2x versions of every single possible image asset in the app, right?
No, of course not. Duplication is bad, and duplicating images is just another form of duplication. But we’re clever folks, I’m sure we can find a nice way around this!
We’ll start out with a simple image that we need to tint to our new color scheme. It has an alpha channel, but it’s a flat color and the new color is going to be flat as well.

The smart way to do this would be to redraw the image using a new color using CoreGraphics. Let’s consider the steps needed to make this happen:
- Create a new image context to draw into.
- Set the new tint color to be the fill.
- Get the image size.
- Draw the source image with the new color while retaining the alpha information.
- Get the image out of the current context and return it.
Looks pretty straightforward, but retaining the alpha channel will likely be the trickiest part of the exercise. Looking into the UIImage documentation, we know we’re going to want to use -drawInRect:blendMode:alpha: to draw the new image. Looking at the available blending modes leaves us a little… confused:
kCGBlendModeSourceAtop
R = S*Da + D*(1 - Sa)
Available in iOS 2.0 and later.
Declared in CGContext.h.
That’s not actually super helpful. Let’s keep reading, I guess.
The blend mode constants introduced in OS X v10.5 represent the Porter-Duff blend modes.
The symbols in the equations for these blend modes are:
R is the premultiplied result
S is the source color, and includes alpha
D is the destination color, and includes alpha
Ra, Sa, and Da are the alpha components of R, S, and D
Ah, ok. So we need to do some translation here. What we’re looking for is a blending mode that will draw the new color (Destination, represented by D) using the alpha components from the source (represented by Sa). Looking through the available options armed with this new knowledge, we find one that looks promising:
kCGBlendModeDestinationIn
R = D*Sa
Available in iOS 2.0 and later.
Declared in CGContext.h.
That looks like it’s using the right components, but there’s only one way to be completely sure. Let’s get ready for some good old fashioned trial and error. First, we’ll go ahead and create a category on UIImage:
// UIImage+Tint.h
@interface UIImage (Tint)
- (UIImage *)tintedImageWithColor:(UIColor *)tintColor;
@end
This feels like a nice interface. We can assume that we will either have the image that needs tinting, or we can simply chain it together with -imageNamed: to grab the image from the bundle. Now for the initial implementation:
// UIImage+Tint.m
#import "UIImage+Tint.h"
@implementation UIImage (Tint)
- (UIImage *)tintedImageWithColor:(UIColor *)tintColor
{
// It's important to pass in 0.0f to this function to draw the image to the scale of the screen
UIGraphicsBeginImageContextWithOptions(self.size, NO, 0.0f);
[tintColor setFill];
CGRect bounds = CGRectMake(0, 0, self.size.width, self.size.height);
UIRectFill(bounds);
[self drawInRect:bounds blendMode:kCGBlendModeDestinationIn alpha:1.0];
UIImage *tintedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return tintedImage;
}
@end
Plugging this into our app is as simple as [[UIImage imageNamed:@"ralph"] tintedImageWithColor:[UIColor thoughtbotRed]];

That was simple enough. But what if we want to retain a gradient from the image? Let’s say we have a nice grayscale button that should be skinned as well:

All we have to do is pass it through our tint method, and voila!

Oops. Looking back at the blending mode, this won’t work at all. The only things that kCGBlendModeDestinationIn takes into account are the destination color, and the source alpha. We’re losing all of the grayscale info from the source image. Looks like we still have more work to do. Once again, we turn to the documentation, and find kCGBlendModeOverlay:
kCGBlendModeOverlay
Either multiplies or screens the source image samples with the background image samples,
depending on the background color. The result is to overlay the existing image samples
while preserving the highlights and shadows of the background. The background color mixes
with the source image to reflect the lightness or darkness of the background.
Available in iOS 2.0 and later.
Declared in CGContext.h.
That sounds like it should tint our gradient nicely. But we don’t want to change the current behavior. This calls for some refactoring. The new interface becomes:
// UIImage+Tint.h
@interface UIImage (Tint)
- (UIImage *)tintedGradientImageWithColor:(UIColor *)tintColor;
- (UIImage *)tintedImageWithColor:(UIColor *)tintColor;
@end
And the new implementation:
// UIImage+Tint.m
#import "UIImage+Tint.h"
@implementation UIImage (Tint)
#pragma mark - Public methods
- (UIImage *)tintedGradientImageWithColor:(UIColor *)tintColor
{
return [self tintedImageWithColor:tintColor blendingMode:kCGBlendModeOverlay];
}
- (UIImage *)tintedImageWithColor:(UIColor *)tintColor
{
return [self tintedImageWithColor:tintColor blendingMode:kCGBlendModeDestinationIn];
}
#pragma mark - Private methods
- (UIImage *)tintedImageWithColor:(UIColor *)tintColor blendingMode:(CGBlendMode)blendMode
{
UIGraphicsBeginImageContextWithOptions(self.size, NO, 0.0f);
[tintColor setFill];
CGRect bounds = CGRectMake(0, 0, self.size.width, self.size.height);
UIRectFill(bounds);
[self drawInRect:bounds blendMode:blendMode alpha:1.0f];
UIImage *tintedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return tintedImage;
}
@end
This gets us closer, but you can see that now we’ve lost our alpha information.

Since kCGBlendModeOverlay doesn’t take the source alpha into account, we need to try to get that back. There’s a very simple way that we can accomplish this. We already know that kCGBlendModeDestinationIn` draws the destination image in the source alpha, so we can conditionally redraw the image using this mode:
// UIImage+Tint.m
- (UIImage *)tintedImageWithColor:(UIColor *)tintColor blendingMode:(CGBlendMode)blendMode
{
UIGraphicsBeginImageContextWithOptions(self.size, NO, 0.0f);
[tintColor setFill];
CGRect bounds = CGRectMake(0, 0, self.size.width, self.size.height);
UIRectFill(bounds);
[self drawInRect:bounds blendMode:blendMode alpha:1.0f];
if (blendMode != kCGBlendModeDestinationIn)
[self drawInRect:bounds blendMode:kCGBlendModeDestinationIn alpha:1.0];
UIImage *tintedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return tintedImage;
}
@end
And we finally have the desired image:

This image is perfect to assign to a static variable to allow it to be used
app-wide, without having to redraw.
By using CoreGraphics to tint our images for us, we open ourselves up to a much wider range of functionality in our apps, and we get the added benefit of smaller bundle sizes, and reduced asset duplication.
Be sure to check out the many different blending modes available in Apple’s documentation. You can check out the sample app that includes the code used here on GitHub.
Posted about 1 month back at GIANT ROBOTS SMASHING INTO OTHER GIANT ROBOTS - Home
We just pushed the latest update to Ruby Science, including three new chapters. Previous purchasers and Prime subscribers can grab the update on Learn.
New chapters this week discuss:
- Using dependency injection to make changes easier and keep decisions close to the objects they affect.
- Inlining classes that no longer pull their own weight to improve readability and simplify dependencies.
- Our first principle chapter, which discusses DRY, including smells and solutions related to detecting and eliminating duplication.
The book is a work in progress, and currently contains around 158 pages of content. Your purchase gets you access to the current release of the book, all future updates, and the companion example application. In addition, purchasers can send thoughtbot their toughest Ruby, Rails, and refactoring questions.
Get your copy of Ruby Science today.
Now Available For Free With Learn Prime
Earlier this week, we announced the launch of our subscription service: Learn Prime.
For just $99/month, you get ongoing access to everything we teach, including books like Ruby Science. You’ll even get access to all our in-person and online workshops. Get access to exclusive subscriber content, as well as access to our private Campfire room, where you can get live help from thoughtbot designers and developers.
Subscribe now.
Posted about 1 month back at Ruby5
Create your indexes concurently with Rails 4, Exceptional joins the Rackspace family, Vagrant abandons rubygems, mobile is just another view into your app, Igata is open sourced, and a fancy teacup for your RubyMotion views all in this episode of Ruby5!
Listen to this episode on Ruby5
This episode is 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.
Concurrent Indexes in Postgres
With Rails 4 you can easily make concurrent indexes in postgres.
Exceptional Joining Rackspace
Exceptional is delighted to announce its range of products has been acquired by Rackspace.
Abandoning Rubygems
Vagrant no longer supports rubygems as an installation method. Find out why in this blog post!
Heroku mobile lead: 'Mobile is not different''
There’s a pervasive myth that traditional web development is dead and that it’s all about mobile.
Igata
Allows developers to create fully realized applications and sell them to non developers.
Teacup
Teacup provides a DSL for easy creation of user interfaces with RubyMotion.
Posted about 1 month back at GIANT ROBOTS SMASHING INTO OTHER GIANT ROBOTS - Home
Hey Denver! Our CTO, Joe Ferris, is going to be in Denver next week and we’d like to have a beer with you. We’ll be joining some of our friends over at SendGrid in their spiffy Denver office for good local beer and a talk on “Improving Performance for Real-Time Requests”.

Joe will be schooling us on how to improve slow requests, avoid duplication, invalidate caches, and refactor for performance within Rails applications.
Leave us a comment with your favorite local beer and we’ll do our best to make sure we have you covered. We’ll also have some nonalcoholic beverages on hand as well.
Our Denver/Boulder team now includes, myself, Corey, Elliot, Sean and a few more starting in the next couple of weeks.
Most of us will be there and we are looking forward to meeting you!
RSVP here.
Posted about 1 month back at Segment7
- home: https://github.com/rdoc/rdoc
- rdoc: http://docs.seattlerb.org/rdoc
- bugs: https://github.com/rdoc/rdoc/issues
RDoc produces HTML and command-line documentation for Ruby projects. RDoc
includes the +rdoc+ and +ri+ tools for generating and displaying documentation
from the command-line.
Changes:
- Bug fixes
- RDoc::Options parser should rescue from OptionParser::ParseError.
- Updated example of RDoc::Options to include reopening RDoc::Options. Pointed out by Michael Granger
- Moved RubyGems documentation installed message into RDoc hook. For RubyGems bug #469 by Jeff Sandberg
- An Error is now raised when a heredoc is not terminated. Fixes exceptions when processing comment blocks. Reported by darix
- rdoc --quiet --no-ignore-invalid now exits for invalid options. Pull request #192 by Jeremy Evans
- RDoc::Parser::C no longer ignores a (METHOD) cast in rbdefinemethod. Pull request #184 by Carlos Agarie
- RDoc::Servlet no longer ignores extra directories from -d. Pull request #173 by Thomas Leitner
- Fixed
rdoc --ri-site. Bug #193 by Michal Papis.
- RDoc no longer attempts to parse binary files. Bug #189 by postmodern, Bug #190 by Christoffer Lervåg, Bug #195 by Aaron Patterson
rdoc --pipe output now contains for markdown compliance.
- RDoc no longer leaves emacs-style modelines in .txt, .md or .rd files. Bug #178 by Zachary Scott
- RDoc no longer puts raw markup in HTML output for markdown input. Bug #204 by Erik Hollensbe
- Code objects with nodoc are no longer included in the ri store. Bug #177 by Thomas Leitner.
- Text#snippet now creates a RDoc::Markup::ToHtmlSnippet correctly.
- The C parser now de-duplicates call-seq if the same C function is used for multiple method names. Bug #203 by Pete Higgins
Posted about 1 month back at Ruby5
This week we have Rails 4 undead cowboys, security updates, custom IRBs, local pull requests, reasons to use Ruby, ways to optimize it and read its documentation, and a couple of great conferences.
Listen to this episode on Ruby5
Rails 4: Zombie Outlaws
This brand new Code School course will run you through all the important changes coming in Rails 4 at a neck-breaking pace.
You can play the first level of the course for free and it's only $25/month to access the rest the course. You'll also gain access to all Code School courses and screencasts if you do so.
Rails Security Updates
David and Chris mentioned last week that Rails 3.2.13 — the last security update — also contained some problematic regressions as well. We wanted to remind you to take a look at Rails 2.3.18 and 3.1.12 which also contain important security patches which you should review. Please take a look at the release announcement we link to in the show notes.
Customize your IRB
Stephen Ball details the ways in which he customizes IRB, for instance he monkey patched the Object class to add a method called interesting_method. This method filters out all the methods that come from the ancestor chain of an object, leaving only the public methods defined specifically on the current object, which when you think about it should be a Ruby default method. He shows a few more
Railsspecific customizations in his blog post, which you should look at.
Checkout Pull Requests Locally
This gist written by Bert Belder outlines how to configure git fetch to include pull requests and how to checkout individual pull requests, which you can then view as branches.
Why Ruby?
If you’re a Ruby programmer, you have probably been asked this question before: “Why Ruby?”. Apparently, it’s something Jeff Atwood (of Coding Horror & Stack Overflow fame) had to deal with when he released Discourse, his recent open source Ruby project. He wrote up a blog post about his decision to use Ruby after years of .NET development. So... if you’re curious about what’s so great about Ruby, give it a read.
Tuning Ruby & Rails for Discourse
Speaking of Jeff Attwood, the Discourse Ruby project Olivier mentioned prompted some interesting notes from Sam Saffron regarding how to optimize Rails and Ruby. The notes are pretty raw but they provide a very interesting look at how to tweak both Ruby and Rails for such a large projects.
pry-doc 0.4.5
The prydoc gem was updated recently with Ruby 2.0 docs and updates to the latest patch levels of Ruby 1.8 and 1.9.
Troubleshooting Gems with Git Bisect
Listener Ben Klang let us know about an interesting post by Justin Aiken on the MojoLingo blog detailing how to use the git bisect command to hunt down bugs in published gems. If you frequently need to find the last known “stable” state of a repository, this is a great tool.
Nickel City Ruby
Nick Quaranto let us know about Nickel City Ruby, the first ever Ruby conference being organized by the WNYRuby User Group in his hometown of Buffalo, New York.
SpreeConf
SpreeConf is happening on May 20 – 21 in Washington, D.C. and you can get a 5% discount on your early bird ticket if you use the code "RUBY5".
Posted about 1 month back at GIANT ROBOTS SMASHING INTO OTHER GIANT ROBOTS - Home
Redis is a fantastic lightweight key-value store. It also acts as a data structure
server for storing data types like lists, sets, and hashes.
With Redis we can create sets to group records together based on time. The
sunion operator then enables us to group multiple sets together based on a
particular time frame.
Example application
Search flights based on a departure city, arrival city, and the date/time
of departure.

| Id |
Departure Time |
Airline |
Departure City |
Arrival City |
|---|
| 1 |
03/23/2013 1:30 pm |
Virgin America |
Los Angeles |
New York |
| 2 |
03/23/2013 1:45 pm |
Virgin America |
San Francisco |
New York |
| 3 |
03/23/2013 1:45 pm |
American Airlines |
San Francisco |
New York |
| 4 |
03/23/2013 1:50 pm |
American Airlines |
Los Angeles |
Boston |
| 5 |
03/23/2013 2:45 pm |
Southwest |
San Francisco |
New York |
| 6 |
03/23/2013 3:30 pm |
Southwest |
San Francisco |
New York |
The flight data is stored as strings in Redis using key-value pairs with the
following key structure:
get flights:1
"1, Virgin America, 03/23/2013 1:30 pm, San Francisco, San Diego"
get flights:2
"2, Virgin America, 03/23/2013 1:45 pm, San Francisco, New York"
...
get flights:6
"6, Southwest, 03/23/2013 3:30 pm, San Francisco, New York"
Group flights by departure time
To group flights by departure time we’ll create a Redis set for each hour of the
day, and flights will be added to the appropriate set based on its epoch
departure time.
smembers departure_time:1364068800:flights
1) "1"
2) "2"
3) "3"
4) "4"
smembers departure_time:1364072400:flights
1) "5"
smembers departure_time:1364076000:flights
1) "6"
Group flights by city
Flights will also be grouped into sets based on their departure and arrival cities.
The city names have been parameterized to keep a consistent key structure.
Departing flights:
smembers cities:los-angeles:departures
1) "1"
2) "4"
smembers cities:san-francisco:departures
1) "2"
2) "3"
3) "5"
4) "6"
Arriving flights:
smembers cities:boston:arrivals
1) "4"
smembers cities:new-york:arrivals
1) "1"
2) "2"
3) "3"
4) "5"
5) "6"
Find flights from San Francisco to New York
To find all flights departing from San Francisco and arriving in New York we can
use sinter to get the intersection of two sets.
sinter cities:san-francisco:departures cities:new-york:arrivals
1) "2"
2) "3"
3) "5"
4) "6"
However, this technique does not allow us to filter flights over a range in time.
To find flights departing on 03/23/2013 between 1:00 pm and 3:00 pm, we’ll need
to group the sets of departure times, and then perform an intersection with
the resulting set.

- Create a new
temp_set using sunionstore to group flights by departure time.
- Intersect the temporary set with the departure and arrival sets.
- Loop over the results of the intersection and generate an array of flight keys.
- Use mget to fetch all the flight data.
We’ll use a combination of Ruby and Redis to achieve this:
# flight_finder.rb
class FlightFinder
def initialize(attrs)
@arrival_city = attrs.fetch(:arrival_city).parameterize
@departure_city = attrs.fetch(:departure_city).parameterize
@window = attrs.fetch(:window)
end
def flights
redis.mget(*flight_keys)
end
private
attr_reader :arrival_city, :departure_city, :window
def flight_keys
flight_ids.map { |id| "flights:#{id}" }
end
def flight_ids
redis.multi do
redis.sunionstore('temp_set', *departure_time_keys)
redis.sinter('temp_set', departure_cities_key, arrival_cities_key)
end.last
end
def departure_cities_key
"cities:#{departure_city}:departures"
end
def arrival_cities_key
"cities:#{arrival_city}:arrivals"
end
def departure_time_keys
window.range_keys { |epoch_time| "departure_time:#{epoch_time}:flights" }
end
def redis
Redis.current
end
end
We’ll introduce the concept of a window to avoid a long parameter list,
and group parameters that naturally fit together. This allows us to encapsulate
behavior between the start_at and end_at attributes.
# window.rb
class Window
ONE_HOUR_IN_SECONDS = 3600
def initialize(start_at, end_at)
@start_at = convert_to_epoch(start_at)
@end_at = convert_to_epoch(end_at)
end
def range_keys
(start_at...end_at).step(hour).map do |epoch_time|
yield(epoch_time)
end
end
private
attr_reader :start_at, :end_at
def convert_to_epoch(string_or_time)
DateTime.parse(string_or_time).to_time.to_i
end
def hour
ONE_HOUR_IN_SECONDS
end
end
Create a command line script.
# flights.rb
require 'flight_finder'
require 'window'
window = Window.new(
start_at: 'March 23, 2013 1:00 pm',
end_at: 'March 23, 2013 3:00 pm'
)
flight_finder = FlightFinder.new(
departure_city: 'San Francisco',
arrival_city: 'New York',
window: window
)
puts flight_finder.flights
Run the command line script.
$ ruby flights.rb
2, Virgin America, 03/23/2013 1:45 pm, San Francisco, New York
3, American Airlines, 03/23/2013 1:45 pm, San Francisco, New York
5, Southwest, 03/23/2013 2:45 pm, San Francisco, New York
Takeaways
- Use sunsionstore to create new sets on the fly.
- Set intersection is a powerful filtering technique.
- Redis data structures are fantastic for slicing and dicing data.
Written by Harlow Ward.
Posted about 1 month back at GIANT ROBOTS SMASHING INTO OTHER GIANT ROBOTS - Home
Episode 41: This is the sausage being made:
This week Ben Orenstein in joined by thoughtbot CEO, Chad Pytel, to discuss thoughbot’s books, online and in-person training programs, other educational products, and the launch of thoughtbot’s new subscription to everything they teach, Learn Prime. They also discuss some changes to apprentice.io, Five Guys, and much more!
Posted about 1 month back at GIANT ROBOTS SMASHING INTO OTHER GIANT ROBOTS - Home
Today we’re happy to announce Learn Prime, a subscription service which gives you access to everything we teach. Your monthly $99 subscription gets you ongoing access to all of our books, screencasts, and even all our in-person and online workshops. Our workshops alone are normally over $1,000 when purchased individually!
In addition to our existing materials, we’ve created a new stream of articles only available to subscribers called Learn Bytes. We’ve already published Bytes on using subdomains in Rails, tricks for finding where a method is defined, and faking out a remote service using rack-test, with much more to come.
Subscribers also receive access to something we (humbly) consider the best resource of all: our team. Got a burning Ruby question? Need help testing something tricky? How about another set of eyes on a pull request? Head to our private Campfire room or send an email, and a thoughtbot developer will help you out.
Our goal is to create more great designers and developers. We hope this new subscription service makes our workshops and other learning materials available to even more people.
We’re are also introducing Prime for Teams. For $1999/month your entire team of up to 25 people can get access to everything provided by Prime. That’s less than the cost of your team’s daily pourovers! And for a limited time, as a special launch discount, the price for Prime for Teams is only $1299 per month!
We hope you’ll join the community of people who have already subscribed to Learn Prime. Find out more at Learn.
Posted 2 months back at Ruby5
Searching your gem code, customizing your IRB, dealing with flashes and sessions on a mixed-version load balanced rails upgrade, RTanque, 3.2.13 performance regressions, Chart.js, and other goodness on this edition of Ruby5
Listen to this episode on Ruby5
This episode is sponsored by New Relic
By now you’ve seen how awesome NewRelic is for your web apps, but if you develop for mobile phones, you’ve been missing out on those kinds of metrics.
Until now – NewRelic can peer inside your mobile apps and tell you whats going on... before angry customers do. Don’t wait until you start stacking up the 1-star reviews to find out whats going on inside your mobile app... know your apps performance in real time.
When it comes to monitoring your mobile app – visibility is a game changer. And as always, your free account is waiting for you at NewRellic.com
Backbone 1.0
It took two and a half years, but backbone is now at a 1.0 release. If you haven't checked it out yet, you should... there will be at least one question about it on the exam.
Searching Bundled Gems
How do you search through the source of your bundled gems? Jim Gay wrote an article about using The Silver Searcher to do just that.
Customizing IRB
Stephen Ball wrote this article on customizing your IRB. I particularly like his object.interesting_methods trick. That one's goin' into the act.
rails_4_session_flash_backport
How do you take a 7 year old rails codebase, and upgrade it from v2.2 without any downtime? Well, if you can have a load balancer with several app instances, and roll out your upgraded app on just one of them, you can introduce it piecemeal...
Oh... except You can't run Rails versions side by side like that because of session incompatibilities.
This gem helps with that.
flatui-rails
You kids today... When I was your age the whole Web was flat! And we liked it! Then came along all your animated gifs and spinners and 'under construction' signs... on and on in an endless progression resulting in reflections and bevels and throbbing jellybeans you all called "web 2.0".... BAH!
Flat is back. Check it out.
RTanque
Do you have grand plans to take over the world? You can prototype your robot brain here, and battle them against other robot brains.
The premise is simple, and its fun! You subclass an abstract robot brain, and add behavior to a 'tick' method. You decide how to scan when and where to move, where to point your gun, and how much energy to fire with while your opponents do the same. Last robot standing wins.
Rails 3.2.13 Regressions
If you ran like a lemming to upgrade to 3.2.13, you might have seen some problems... here's a recap.
chart.js
Nick Downie has released a pretty cool charting library in javascript. Check out the demo page - the subtle default animations are pretty nice.
Posted 2 months back at Nuby on Rails
This article is heavily styled and is best viewed at PeepCode!
by
Geoffrey Grosenbach
and
Paula Lavalle

From the It Just Makes Sense department

Stream to your Apple TV! We’re watching Play by Play with Corey Haines and Aaron Patterson.
As a bootstrapped company, it’s not always clear what the next step is, but an iOS app for viewing PeepCode videos has been one of the longest standing requests we’ve received. Which makes sense! It’s almost as if these devices were perfectly designed for watching PeepCode videos. The new iPhone 5 is the right dimensions for displaying HD video, which is what all our new videos have been filmed in since the end of last year (and some before that).
So we (finally) took the plunge and built an iOS app. We worked with expert iOS developer (and PeepCode author) Alex Vollmer of Radiant Capsule, and while he did most of the heavy lifting we certainly put in a lot of work and learned a lot along the way.
Solving the Progress Bar Problem

Download progress shows both percentage and remaining MB.
Desiging a good progress bar is famously difficult. Given that our audience is technical and speaks MB and GB, we settled on a great solution that works specifically for the content we’re delivering.
We decided to combine a standard progress bar with a numerical percentage. This works well for any videos under 100MB. But large videos might appear to be stalled if we can only show 100 points of progress. If a video is 500MB, it might take a minute or more to download 1/100th of it (5MB) and show progress.
So we also show you the number of MB remaining. This gives visual feedback that’s useful for videos larger than 100MB. The end result is that for any video you’ll download, progress is frequent and keeps you updated.
Delivering Instant Gratification

The UI shows progress in two steps.
One of the things we find frustrating about video streaming applications is all the waiting.
Starting an HTTP video stream can involve an API call, requests for 2 metadata files, and another request for a media file…all before you see a single frame of video.
We wanted to improve on that by showing you some progress along the way. So you’ll see an initial spinner when you click the “Play” button on the cover. When the first API call has completed, you’ll be taken to the video player where the video will start to stream.
Splitting progress into two visual steps makes the application feel more responsive than it would if we just sent you directly to the video player where you would have to wait for 5 or 10 seconds. It’s part of the attention we’ve put into the UI of this application to make it enjoyable to use.
Note: Video streams start at low quality while the device figures out what bandwidth is available. If you have a good Internet connection, you’ll see better quality video after a few seconds. We’re working on adding full HD streams to videos, too.
The Value of a Flaky Development Server
It’s not easy to bootstrap a multimedia application that requires client, server, and media.
Due to misbehaving third-party libraries, our first implementation of a video streaming server would sometimes monopolize 100% of the server’s CPU and hang, or never return a response at all. This was bad news for the iOS client application since it couldn’t get the data it needed to start streaming a video.
Or was it? The early flakiness forced Alex to add more error checking code to the iOS client, and better error messages for the user. And it forced us to write the server code to look for timeouts or blank API responses. Overall, it made our code more robust.

Brother Baba Budan, Melbourne
And yes, we rewrote the server so it doesn’t use 100% CPU anymore. In fact, it’s been smooth sailing since the launch.
Keeping it Simple
We’ve launched version 1.0 with a simple but straightforward feature set: PeepCode Unlimited subscribers can download or stream any video we’ve published in the last two years. We’re starting with only PeepCode Unlimited subscribers so we can fine-tune our streaming infrastructure and determine what mirrors we need around the world for a top notch download and streaming experience. So far everything has been running very well.
Anyone with a PeepCode account of any kind can use the app to stream previews of current videos.
Interesting Features
- The app will remember the playback time of each video you’ve watched. If you have iCloud, it will sync that across all your devices. So you can watch part of Play by Play with Aaron Patterson and Corey Haines on your iPhone, then resume watching on your iPad at the same time in the video.
- We’ve done extensive testing, literally all around the world (Seattle, Melbourne, Kauai, San Francisco). We hope to add video streaming mirrors for an even better experience.
- Stream to your AppleTV with AirPlay. Play by Play looks fantastic on an HDTV.
- Smart download doesn’t drain your battery if you leave the app. It resumes when you’ve re-launched the app and are back in Wi-Fi range. (Our developer tested this by walking down the street until he was out of range).
- Download full quality videos or stream up to half resolution. Our new HD videos look amazing on the iPhone 5!
- We built a custom, self-contained Sinatra server for streaming video. This will make it easier for us to deploy extra streaming or download servers around the world or whenever needed.
- A series of command line scripts together with remote APIs makes it a breeze to encode video for all the necessary formats and copy it to our servers.
Try it!
We’re proud of this application, our first shipping iOS application. For a 1.0, it covers most of what’s needed for a great mobile experience.
Possibly the best evidence of how useful this application is was how much we started using it in-house! On the bus, at home streamed to an Apple TV, or on a plane. The last three months of rigorous testing and refinement have been a lot of fun.
Try it out with any PeepCode account. Or upgrade to PeepCode Unlimited for full-length streaming!
Did you know…if you’ve ever had a PeepCode Unlimited subscription, you can renew now for only $109! Or tell your employer to contact us for a business subscription.


Watch on the iPad, too!