Pivotal Labs

Main menu

Skip to primary content
Skip to secondary content
  • About
  • Case Studies
  • Team
    • Executives
    • Locations
      • San Francisco (HQ)
      • Boston
      • Boulder
      • Denver
      • London
      • Los Angeles
      • New York
  • Community
    • Blogs
    • Tech Talks
    • Events
  • Careers
    • Lifestyle
    • Principles & Practices
    • Benefits
    • FAQ
    • Apply
  • Contact
    • Press Room
    • Press Releases
    • In The News
    • Press Kit
  • All
  • Labs
  • Standup
  • Tracker

Monthly Archives: October 2011

Charles Hansen

Standup 10/24/2011: Women who code meetup

Charles Hansen
Monday, October 24, 2011

Interesting Things

There will be a Women Who Code meetup on Tuesday. Sarah Mei will be giving a lightning talk at it about a day in the life of an engineer. The organization is for both women who are currently coders and those just interested in coding.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Amit Gupta

Making math make sense to programmers

Amit Gupta
Saturday, October 22, 2011

Whether you’re learning math for pleasure or profit (jumping on the Big Data bandwagon), there are times when it may seem intimidating, overwhelming, confounding, etc. My assertion is that if you think like a programmer, you already have a leg up when it comes to learning math.

I gave today’s Tech Talk at Pivotal Labs SF on this very topic. The outline of the talk is listed below, and these are the slides. I’ll be following up with a series of mini blog posts extracting the contents of the talk.

  1. Program-y translations of math notation
    • Why is math hard to read? Conventions!
    • Translation 1: Mathematical functions (lines, sinusoids)
    • Translation 2: Sigma notation, and other indexed operations
    • Translation 3: Set notation and quantifiers
    • Resources for learning on your own
  2. Program-y proof that the infinity of the reals is bigger than the infinity of the naturals (yes, there are different sizes of infinity)
    • Groundwork: The real numbers
    • Groundwork: Cardinality, the math way to say “how many”
    • Groundwork: Proof by contradiction, the math way to say “when pigs fly”
    • The proof that |R| > |N| for programmers (read: finitists)
  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Pivotal Labs

Rolling your own object creation methods for specs

Pivotal Labs
Saturday, October 22, 2011

Lately my favorite way to create objects in my spec suite is to use an object mother pattern. There are a number
of object mother libraries to choose from (see ruby toolbox for a few), but it’s such an easy pattern
to implement that lately I’ve just been rolling my own. In this post I’ll describe what I’ve been using recently and
why I’ve chosen it over using gems.

To implement a basic object mother pattern, all you need to do is define a few methods that are available to your specs, like so:

def new_post(overrides = {})
  Post.new( {:title => "Some title"}.merge(overrides) )
end

def create_post(overrides = {})
  new_post(overrides).tap(&:save!)
end

This allows you to initialize a new, valid Post, or create one with a single method call:

new_post
create_post
create_post(:title => "Some other title")

You might notice that if you use attr_protected for the Post#title attribute, the previous example wouldn’t work.
So the next step is to make sure that protected attributes are assigned correctly:

def new_post(overrides = {})
  Post.new do |post|
    post.title = "Some title"
    overrides.each do |method, value|
      object.send("#{method}=", value)
    end
  end
end

Let’s say you add a unique constraint the Post#title field. You’ll need to be able to generate a unique post name.
Here’s a quick and dirty (and probably non-thread-safe) way to create unique post titles:

def new_post(overrides = {})
  Post.new do |post|
    post.title = "Some title #{counter}"
    overrides.each do |method, value|
      object.send("#{method}=", value)
    end
  end
end

def counter
  @counter ||= 0
  @counter += 1
end

Associations are typically simple to deal with:

def new_comment(overrides = {})
  Comment.new do |post|
    comment.post = new_post
    overrides.each do |method, value|
      object.send("#{method}=", value)
    end
  end
end

This allows you to do the following:

comment = new_comment
comment.save! # => ActiveRecord will automatically save the post for you

comment = new_comment(:post => Post.first)
comment.save! # => will use the post you passed in

Notice that the new_comment method initializes a new post even if you pass in a post.
This might seem like a detail, but initializing the Comment object unnecessarily will increase the time it takes your
spec suite to run. This might be trivial, but in a large test suite it can add up. To see how much of an impact it
might have in your app, you can run some simple benchmarks:

Benchmark.realtime do
  1000.times { Comment.new :post => Post.new }
end

Benchmark.realtime do
  post = Post.new
  1000.times { Comment.new :post => post }
end

In an app that I’m working on now, it showed that initializing a new post took over twice as long as not doing it. With that in
mind, it’s easy to solve that problem:

def new_comment(overrides = {})
  overrides[:post] = proc { new_post } unless overrides.has_key?(:post)
  Comment.new do |comment|
    overrides.each do |method, value_or_proc|
      comment.send("#{method}=", value_or_proc.is_a?(Proc) ? value_or_proc.call : value_or_proc)
    end
  end
end

This way, the Post is only initialized when one isn’t passed in. With those pieces in place, an example file might look like this:

# spec/spec_helper.rb
RSpec.configure do |config|
  config.include ObjectCreationMethods
end

# spec/support/object_creation_methods.rb
module ObjectCreationMethods
  def new_post(overrides = {})
    defaults = {:title => "Some title #{counter}"}
    Post.new { |post| apply(post, defaults, overrides) }
  end

  def create_post(overrides = {})
    new_post(overrides).tap(&:save!)
  end

  def new_comment(overrides = {})
    defaults = {:post => proc { new_post }, :text => "some text"}
    Comment.new { |comment| apply(comment, defaults, overrides) }
  end

  def create_comment(overrides = {})
    new_comment(overrides).tap(&:save!)
  end

  private

  def counter
    @counter ||= 0
    @counter += 1
  end

  def apply(object, defaults, overrides)
    options = defaults.merge(overrides)
    options.each do |method, value_or_proc|
      object.send("#{method}=", value_or_proc.is_a?(Proc) ? value_or_proc.call : value_or_proc)
    end
  end
end

You might be wondering why you might roll your own rather than using an existing library
like Factory Girl or Fixjour. A few of the benefits are:

  • The methods are not generated by meta-programming, so IDEs like RubyMine (or editors that make use of CTags) can offer code completion and refactoring support
  • It’s plain ruby, and is unlikely to break as ActiveRecord updates itself, whereas using a 3rd-party library you can’t upgrade Rails until that 3rd-party library supports the new Rails version
  • When you have complex object graphs it’s easy to initialize or create objects in the exact manner you’d like, as opposed to potentially being constrained by the library you are using
  • Developers on the project don’t have to learn a 3rd-party library’s api or idiosyncrasies
  • It takes about the same time to write these methods as it does to define similar methods in libraries like FactoryGirl
  • There are only 2 plumbing methods to support the framework – it’s super simple to understand

One feature I’ve seen implemented in object mother libraries is support for attribute hashes, similar to:

def valid_comment_attributes(overrides = {})
  {:post => new_post}.merge(overrides)
end

Presumably these attribute hashes would be used for passing into controller specs. In practice, I’ve never seen this work
as expected. In the example above, rspec would happily pass a new Post object into the controller spec, but that could never happen
in real life. However, if you wanted those valid attributes, you could easily incorporate those into your home-rolled ObjectCreationMethods.

I’ve used this pattern on several recent projects ranging from Rails 2.2.2 on Ruby 1.8.6 to Rails 3.1 on Ruby 1.9.2 and
it just works.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter

Standup 10/21/2011 JS['test'] == ‘test’

Stephen Hopkins
Friday, October 21, 2011

Ask for Help

“Anyone used Akamai with HTTP Delete?”
Akamai doesn’t understand the DELETE verb. Maybe try to pass it through Akamai?

Interesting

  • JS['test'] == ‘test’. Make sure you use === so that you get expected behavior.

  • IntelliJ 11 Android has great UI previews!

  • Blitz.io : Affordable and easy to use server benchmarking

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Alex Welch

Serving up different sized dynamic images based on device resolutions

Alex Welch
Thursday, October 20, 2011

Serving up different sized dynamic images based on device resolutions.

Jason and I were working on an app where we needed to render dynamic images of several different sizes for different mobile devices, depending on device resolution.

Our scenario was analogous to the following:

Let’s say you are an engineer for Twitter and you need to display a user’s avatar on their show page, but you need to serve a small, medium, or large image based on the resolution of the device accessing the page.
This is a potential candidate for CSS media queries, except that the image url needs to be obtained from our User object (in Ruby).
Let’s cross that bridge when we get there and spike on an initial proof-of-concept.

users#show view
<h2><%= @user.name %></h2>
<div class="avatar"></div>
# ...
stylesheet
/* Default - screens over 767px wide */
.avatar {
  /* ... */
  width: 220px;
  height: 220px;
  background: url('/assets/dfp/large.jpg');
}

/* Mobile Landscape */
@media only screen and (min-width: 480px) and (max-width: 767px) {
  .avatar {
    /* ... */
    width: 140px;
    height: 197px;
    background: url('/assets/dfp/medium.jpg');
  }
}

/* Mobile portrait */
@media only screen and (max-width: 479px) {
  .avatar {
    /* ... */
    width: 60px;
    height: 85px;
    background: url('/assets/dfp/small.jpg');
  }
}

Pretty straightforward stuff, especially if you’ve followed the Responsive Web Design (CSS media queries) trend.
The interesting thing to note here is that when putting the background image in the stylesheet, the asset does not get requested until you resize your browser to the size that uses that image.
Go ahead and load this page in a web browser, open up the network panel, resize the display, and watch the asset size change and different requests getting fired off. That’s exactly what we want!

Okay, great. But, although it would be glorious, not everyone is going to have Dog Fanny Pack for their avatar. We need to call some ruby method on some ruby object to get the image (e.g. user.avatar.path).
Not really something you can do from within the stylesheet. Alternatively, you wouldn’t want to move the background image reference to the view because then it gets loaded as soon as the page loads, regardless of the screen resolution.

To make this puppy (pun intended) dynamic, we create a little proxy. See below:

Routes
ResponsiveUserAvatar::Application.routes.draw do
  # ...
  match "users/avatars/:size.jpg" => "users#avatar"
end
Users controller
def avatar
  user = get_user
  size = params[:size]
  if user.present?
    send_file "#{Rails.root}/#{user.avatar.path(size)}"
  else
    render :status => :not_found, :text => "not found"
  end
end

We create an action, called avatar, on our users controller (you also create a separate avatars controller) that takes a size parameter. The avatar action first looks up the user (You don’t get to see how ’till later),
then it grabs the size from the url and renders the user’s avatar for that size.

Quick aside

You may notice this action isn’t really on the member (i.e. no user id), even though it should be. We’ll get to that in a second.
You may also be thinking of alternatives to using send_file. Jason and I experimented with redirects, but ran into caching issues. I am open to suggestions on these topics, so feel free to post feedback in the comments or submit a pull request to the demo app.

Back to business

Now all we have to do is call our proxy image/action in the stylesheet, see below:

users.css
/* Default - screens over 767px wide */
.avatar {
  /* ... */
  background: url('/users/avatars/large.jpg');
}

/* Mobile Landscape */
@media only screen and (min-width: 480px) and (max-width: 767px) {
  .avatar {
    /* ... */
    background: url('/users/avatars/medium.jpg');
  }
}

/* Mobile portrait */
@media only screen and (max-width: 479px) {
  .avatar {
    /* ... */
    background: url('/users/avatars/small.jpg');
  }
}

Coming clean…

So, I left out one minor detail… Okay major detail… It’s time to show the implementation of the “get_user” method.

users_controller
class UsersController < ApplicationController
  # ...
  private

  def get_user
    if request.env["HTTP_REFERER"].present?
      user_id = request.env["HTTP_REFERER"].match(//(d+)/?/)[1]
      user = User.find_by_id(user_id)
    end
  end
end

In our case we always had the user id in the page that used the avatar. If we tried to implement this on the listing page… Well it wouldn’t be pretty.

While this isn’t a silver bullet solution, it’s a cool concept and can be applied to many different applications. I call it the “responsive-css-background-fake-image-proxy” pattern.
Okay, maybe not, but to recap, the main components are:

  1. Use CSS media queries to target different device resolutions.
  2. Reference the background-image proxy url in the stylesheet, which only loads the image size needed.
  3. Use a fake image proxy to get your dynamic image.

Demo app and demo app code

  • 0 Shares
  • Share on Facebook
  • Share on Twitter

Standup 10/20/2011 – License Finder and rails 2.3

Jesse Toth
Thursday, October 20, 2011

Ask for Help

“License Finder doesn’t work with rails 2.3?”

This problem has come up a few times, but no one could recall what the solution was. Might be something about a rake task….

Interesting Things

  • MySQL Prefpane isn’t working with the Pivotal install on Lion. Seems like it expects a particular installation/configuration. Got around this by reinstalling MySQL from dmg. Another pivot suggested this could be a path issue that could be solved without a full reinstall.
  • An older version of Chrome on Windows has a bug with mouse-enter and mouse-leave events. It will think you have left a div if you mouse over a text input contained within that div. Upgrading Chrome should fix this.
  • event.layerX and event.layerY will be deprecated at some point… you’ll see these warnings now on the newest build of Chrome since it auto-updates.
  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Dan Podsedly

TrackerDashboard – 3rd Party Tool to Help Manage Large Projects

Dan Podsedly
Wednesday, October 19, 2011

Our friends at CaseCommons have built TrackerDashboard – a tool to help manage a large team of 25 developers, 2 designers, and 4 product managers as they build a world class enterprise application. It’s open source, and available for use to anyone, so check it out!

  • 0 Shares
  • Share on Facebook
  • Share on Twitter

Standup 10/19/2011: Stripe > Paypal

Stephen Hopkins
Wednesday, October 19, 2011

Interesting

  • replaceState() vs pushState()
    replaceState() can be used for javascript applications instead of pushState() to change the address bar when you don’t want to add new items to the browser history.

  • Stripe > Paypal
    Stripe is awesome and can be set up in less than a day!

  • SF Elections
    Coming soon, so vote!

  • 0 Shares
  • Share on Facebook
  • Share on Twitter

Standup 10/18/11: accepts_nested_attributes_for validation gotchas

Jesse Toth
Tuesday, October 18, 2011

Ask for Help

“accepts_nested_attributes_for doesn’t validate nested records? When a form contains two of the same nested attributes and the values of these should cause a validation error (e.g., both have the same email, which has a uniqueness constraint), the form saves properly, but the nested objects are invalid when accessed later.”

accepts_nested_attributes_for only validates against the database, but the records in this example would only be in memory. The best solution is to handroll a validator on the parent that iterates over the nested attributes and checks the constraints.

“A Pivot was getting some errors using minified jQuery in IE8, which went away when he used the un-minified version. Any other IE8/jQuery gotchas?”

A few have been mentioned at standup in the past few weeks, most notably some versions of jQuery crash IE8 entirely.

“Is there a way to generate a png from html server-side?”

You can use a command-line tool like webkit2png or there is some rack middleware that can generate pdfs and maybe pngs from html

“A pivot had a page that was requesting images after the page loaded, but couldn’t find where they were coming from…”

You can check the originator column of assets in firebug or the chrome developer panel. You can also try overriding jquery ajax to see each call (which you may not want to do if you have a lot of ajax calls).

  • 0 Shares
  • Share on Facebook
  • Share on Twitter

Standup 10/17/11: Devise + Omni-Auth Interactions

Stephen Hopkins
Monday, October 17, 2011

Ask for Help

“Rails creates a callback for each symbol. Why am I getting a symbol table overflow?”

Issue has been resolved, staging.rb environment file was missing.

Interesting Things

“Devise + Omni-Auth => KABOOM”

Devise and Omni-Auth make a great combination, but if you’re using Omni-Auth in integration test mode, you’ll get all sorts of errors. Instead, mock up the O-Auth service.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter

Topics

  • agile (778)
  • rails (113)
  • testing (86)
  • ruby (83)
  • ruby on rails (70)
  • jobs (62)
  • javascript (53)
  • techtalk (44)
  • rspec (38)
  • activerecord (29)
  • productivity (29)
  • gogaruco (29)
  • ironblogger (29)
  • git (28)
  • nyc (27)
  • rubymine (25)
  • mobile (21)
  • cucumber (20)
  • bloggerdome (19)
  • process (19)
  • pivotal tracker (19)
  • design (18)
  • jasmine (18)
  • ios (18)
  • webos (17)
  • objective-c (17)
  • android (16)
  • palm (16)
  • "soft" ware (16)
  • fun (15)
  • tracker ecosystem (15)
  • ci (15)
  • cedar (15)
  • rails3 (14)
  • performance (14)
  • gem (13)
  • bdd (13)
  • selenium (12)
  • css (12)
  • goruco (12)
  • bundler (12)
  • tdd (12)
  • meetup (11)
  • railsconf (11)
  • nyc-standup (11)
  • capybara (10)
  • mac (10)
  • mojo (10)
  • chef (10)
  • rubygems (9)
Subscribe to Community Feed
  1. ←
  2. 1
  3. 2
  4. 3
  5. 4
  6. →
  • About
  • Case Studies
  • Team
  • Community
  • Careers
  • Contact
  • Labs
  • Events

Contact Us

contact@pivotallabs.com
+1 415-77-PIVOT
TwitterLinkedInFacebook

Pivotal Tracker

Tracker is the award-winning agile project management tool that enables real-time collaboration around a shared, prioritized backlog.
Visit pivotaltracker.com >