On Vinaigrette and Company Culture

Nothing beats a fresh vinaigrette on mixed greens. It’s really easy to make if you follow some simple rules. The key to the making vinaigrette is to create an emulsion.

It isn’t everyday that I get to use my degree in Chemical Engineering, but the idea when you make an emulsion is that you are combining two liquids that normally wouldn’t mix, like oil and water. In the case of our vinaigrette, we might be combining lemon juice, balsamic vinegar, or some other water-based ingredient with olive oil.

The key to emulsifying is to slowly incorporate the oil into the lemon juice, while vigorously whisking. Incorporating slowly, the tiny little oil molecules are able to mix in with the water molecules and what you end up with is something wonderful, that is neither lemon juice or oil. Dump the oil in too quickly, or don’t allow the oil time to be incorporated, and you end up with an oil slick.

I’ve been thinking about this and how it relates to company culture. Smart companies hire smartly (the first rule of Tautology club is the first rule). Hiring smartly often means hiring slowly, even when you feel you need to add lots of smart people. Hiring slowly allows new team members to become part of the existing structure and values, while still being able to impart their own flavor and characteristics, just like our vinaigrette. Add too many people at once, even smart people, and suddenly you lose cohesion and you are left with a fragmented set of values, like a vinaigrette that has “broken”.

Sometimes you have no choice in the matter, particularly in this day and age of acqui-hires. Suddenly the team grows. How can you do it and maintain the values and strengths of each team? Ideally you still try and do it slowly, but sometimes that’s not an option. What can you do in those cases where you just have to throw the teams together.

Start by allowing each team or group to learn more about the other’s strengths and weaknesses. Have honest, open communication about what’s working well and areas that deserve special attention. Share lessons learned and core values through presentations, brown-bags, and pair-programming. Carefully form project teams with members from different groups that might provide an example for others to follow. And please, please, please don’t deliver your core values from on high. Nobody needs slogans.

And don’t forget to pay attention to the little things too. What is the new office environment like?

  • Is the space “vibrant” or “noisy”.
  • Are people from different teams interacting, going to lunch together?
  • Are the “new people” getting “new equipment” or other special treatment.
  • Does the “old guard” have the ear of management.

Remember, perception is reality.

On Working Remotely

I don’t know if you’ve heard, but we’ve had some historic snows here in Boston, that have had a “slight” impact on public transit and just getting around in general.

I have always felt that being in the office is key to being effective as a software developer.  So much of what we do is about communication. How can we do that without being face-to-face with a customer or coworker?  How can we do that without being able to seamlessly share code, ideas, nuance.  Although I have worked from home from time to time due to weather or other conflicts, I always thought friends who worked primarily from home were probably stretching the truth a bit about how effective they could be working remotely.

After a couple of weeks working primarily from home, I have changed my tune.

The quality of tools available to facilitate remote work amazes me.  It seems like in just the last 2-3 years they have grown in leaps and bounds. I am a big fan of Screenhero and Slack, and am delighted that they have combined forces. What truly amazes me is the way these tools facilitate multi-user (more than 2 people) support.  Throw in the odd, Google Hangout, Goto Meeting, Join.me and there are so many ways that we can now communicate effectively from anywhere.

I still prefer working in the office.  I like my coworkers (no, really), and in my opinion there still is no substitute for a true face-to-face conversation.  I like socializing and grabbing lunch with friends.  But I can now envision a time when I can make working remotely a significant part of my typical work-week.

There are some potential drawbacks. ¬†I notice I take fewer breaks when I am working remotely, and I think periodically stepping back is a big part of solving hard problems. ¬†I also worry about the overall impact on work-life balance when it is so easy to always being “available”. ¬†But these are solvable problems, like someday people being able to decide on their own what can of tomatoes to buy without calling home when¬†the low-sodium kind aren’t available at the market.

I think the ideal situation for me would be 2-3 days/week in the office, especially if that is coordinated with other peoples remote schedules. That would seem to allow for the most effective face time, reduce time wasted on commuting, and allow for significant chunks of uninterrupted time.

Getting Started with Haskell – Comprehending List Comprehensions

As promised, we are now in the Season of Haskell.  I decided to spend this week with some baby steps and also try to figure out what resources to use to get started.  I had heard good things about Learn You a Haskell For Great Good and Real World Haskell.  I felt like reading the first few chapters of each would give me a feel for the book styles and let me narrow my focus.

I have to say that there are certainly some neat things that Haskell can do in a fairly terse syntax. List comprehensions are pretty cool. There is an example in Learn You a Haskell that allows you to find all the right triangles with a hypotenuse less than 10 in one (fairly) simple line, once you start to grok the syntax.

[ (a,b,c) | c <- [1..10], b <- [1..c], a <- [1..b], a^2 + b^2 == c^2] 

What this says is get me the list of points, actually tuples, (a,b,c) where

  • c is drawn from the range 1..10
  • b is drawn from a range¬†of 1..c
  • a is drawn from a range¬†of 1..b
  • and the predicate function a^2 + b^2 == c^2 is applied to test that it is a right triangle

The result is [(3,4,5),(6,8,10)]

Versus something like this in Ruby

rightTriangles = []
(1..10).each do |c|
  (1..c).each do |b|
    (1..b).each do |a|
      if (a**2 + b**2 == c**2)
        rightTriangles << [a,b,c]
      end
    end
  end
end

Obviously Ruby has a lot of other strengths going for it, but clearly this is the type of problem where functional languages may shine. And who knows, there may be ways to bring some of these ideas into my Ruby programming. Might be a good time to re-watch Pat Shaughnessy’s talk on Functional Programming and Ruby.

I’m curious to see what comes next.

Book Review – Effective Ruby by Peter J. Jones

Effective Ruby

One of the great strengths of Ruby is that it is easy to pick up and be productive right out of the gate. But¬†Ruby is such a rich, full-featured language that there are probably a lot of things you aren’t aware of that can make you a better developer.

I recently received a copy of Effective Ruby by Peter J. Jones, and I really enjoyed it.  This book is a good addition for beginner and intermediate Ruby developers to learn more of the language features and write better, more maintainable code.  The author has geared the book towards people who have some experience with Ruby and points out some of the common pitfalls that developers new to Ruby might face.

The book has 48 items to help you improve your code and covers everything from Ruby basics to an overview of the garbage collector. ¬†As someone who has been using Ruby for a few years, I learned a few¬†new things about collections, Ruby’s inheritance hierarchy, exceptions, and performance tips.

I thought the section on testing was a little thin, but there are entire books dedicated to testing and it is a tough topic to address in a single chapter. ¬†I think the author’s intention is just to make the reader aware of the testing tools and methodologies available.

All in all, I thought this was a good read. ¬†I’ll keep it handy and look forward to applying and experimenting with some of the ideas.

It’s Time To Go Functional

It was 3 years ago that I embarked on a learning adventure with Ruby and Rails, my Season of Ruby, that would change my career in ways that I could not imagine at the time. The Pragmatic Programmer¬†recommends learning one new language a year, and though I’ve added a few languages and frameworks since then, Javascript and AngularJS to name a few, I’ve never learned a purely functional language.

My experience in programming to this point has been procedural (way back in C and assembly) and¬†object-oriented (C++, C#, Java, Ruby). ¬†I have no experience in functional programming, and I wonder if that leaves a gap¬†in the tools I have in¬†approaching a problem. ¬†I have no idea where this will lead, or how this might change me as a developer, but that’s fine. ¬†It worked out ok last time with Ruby.

My motivation behind this is strictly to learn a new way to think about and solve problems, not find a shiny new language/framework to land a new gig.  For that reason I am planning on learning a pure functional language, most likely Haskell. Having talked to a few people there are other options out there, but Haskell keeps coming up as the top choice if you want to learn the concepts of functional programming.

I’m planning on starting¬†out with Learn You A Haskell For Great Good. ¬†It is a resource that has popped up in discussions and threads as this idea has festered in my brain, but if folks have other ideas I’d love to hear them.

Stay tuned, someday soon I may actually understand what a monad is.

 

Previewing emails in Rails applications with the mail_view gem

Mailer specs are a great to verify that the emails sent from your Rails applications have the required data, links, and important content. But often a developer, or more likely the product owner, may want to see the emails to make sure they are properly formatted, read well, and are free of spelling errors.

Getting your application to send an email from a development or staging environment can be an onerous task depending on how much user workflow and data setup is required for a given email. This is where the mail_view gem can really help you out.

The mail_view gem lets us easily preview emails right from within your Rails application running in the development environment

Using mail_view in Rails 4.1+

Configuring mail_view

mail_view is built into Rails 4.1+, so there is no additional setup or configuration to start using it.

You can read more about support for mail_view in Rails 4.1 in the following links

Edge Guides Release Notes

ActionMailer API Docs

Setting up emails to preview

By default, Rails 4.1 expects the mail preview classes to be located in the test/mailers/previews directory. If you use the mail generator, a preview file will be created for you automatically. You create a class that inherits from ActionMailer::Preview for each email to be previewed.

class WelcomeMailerPreview < ActionMailer::Preview

  def welcome_investor
    user = User.last
    WelcomeMailer.welcome_investor(user)
  end

end

Previewing the emails

Browsing to http://localhost:3000/rails/mailers/welcome_mailer/welcome_investor will show you a preview of the email. But before you do that you will probably need to set up some data for the preview

Using mail_view in Rails prior to 4.1

Configuring mail_view

For Rails versions prior to 4.1, there is just a little work to do to get set up.

First you will need to add the gem to your Gemfile.

gem "mail_view", "~> 2.0.4"

Then you mount the mail_view engine into your application via the routes.rb file.

  if Rails.env.development?
    mount MailPreview => 'mail_view'
  end

I wanted to make the mail_view available on my staging server, so I used an environment variable to enable it.

  if Rails.env.development? || ENV["PREVIEW_EMAIL"] == "true"
    mount MailPreview => 'mail_view'
  end

With the engine mounted at mail_view, browsing to http://localhost:3000/mail_view will present us with a list of emails to preview. But before we do that, we need to set up the emails to preview.

Setting up emails to preview

You set up the emails to preview by creating a class that inherits from MailView

class MailPreview < MailView

  def welcome
    user = User.last
    WelcomeMailer.welcome_investor(user)
  end

  def payment_confirmation
    payment = Payment.last
    PaymentConfirmationMailer.confirmation_email(payment)
  end

  def contact_us
    ContactMailer.contact_email("Joe Smith", "617-555-1212", "jsmith@example.com", "I have a question...")
  end

Listing the emails

Now that we have some emails to preview, we can browse to http://localhost:3000/mail_view will present us with a list of email preview links as defined in the MailPreview class.
Mail Preview List

Providing data for the emails

Typically our emails are working with data from our database. The mail_view documentation describes some of the ways you can provide data to the mailer, using either actual data from the database, using a factory pattern, or providing a stub.

In the examples above, I am using data from the database. Each approach has its advantages and disadvantages, and it really depends on how you data is structured as to which approach you use. You can also mix and match the different approaches as you see fit.

Viewing an email

mail_view displays a preview of the email with the header information shown in the page header and the body in an iframe, as shown below.
Mail Preview As HTML

If you have provided a text and html template for the email, a drop-down is displayed in the page header to allow you to preview the different formats. Here we are displaying the text version of the email
Mail Preview As Text

Since the body of the email is displayed in an iframe, clicking on a link in the email will open the link inside the iframe.
Mail Preview Open Link

Summary

The mail_view gem is a great tool to allow you to visually inspect the emails sent by your Rails application.

Responsive Design Comparison: Neat vs Foundation

In the interest of improving my design skills, I wanted to brush up on a couple of different grid-based systems that provide responsive design capabilities. ¬†There are several to choose from, but I settled on trying out thoughtbot’s neat¬†library and Zurb’s Foundation framework. ¬†Along the way, I also got a chance to play around with thoughtbot’s Bourbon library.

Just The Grid, Thanks

Now first off, comparing neat to Foundation is like comparing apples to fruit salad.  neat is strictly a grid system, it is not a full-blown framework, like Foundation.  There is a time and a place for either approach, but since I wanted to focus primarily on how the two grid systems work I think it is mostly a fair comparison.

I developed two bare-bones apps that just let me play around with the grid system and some basic styling.  All I really wanted to do with the apps was to have a few static pages, see how the grid system layout worked, and how it responded to different screen sizes (desktop, tablet, phone).  The apps can be found here.

These apps are a simulation for a wine store application. ¬†Again, wasn’t going for a full functioning app. ¬†Just wanted the following features in the demo apps

  • Page header with some simple navigation links
  • Home page with a grid-based sections for “Staff picks” and “Calendar of events”
  • Responsive design to change the layout for desktop/laptop, tablet, and phone contexts

tl;dr

Either neat or Foundation is a solid choice for a grid system.  Both default to 12-column grids, and can configured to support other layouts.  Both are really easy to integrate into a Rails application.  Both also have good documentation, though I might give Foundation a slight nod there.

As far as just the grid system, my preference would be for Foundation. ¬†For me, the syntax of defining the grid system seemed a little more straightforward. ¬†I also liked that when nesting, the child elements don’t need to know about the number of columns in the parent.

Going with a full framework also brings some extra functionality. ¬†I was able to play around with¬†the block grid,¬†the top-bar navigation, and the easy to set up “hamburger” menu icon. ¬†I think it has really solid documentation as well.

Now let’s get to the details…

neat

neat defaults to a 12-column grid, which I like a lot since your sections can easily switch between multiples of 3 or 4 without changing the overall number of grids.  You have the ability to configure the number of columns you want the grid to have, but I had no reason to want to do that with what I was doing.

A grid region is defines using the outer-container mix-in.  According to the neat docs, you can have multiple outer-containers on a page, however they can not be nested.  Given the simplicity of my app, I just threw it on the body element.

body {
  background-color: $background;
  color: $text;
  font-family: 'lato';
  @include outer-container;
}

The span-columns mix-in is used to specify how many columns an element should span. ¬†If the element is nested, you must also specify the number of columns its parent element contains, for example,¬†@include span-columns(4 of 8) specifies that the element takes up 4 columns of an 8 column parent. ¬†I personally found having to specify the parent information to be a bit of a nuisance, and one where neat and Foundation differed. ¬†It wasn’t a show-stopper, but I didn’t like having to concern myself with it.

Responsiveness is attained using the media mix-in.  Inside of the block for the media mix-in, you can define the features for that context.  This allows you to redefine columns, font sizes, whatever for that particular context, e.g. tablet or mobile.  This gives you a lot of control, but to me felt a little heavy. Here you can see where I define that an element normally spans 4 of 8 columns, but for the tablet and mobile contexts spans 4 of 4 columns.

.staff-pick {
  @extend .tile;
  @include span-columns(4 of 8);
  @include omega(2n);
  @include media($tablet) {
    @include span-columns(4 of 4);
    @include omega();
  }
  @include media($mobile) {
    @include span-columns(4 of 4);
    @include omega();
  }
...
}

You can also change the width for when the context switches as well as the number of columns in the grid for the context using the new-breakpoint mix-in.  For my application, I went with an 8 column tablet breakpoint and a 4 column mobile breakpoint.

$tablet: new-breakpoint(max-width 900px 8);
$mobile: new-breakpoint(max-width 600px 4);

I think one of the strengths of neat may be that you have very fine-grained control or the grid and underlying elements through the multiple mix-ins it provides, but that will also take a little more work (or familiarity on neat) on your part.  I also found it required reading both the gem docs on github and the neat page docs to fully understand how to set it up and get running.

Foundation

As I said earlier, Foundation is a full blown framework, along the same lines as Twitter Bootstrap.  You get the grid system, but also navigation elements, buttons, forms, controls of all different kinds, alerts, drop-downs, and on and on.  But for the purposes of this comparison, I wanted to concentrate primarily on the grid system.

Like neat, Foundation uses a 12-column grid, and like I said earlier, a 12-column grid has a lot of advantages.  You can also customize the number of columns in the grid system, but the default was fine for what I was doing.

Foundation uses a different format for specifying the grid layout. ¬†Rather than try and spell it out in all it’s detail, take a look at the grid documentation. ¬†Overall, I found the ability to specify the columns all on one line more readable than the way neat does it.

To define an element that spans 4 columns for large screens and 2 for mobile, you would do something like this

<div class="row"> 
  <div class="small-2 large-4 columns">...</div>
  ...
</div>

Whereas with neat, you would do it this way

  .some-style {
    @include span-columns(4);
    @include media($mobile) {
      @include span-columns(2);
    }
  }

Foundation also has some nice features that make layout a lot easier, IMO. ¬†My toy app had a section for “Staff Picks” that displayed a bunch of wines in a grid layout. ¬†With Foundation, I could use the Block Grid¬†feature to easily lay out the grid based on the screen size.

<div class="row">
  <ul class="small-block-grid-1 medium-block-grid-1 large-block-grid-2">
    <% @reviews.each do |review| %>
       .......
    <% end %>
  </ul>
</div>

Now in 1 line, I can easily see that the block-grid will have

  • 1 review per row for a small screen
  • 1 review per row¬†for medium screen
  • 2¬†reviews per row¬†for large screen

Foundation also provides some easy mechanisms to implement a “hamburger menu” (the three vertical bars) for the navigation links when going to a small screen, using the¬†class=”toggle-topbar menu-icon” line.

<nav class="top-bar" data-topbar>
  <ul class="title-area">
    <li class="name">
      <h1><%= link_to "Denomy's Wine Emporium", root_path %></a></h1>
    </li>
    <li class="toggle-topbar menu-icon"><a href="#"></a></li>
  </ul>
  <section class="top-bar-section">
    <ul class="right">
      <li><%= link_to 'Home', root_path %></li>
      <li><%= link_to 'About', about_path %></li>
      <li><%= link_to 'Help', help_path %></li>
    </ul>
  </section>
</nav>

Foundation also provides a lot of tools for handling nesting, offsets, incomplete rows, and other potential gotchas that really look great for helping to manage the grid.

Given that you get a lot of other features with it, like forms, alerts, drop-downs, etc, I am really starting to look forward to using Foundation more in the future.

It wasn’t all perfect, there were some annoying things. ¬†For instance, I was unable to use a linear gradient in the header bar, but for the most part it was pretty easy to work with.

Adding In a Splash of Bourbon

I am happy to say that it was easy to use both neat and Foundation in a Rails app with Bourbon.  Bourbon has some a really rich set of SASS mixins that can be used to customize the look of your app.

Programmatically Clearing the Facebook Share Image Cache

When you share a URL on Facebook, it scrapes the page for the URL for the Open Graph data to determine what image/video to display.  Facebook caches the image for that URL, so if you change the image and then share the same URL at a later time, the old image will still get displayed, which is probably not what you want to do.

Facebook provides the Open Graph Debug Tool that can be used to manually clear the cached value for the URL, but that may not be a workable if your website allows images to be changed dynamically.  Ideally, you would want a way to programmatically clear the cache after the associated image is changed.

Fortunately, there is a way to clear the cache using the OpenGraph API¬†by forcing a scrape of the URL. The key is to set the ‘scrape’ parameter to true in the API call. The following Ruby code assumes that the Facebook application id and secret are stored in environment variables.

facebook_open_graph.rb

module FacebookOpenGraph
  def self.clear_cache(url)
    params = {
      :client_id => ENV['FACEBOOK_APP_ID'],
      :client_secret => ENV['FACEBOOK_SECRET'],
      :grant_type => "client_credentials"
    }
    uri = URI("https://graph.facebook.com/oauth/access_token?#{params.to_query}")
    response = Net::HTTP.get(uri)
    access_token = Rack::Utils.parse_nested_query(response)["access_token"]
    unless access_token.nil?
      uri = URI('https://graph.facebook.com')
      res = Net::HTTP.post_form(uri, 'id' => "#{url}", 'scrape' => 'true',
          'access_token' => "#{access_token}", 'max' => '500')
    end
  end
end

Then to clear the cache you merely need to call the clear_cache method, passing in the URL being shared.

FacebookOpenGraph.clear_cache("http://myurl.com/some_cool_page")

Aikido, Controller Tests, and LinkedIn at Launch Academy

I had a nice visit the other day speaking at Launch Academy. ¬†It’s no secret that I am a big fan of the program. ¬†As a community, we need to do more to produce good entry-level developers and also to help them develop their careers.

My talk was geared towards preparing them for what happens when they leave Launch Academy and some of the things they can do to continue learning and growing as software developers. ¬†The three topics: Aikido, Controller Tests, and LinkedIn don’t seem to have anything to do with one another, but let’s look a little closer.

Aikido

I don’t know the first thing about aikido, but I do know of a talk that Alistair Cockburn gave where he talks about aikido and the three stage of learning: Shu, Ha, and Ri. ¬†These stages of learning are common to almost any endeavor, including software engineering. ¬†Right now, the students at Launch Academy are in the¬†shu phase, learning a single technique from their masters.

When they go out into the world, they will be exposed to new techniques and new masters, and it is their responsibility to be open to these new techniques, try them out, and incorporate them into their own practices.  This is the ha phase.

With some hard work, practice, and luck they may reach the ri phase, where they are inventing their own techniques, but that wasn’t part of my talk.

I highly recommend the talk by Alistair Cockburn, it covers so many great ideas about developing your craft.  He is an amazing guy and his talks are always engaging.

Controller Tests

I have been thinking a lot lately about controller tests in Rails.  What value do they serve, are they still worth writing?  This is probably the subject of another blog post or series of posts, but in the talk I wanted to tie it in with the concept of shu-ha-ri and being open to new ideas.

When I first started learning Rails, one of my primary resources was Michael Hartl’s amazing tutorial. ¬†So many of us owe him so much for showing us the way into an awesome framework. ¬†At the time I was learning, I recall the tutorial having a fair number of controller tests, and those tests became part of my shu¬†learning phase of Rails.

As I started to develop more Rails apps, and getting exposed to more practices and techniques, I was forced to rethink the role of controller tests.  I found some of the ways I was using them had little intrinsic value.  In some cases, they were essentially testing the framework (e.g. index action rendering index template) or were a mix of controller and view tests that were brittle and not as comprehensive as a Capybara feature spec.

Taking a ri approach, I have adapted my practices to do more outside-in tests.  These have the advantage of reinforcing the customer experience and keep me from diving too deep too soon.  They allow me to explore the data relations and behaviors before getting in to specifics about the low-level details.

It is interesting to note that in researching the talk, I could not find many (if any) controller tests in the current edition of Hartl tutorial.

LinkedIn

The third phase of the talk took a bit of a left turn, but I think is an important lesson for someone trying to break into the field.

I am a big believer in REAL networking, i.e. talking to people, building relationships, asking questions, and following up.  I have made some awesome friends, mentors, and mentees in the Rails community.  It took me too long to learn how to effectively meet people and build relationships.  Fear and imposter syndrome are tough things to overcome.

I see a lot of people not networking effectively and it makes me sad.  We had a really good discussion about getting out and talking to people, sending follow up/thank you emails, and personalizing your LinkedIn invites so the person on the other end remembers you and is inclined to accept your invite.  A big key is following up, if you make a contact at a meetup, say hello at the next meetup, ask a question about something they told you about themselves, be genuine.

As always, it was great to meet another Launch Academy cohort.  I hung around for quite a while and the Launchers had awesome questions.  Looking forward to seeing them out in the community soon.

Facebook URL Linter, Critical Errors, and Rackspace

When you share a URL on Facebook, Facebook will scrape the page to find the Open Graph data embedded in the page.

Facebook also provides a tool called the Open Graph Object Debugger to help you debug errors found in the page.  This can be rally useful if, for instance, your tags are not well-formed, or there are problems with the images or videos that are on the page being shared.

Sometimes, unfortunately, you get a dreaded “Critical Errors That Must Be Fixed – Error Linting URL” as shown below.

UrlLinterCriticalError

Unfortunately, this doesn’t tell you a lot about the cause of the error. ¬†I was trying to have an image display using the og:image tag. ¬†I had been able to successful share pages that had images that were in my Rails ¬†asset directory, but this particular page used an image that was hosted on Rackspace Cloud Files.

To try and diagnose whether there was a problem with the image (e.g. corrupt file, invalid size for Facebook, etc) I downloaded the image and stored it in my Rails assets.  Everything worked fine.  No errors from the Facebook URL Linter.  The problem must have something to do with the storage on Rackspace.  But browsing to the image on Rackspace worked fine as well.  The image displayed fine in the browser and was publicly accessible.

Why wasn’t the Facebook URL Linter able to parse it?
Well when you store files with Rackspace Cloud Files, you get a pretty hideous URL, like

http://12345678901234567890-12345678901234567890123456789012.r12.cf3.rackcdn.com

A URL is a URL right? ¬†Well yes and no. ¬†I think the Facebook URL Linter finds this to be a pretty suspect URL and considers it spammy. ¬†So I needed to make the URL a little more “friendly” to a spam filter.

The answer was to use a CNAME to map a more readable URL to the Rackspace URL.

My client’s site is hosted on GoDaddy, so that meant going into their DNS settings and adding a CNAME record to point to the Rackspace URL. ¬†I picked something meaningful like “images”. ¬†So now my og:image tag could change from

<meta property="og:image" content="http://12345678901234567890-12345678901234567890123456789012.r12.cf3.rackcdn.com/some_image.png">

to

<meta property="og:image" content="http://images.mydomain.com/some_image.png">

In hindsight, the CNAME is a good idea on its own. Sure it might be an extra hop to get the image, but having a more logical URL makes a lot of sense, and it also makes in easier to change where your images are stored.