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: April 2010

Sean Beckett

Case Commons seeking VP Eng / CTO in New York

Sean Beckett
Friday, April 30, 2010

At Pivotal Labs, one of the services we provide is bootstrapping startups, including helping them interview and hire. Pivotal Labs and our clients place a strong emphasis on Agile development and its many aspects: Pair Programming, Test-Driven Development, rapid iterations, and frequent refactoring.

Here is a job posting from Case Commons, a current Pivotal client looking for a VP of Engineering or CTO in New York.

Case Commons’ mission is to transform public sector human services through technology. Case Commons enables workers serving the most vulnerable families and children to be more effective and efficient via new software tools. Casebook™, Case Commons’ marquee technology, is a collaborative, family-centered case management system that leverages the capabilities inherent in social networking technology for the public sector child welfare segment. A growing number of policymakers believe that Casebook™ can be a citizen portal for government services, including health, education and human services. Case Commons is funded by the $2.5 billion Annie E. Casey Foundation, which has spent 20 years pursuing human services system reform; since 2007, AECF has been building Casebook™ in partnership with Tipping Point Partners.

DESCRIPTION

  • You will lead the engineering team building Casebook™, reporting to the Chief Operating Officer
  • You will assume a leadership position, revolutionizing technology for people serving less advantaged children and families, with high visibility among government, foundation, venture capital, and business leaders
  • You will work with a unique team that consists of proven domain leaders, successful entrepreneurs who have helped transform other technology market segments, and software developers from Pivotal Labs, the top Ruby on Rails software development consultancy in the world
  • Salaried position in a non-profit organization located in New York City
  • Significant travel – up to 50% of time

REQUIREMENTS

  • You have the passion and skills to succeed in a startup: tenacious, self-directed, flexible, strategic but can turn on a dime, able to inspire others and to be inspired
  • You go the extra mile
  • You spent 10 years in information technology, preferably in application development, application management, and operations within a Fortune 500 company or government organization
  • Optional but especially valuable would be experience with government software for human services, such as for AFCARS, IV-E eligibility, and SACWIS
  • You have rolled out software to several thousand users within a large organization
  • You have 3-5 years of managing small engineering teams (< 25)
  • You have delivered software on time and within budget
  • You are a student of organizations, familiar with the team structures and processes necessary to handle the full lifecycle of enterprise software (conceptualization, estimation, design, development, piloting, training, deployment, maintenance, customer support, release management, reporting and tracking, sunsetting and migration)
  • You have managed vendors for software development, web hosting, and security
  • You are familiar with best practices for securing web applications including but not limited to OWASP, security scanning, secure network design
  • Your prior work involved sensitive customer data, such as financial information, transactions, HIPAA data, credit cards, or personal health information
  • You use and appreciate consumer Internet software, including Facebook, Twitter, Google, YouTube and other “Web 2.0” applications
  • You have personal or professional Web application projects in Ruby on Rails, LAMP or similar technology stacks
  • You are expert in agile development processes, and want to transform software development processes within governments and large organizations
  • You like people and enjoy sharing your knowledge: able to translate engineering needs and challenges into plain English verbally and in writing
  • You care about people and their success: strong inter-personal and team skills, with active listening abilities and instincts
  • You have made mistakes part of your process and know how to create a culture that identifies and surfaces problems early
  • You have common sense, limitless curiosity, terrific taste, and an appreciation for the absurd
  • You are passionate about our mission

Case Commons and Tipping Point Partners. Tipping Point Partners has worked on Casebook™ since 2007, leading product development and business functions. Tipping Point is responsible for building the Case Commons team.

Tipping Point builds and renovates Internet-based startups using innovative approaches to solving business model challenges. We look for opportunities to create new businesses that have significant social and/or cultural importance in markets that are ripe for disruption, both for-profit and not. Since 2005, Tipping Point Partners’ unique approach to startups has included co-founding, interim management, strategic deal making, financing, investing and strategy, generally all at the same time. Our portfolio has included IGA Worldwide, FashionGPS, Mobile Commons, Cookstr, Rapid Ratings and many others. We achieve the highest and best use for our companies with an agnostic approach to capital sources and huge doses of sweat equity to accelerate development, extend runway and amplify opportunities.

INTERESTED?
Send resume, biography, and link(s) to project(s) to art@tippingpointpartners.com, with a copy to christine@tippingpointpartners.com

  • 0 Shares
  • Share on Facebook
  • Share on Twitter

Basic Ruby Webapp Performance Tuning (Rails or Sinatra)

Alex Chaffee
Wednesday, April 28, 2010

My company launched our app, Cohuman, a few weeks ago. The rush of finishing features, fixing bugs, and responding to user feedback has subsided a bit, and it’s time to go back and give the little baby a tune-up. I find that a good development process will ebb and flow, and as long as you don’t let something slide for too long, it’s perfectly acceptable to let bugs, or performance issues, or development chores pile up for a bit and then attack them concertedly for an entire day or two. A bug-fest or chore-fest or tuning-fest can actually increase efficiency as you get in a rhythm… and it feels really good at the end of the day when you see all the bugs you slayed or all the milliseconds you shaved.

In this article I’d like to describe some of my techniques. I make no claim of originality or great expertise; I just want to share what I know, and hear (in comments) what other people have learned. I’m using Sinatra and ActiveRecord, but not Rails; hopefully this discussion will help people no matter what framework they’re using.

Metrics and Logs

The first step, and often the most overlooked, is to gather metrics. Without knowing how it’s working now, how are you going to know what to improve? And how are you going to know whether you made things better or worse? Frequently I’ll make a change that I’m sure will improve performance, only to discover that it’s made no change, or helped in one place but hurt in another.

Where to begin? We’re using New Relic for live performance monitoring, so my decision of what to optimize was easy: I went to their Web Transactions panel and looked at the Most Time Consuming and Slowest Average Response Time reports. If you don’t have a flashing signpost like that, it’s easy enough to decide on a path to work on: either go with user reports, or click around your app and see what feels slow, or choose the most popular request (which is usually the home page).

I always pick a single path to work on, from request to controller to database to view, and work on the slowest parts. This demands more metrics! It’s a common mistake to jump in and start tuning the database when the view is actually taking twice as long. What’s the use of cutting the database access from 400 to 200 msec when the view is taking 1200 msec to render?

I also like to grab a copy of the production DB and bring it to my development machine so I can be sure I’m profiling real cases, and not being fooled by artifacts of generated data. We’re lucky that our app is currently small enough to do this; when the app gets bigger we’ll have to write a script that grabs only selected users’ data as a slice of the whole enchilada. (Note that there are some privacy concerns here: we are careful to only log in locally using our own accounts, and only to gather statistics in aggregate, not to look at details of user-entered data unless it’s to diagnose a specific user-reported issue or bug.)

Lots of in-app metrics tools exist (e.g. ruby-prof, benchmark), but I prefer the simple approach: I rolled my own Marker class that spits out basic msec timing information to the logs. In single-request performance tuning, what matters is relative timing between sections of code, so any objections to this technique on grounds of accuracy or detail are outweighed by its advantages: it’s simple, it shows where your bottlenecks are, and it divides the logs into sections so you can get a sense of who’s making what calls.

class Marker
  def self.mark(msg, logger = ActiveRecord::Base.logger)
    start = Time.now
    logger.info("#{start} --> starting #{msg} from #{caller[2]}:#{caller[1]}")
    result = yield
    finish = Time.now
    logger.info("#{finish} --< finished #{msg} --- #{"%2.3f sec" % (finish - start)}")
    result
  end
end

Usage is simple: pick a block you’re interested and wrap it in Marker.mark("foo") do...end. You can then scan the logs using “less” (or a text editor) and search for the name you gave the block. Marking your controller and your view is a natural place to start; later you can insert marks inside interesting blocks of domain code. In Sinatra, you can do something like this:

get '/foo/:id' do
  foo = Marker.mark("loading foo") do
    Foo.find(params[:id])
  end
  Marker.mark("rendering foo") do
    FooWidget.new(:foo => foo).to_s # Erector
  end
end

I’ve also got a nice little Rack middleware component that marks the time spent inside each request. Note here that you can put lots of fun information in the name that can be helpful for debugging.

class Marking
  def initialize(app)
    @app = app
  end

  def call(env)
    response = nil
    Marker.mark("#{env['REQUEST_METHOD']} #{env['SCRIPT_NAME']}#{env['PATH_INFO']}") do
      response = @app.call(env)
    end
    response
  end
end

Figuring out where a particular log message (especially a DB query) is coming from is essential. It’s important not to make assumptions. If you think you know where the call is coming from, put in a stack trace to make sure, and rerun the request to confirm. That’s why Marker is outputting caller — caller[0] is the code that names the mark, so you already know where that is; caller[1] is the line that called it, and caller[2] is the line that called caller[1]. If that’s not enough context, drop in a logger.info(caller.join(”nt”)) so you can scan the entire stack trace back up to the application code that you understand.

I’ve found that while ActiveRecord (2.3.5) tries to show where a result is coming from, it doesn’t always get it right, especially if you’re using plugins or gems that insert themselves into the call chain. So I monkey-patched AR to be a little smarter about its tracing:

module ActiveRecord
  module ConnectionAdapters
    class AbstractAdapter
      # strip library file pathnames from logged stack traces
      def log_info(sql, name, ms)
        if @logger && @logger.debug?
          c = caller.detect{|line| line !~ /(activerecord|active_support|__DELEGATION__|vendor|new_?relic)/i}
          c.gsub!("#{File.expand_path(File.dirname(RAILS_ROOT))}/", '') if defined?(RAILS_ROOT)
          name = '%s (%.1fms) %s' % [name || 'SQL', ms, c]
          @logger.debug(format_log_entry(name, sql.squeeze(' ')))
        end
      end
    end
  end
end

All this leads to log entries that look like this:

Thu Apr 15 11:09:17 -0700 2010 --> starting GET /app from /Users/cohumancomputer27inmac/dev/cohuman/lib/query_caching.rb:15:in `call':/Library/Ruby/Gems/1.8/gems/activerecord-2.3.5/lib/active_record/connection_adapters/abstract/query_cache.rb:34:in `cache'
  User Load (0.8ms) domain/user.rb:362:in `authenticate_from_login_token'   SELECT * FROM "users" WHERE ("users"."login_token" = E'abc123xyz') LIMIT 1
Thu Apr 15 11:09:17 -0700 2010 --> starting rendering ApplicationPage from /Users/cohumancomputer27inmac/dev/cohuman/controllers/app_controller.rb:4:in `GET /app':/Library/Ruby/Gems/1.8/gems/sinatra-0.9.4/lib/sinatra/base.rb:779:in `call'  Project Load (13.4ms) domain/user.rb:146:in `projects'   SELECT "projects".* FROM "projects" INNER JOIN "memberships" ON "projects".id = "memberships".project_id WHERE (("memberships".user_id = 2))
  User Load (3.2ms) domain/user.rb:135:in `coprojectmates'   SELECT "users".* FROM "users" INNER JOIN "memberships" ON memberships.user_id = users.id WHERE (memberships.project_id in (4,129,122,1,66,82,102,684,533,139,3,155,624,106,90,394,399,153) AND memberships.user_id != 2)   Email Load (2.1ms) domain/user.rb:135:in `coprojectmates'   SELECT "emails".* FROM "emails" WHERE ("emails".user_id IN (1,3,5,7,8,11,12,9,6,14,15,16,17,18,22,27,26,35,45,32,30,79,37,109,80,504,507,508,39,165,521,725,727,729,730,731,734,735,736,105,28,58,240,381,51,40,36,785,834,839,844,847,850,842,840,841,843,889))
  User Load (11.7ms) domain/user.rb:128:in `cohumans'   SELECT "users".* FROM "users" INNER JOIN "cohumanities" ON "users".id = "cohumanities".cohuman_id WHERE (("cohumanities".actor_id = 2))
  Email Load (19.4ms) domain/user.rb:128:in `cohumans'   SELECT "emails".* FROM "emails" WHERE ("emails".user_id IN (1,6,108,8,22,35,509,852,853,854,862,864,866,3,895,896,897,929,930,931,30,944,165,827,976,977,978,735,1024,2003,2004,59))
  SQL (0.5ms) domain/user.rb:177:in `temporary?'   SELECT count(*) AS count_all FROM "emails" WHERE ("emails".user_id = 2)
  Email Load (0.3ms) domain/user.rb:173:in `verified?'   SELECT * FROM "emails" WHERE ("emails".user_id = 2)
Thu Apr 15 11:09:17 -0700 2010 --< finished rendering ApplicationPage --- 0.307 sec
Thu Apr 15 11:09:17 -0700 2010 --< finished GET /app --- 0.311 sec

I know it can look daunting, but when scanning logs, it’s important to keep a clear head. Let’s examine this little burst of gibberish and try to make sense of it.

Line 1 says “–> starting GET /app” which means that the user has made a GET request for our main URL. We can skip ahead (search for “–< GET /app”) and see that the entire request took 0.311 seconds. This isn’t bad, but it could be better.

Line 3 says “–> starting rendering ApplicationPage” which means that all the other queries are happening from inside the rendering view code.

Note that the database queries are only taking 49.3 msec out of 311 msec, which means 84% of the time is spent either processing DB results or rendering them. This request is probably not a good candidate for DB-level tuning.

(How’d I add up all those scary milliseconds without an abacus? Piped my log text into this bad boy:

  ruby -e 'x = 0; STDIN.each do |line| if line =~ /(([0-9.]*)ms)/; then x += $1.to_f; end; end; puts x'

)

Indexes

Most (if not all) databases add an index for the primary key of a table. But a quick scan of the database logs will show many fields that are used in queries, and chances are you haven’t added indexes for them. (In fact, you probably shouldn’t add an index for a field until it shows up in the logs, since indexing slows down writes and takes up extra disk space. Not a lot, but it might add up.) In the above example, look at the User Load — every time a user hits the site we check to see if he’s logged in by querying the database for his login cookie. Adding an index for the “login_token” field in the users table sped up this query by a factor of 10. (Yes, that violates my “don’t fix what ain’t slow” dictum, since going from 10 ms to 1 ms isn’t really fixing much, but I figure it adds up over time since it happens on every single app request.)

Avoidance

The only perfect program is the one with zero lines of code. And the fastest code is that which is not run.

Sometimes you can optimize a section of code by removing unnecessary calls from your app layer. One nice trick these days is to move stuff behind an Ajax call. In Cohuman, we do this with some of our tabs: if you switch to a tab, and it hasn’t been loaded yet, it shows a spinny and starts an Ajax call to load it in. As long as we can keep each Ajax call under a second in length, the user-perceived delay is negligible.

Query Caching

ActiveRecord maintains a query cache, so if you run the same query (and I mean the same SQL), it won’t hit the database again. But if you’re not using Rails, query caching is disabled by default. So I wrote yet another Rack middleware so I don’t have to remember to wrap all my controllers in a ActiveRecord::Base.cache do block:

# a Rack middleware component that enables ActiveRecord query caching
# To use, put "use QueryCaching" in your Sinatra app.

class QueryCaching
  def initialize(app)
    @app = app
  end

  def call(env)
    if is_static_file?(env)
      @app.call(env)
    else
      response = nil
      ActiveRecord::Base.cache do
        response = @app.call(env)
      end
      response
    end
  end

  def is_static_file?(env)
     # if the path end with a dot-extension (e.g. 'foo.jpg') then we assume
     # it's a static file and don't enable the query cache. (This will only
     # work for some application URL schemes, naturally.)
    env['PATH_INFO'] =~ //[^/]*.[^/.]+$/
  end

end

Note that this is a query cache, not an object cache (see below).

Query Tuning

Once you’ve identified some troublesome queries, you need to decide how to optimize them. You’ve basically got two choices here; which to choose should be obvious from the logs. Are there many low-latency queries, or a few high-latency queries? High-latency queries are an obvious target, and you should do your best (with indexes and SQL) to cut them down to size, but don’t let them distract you. There are two hidden costs to low-latency queries:

They actually take longer than they say they do – the AR log line only displays the time for the database connector to return the raw data. It doesn’t show the time to create AR instances, build association “classes” (which takes an annoyingly long time, since all their methods are built on the fly for each instance), and run post-load initialization code. (I just did a little experiment loading ~3000 of our User objects, which have a fair number of associations; SELECT * FROM users took 21 msec but User.all took 547 msec. That’s about 25x as long!)

They stack up, and I’m not talking pancakes – chances are you’ve got a lot of webapp processes hitting a single database (or a small number of slaves). As traffic increases, the queries will stack up like airplanes requesting permission to land. At a certain point you’ll hit a cliff (sorry for the mixed metaphor — it’s not fun to imagine a plane hitting a cliff) and per-request latency will rise dramatically. Lowering the number of queries per web request will, um, raise the ceiling? Lengthen the runway? Lower the cliff? Anyway, it’ll make this problem, uh, less worse. It’s kind of counterintuitive, but the limiting factor for modern webapps is really the number of queries, not the amount of data returned by each query.

ActiveRecord associations (like has_many and belongs_to) are great for getting an app up and running, but as you peruse your logs you’ll notice some things they’re doing that aren’t very efficient. Our app loads a lot of objects, each of which has lots of associated objects, some of which associate to other objects. If we’re displaying a list of Users, and each user has associated Emails (via has_many :emails), and we want to render a list of users and their email addresses, we’ll probably see one query that loads all users, and then one query for each user loading his or her emails.

Adding an :include to the declaration is a good way to reduce these from N+1 to 2, but it doesn’t always work. I have never been able to comprehend AR’s alien logic, so my logs are often littered with queries despite my best efforts fiddling with the association declaration. Furthermore, AR is quite naive about object graphs: for example, user.emails.first.user will make an extra query and return a different user than the one you started with, even though they have the same id and you loaded the emails via :include.

So I’ve gotten good performance boosts by moving away from ActiveRecord and doing some nested queries by hand. Not by writing literal SQL, but by doing one query, extracting the necessary ids, and then doing the next query, and saving or plugging in values directly. This led naturally to Treasury (see below).

Sometimes, of course, writing SQL is unavoidable; fortunately, AR allows it, and there are many people who are much better at that than I, so I won’t embarrass myself by discussing it further here.

Object Caching and the Repository Pattern

During my first pass at tuning Cohuman several months ago, I took a little time to write a library that implements a Repository Pattern. The Treasury is a work in progress that sits in front of ActiveRecord (and eventually, other ORMs) and caches object instances as they pass through. If you then request an object via the Treasury, it will check in its cache and return a pointer to the existing object instead of making a query; if you specify a list of ids, then it will only query for the ones it doesn’t yet have. (There are other features I won’t go into here, including a DSL for building queries… expect an upcoming article to officially introduce Treasury to the world.)

I’ve heard that DataMapper has an object cache, but I haven’t yet dug into the details of how it works, so I don’t know if Treasury is redundant with it, or if it would make sense to plug in DM behind it. (I’ve also heard it solves the N+1 query problem gracefully. Anyone want to proselytize DM in the comments?)

All the caches I’ve mentioned only persist within a single request. This is probably a good thing, since allowing instances to persist between requests would open a can of data integrity, thread safety, and multi-host worms. But I can’t shake this vision I have of a sort of in-process memcache for Ruby objects, where multiple processes communicate changes to each other via TCP wormholes… Does anyone else share this vision, or am I doomed to wander the Ruby blog desert, mumbling incoherently at strangers?

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
David Stevenson

Standup 4/28/2010: Webrat threading errors & new RubyMine version

David Stevenson
Wednesday, April 28, 2010

Ask for Help

“We keep getting webrat thread exceptions running our integration specs with the rails integration runner: Thread tried to join itself. The error message varies with different versions of ruby 1.8.6 vs 1.8.7.”

Anyone had this problem or know why?

“How do I skin an iphone mobile site to be the correct width so it’s not 980px wide?”

<meta name="viewport" content="width = device width" />

*”We’re trying to deploy some nginx configuration changes to EngineYard Cloud, what’s the right way to do that?”

We’ve tried building custom chef recipes to solve this problem, but they run after nginx has already restarted, so are a poor solution to this problem. The better solution might be to check in configuration files into the application and symlink them into the nginx configuration directory using a before_symlink.rb hook in the /deploy directory.

*”We’ve got a has_many association where some of the child records are originally saved in an invalid state. When we later load the parent and ask it if it’s valid, it returns true even with validates_associated. How can we get the desired validation behavior?”

Turns out that unloaded associations are not validated. Solution: load the association before calling .valid? on the parent. In general, you should also not create invalid objects, instead using a state variable to put them into a “draft” or “incomplete” state where they are still valid but not complete. Then remove that state and you’ll see the errors required to finish that object.

Interesting Things

  • When RubyMine 2.0.1 won’t run your focused specs, try attaching rspec 1.2.9 to it rather than 1.3.x. It fixed this issue for one of our teams.
  • Rubymine 2.0.2 came out today: can finally run focused contexts?! Also including bundler support! What’s new
  • We tried our Unicorn on EngineYard cloud: so far so good. It’s still “experimental” but seems to work.
  • 0 Shares
  • Share on Facebook
  • Share on Twitter
David Stevenson

Standup 4/26/2010: Ruby hack night with Sarah Mei

David Stevenson
Monday, April 26, 2010

Interesting Things

  • Given a list of IDs, how do you find which ones are not in the database?
ids = [1,2,3,4,5,0]
missing_ids = ids - Model.find_all_by_id(ids).collect(&:id)
  • Sarah Mei is hosting a Ruby Hack Night at pivotal labs tomorrow at 7PM (Tues April 27th. 731 Market St Floor 3, San Francisco).
  • There is an android users group tomorrow. We don’t know any more about it than that.
  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Pivotal Labs

NYC Standup Roundup – Week of 4/19

Pivotal Labs
Saturday, April 24, 2010

Interesting

  • A Pivot noted a facepalm + headdesk moment when debugging an issue whose cause turned out to be related to two adjacent string literals being auto-concatenated by Ruby’s parser.

    >> "foo" "bar"
    => "foobar"
    

In this case, a missing comma in a method call went undetected because of this language characteristic. Whether or not this follows the principle of least surprise is an exercise left up to the reader.

  • Another pair warned that while this is valid syntax in Ruby 1.8.7 and beyond:

    define_method(:burninate) { |&block| block.call("burninating") }
    

.. in 1.8.6 you can’t use a block as a parameter of a block.

  • Another pair noted that exceptions with Sunspot can cause wider failures on a site than just those that touch Solr. The symptom on this project was that if Solr was inaccessible for any reason every page on the site would throw an error. Their fix was to use Sunspot’s SessionProxy to wrap methods with some exception handling love.

  • Lastly, GoRuCo — the Gotham Ruby Conference — will be held on May 22nd at Pace University’s downtown campus. The roster of talks is up and registration is open for business.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Edward Hieatt

Mavenlink Chosen as finalist for TechAmerica High-Tech Innovation Awards

Edward Hieatt
Friday, April 23, 2010

We’d like to congratulate Mavenlink, one of our clients, for being chosen as a finalist for TechAmerica High-Tech Innovation Awards. Mavenlink (http://www.mavenlink.com) provides an online workspace that helps businesses and their consultants collaborate better. We’ve really enjoyed our ongoing work with the Mavenlink team, and we’re excited about Mavenlink’s progress!

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Dan Podsedly

Looking for Ruby on Rails developers

Dan Podsedly
Monday, April 19, 2010

Pivotal Labs has been at the forefront of agile development since it’s early days. We’ve taken what we’ve learned by applying agile concepts on a countless number of real world projects, and honed these skills into a very effective way to build software. Along the way, we also built a great project management and collaboration tool – Pivotal Tracker.

Not only does Tracker serve as a critical component of our own development process, it’s also relied on by thousands of teams out there in the world, from open source developers, to fast growing startups, and high profile, established companies.

It’s a great app, yet we have lots of ideas for how we’d like to improve it. Want to help us? If you’re a Ruby on Rails developer, enthusiastic about agile development, and want to help us to take Tracker to the next level, read on.

We’re currently looking for developers in the Denver/Boulder, Colorado area. Familiarity with Ruby on Rails is important, as are strong Javascript, CSS, and overall web UI skills. At Pivotal Labs, we pair and test drive 100% of the time, so any experience with pair-programming and/or test driven development would be a huge plus. We’re also big on aggressive refactoring, so be ready to roll up your sleeves.

If you’re interested in working with us, please send your current resume to tracker-jobs@pivotallabs.com, and tell us a little about yourself. Principals only, please.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Pivotal Labs

NYC Standup Roundup – Week of 4/12

Pivotal Labs
Sunday, April 18, 2010

Help

Does anybody have any good techniques for dealing with STDOUT/STDERR and exception handling when shelling out in Ruby on Windows?

Nobody did. Do you? Please share in the comments.

Interesting

A pair ran system updates on their Snow Leopard box which caused bunch of test failures in their project. Most of the failures were occurring around the parts of the application that used BigDecimal. After digging they found:

     >> BigDecimal.new("1.01").to_f
     => 1.1

Oops! Looks like Apple shipped Ruby 1.8.7 p173 with a recent update. p173 has a bug that some dude introduced into BigDecimal. The fix was to update to p174 which was released quickly after this was discovered.

While on the subject, BigDecimal is kind of a drag. Its #inspect output is inhumane and new’ing up BigDecimal objects requires an ugly call to its constructor. A Pivot recommended using the undocumented bigdecimal/util which adds a convenience method to Float for creating new BigDecimals:

    >> require 'bigdecimal/util'
    >> 3.14159265.to_d
    => #<BigDecimal:10056bea8,'0.314159265E1',12(16)>

And a nickel’s worth of free advice?

    >> BigDecimal.send :alias_method, :inspect, :to_s
    >> 98.6.to_d
    => 0.986E2

Unless you prefer:

    #<BigDecimal:101137c78,'0.986E2',8(8)>
  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Pivotal Labs

Standup 04/15/2010 – iconv and EY+JRuby

Pivotal Labs
Thursday, April 15, 2010

Ask for Help

  • Anyone have advice for loading seed data in both regular and test environments? One of our projects has some data that is necessary to bootstrap the app into a working state and they’d like it to be in the database for all their tests as well.

  • EngineYard Cloud installs a weird version of JRuby. Some of the standard command line options don’t seem to work. Anyone have a pointer to a good chef recipe for getting JRuby up and running on EYCloud?

Interesting Things

  • Ever get a UTF-8 file with messed up encoding? If all the bytes are still in the right order, try using iconv to fix it. Telling iconv to convert from UTF-8 to UTF-8 fixed a file that had been emailed to one of our projects.
    iconv -f UTF-8 -t UTF-8 es.yml > es2.yml
  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Pivotal Labs

Standup 04/14/2010 – MySQL and Cloudfront

Pivotal Labs
Thursday, April 15, 2010

Interesting Things

  • One of our teams saw a significant (20%+) speedup on their product by switching to Amazon’s Cloudfront service. They’re using Paperclip and it only took about 20 minutes to switch from S3 to Cloudfront.

  • If you have an integer column in MySQL that does not allow NULL values and you update a row and set that column to NULL the column ends up being set to 0. This was very surprising to one of our teams.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter

Topics

  • agile (780)
  • rails (113)
  • testing (88)
  • ruby (83)
  • ruby on rails (70)
  • jobs (62)
  • javascript (55)
  • techtalk (44)
  • rspec (38)
  • ironblogger (32)
  • productivity (30)
  • activerecord (29)
  • gogaruco (29)
  • git (28)
  • nyc (27)
  • rubymine (26)
  • bloggerdome (23)
  • mobile (22)
  • process (21)
  • pivotal tracker (20)
  • cucumber (20)
  • jasmine (19)
  • design (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)
  • bdd (14)
  • gem (13)
  • css (13)
  • tdd (13)
  • selenium (12)
  • goruco (12)
  • bundler (12)
  • meetup (11)
  • railsconf (11)
  • nyc-standup (11)
  • capybara (10)
  • mac (10)
  • mojo (10)
  • chef (10)
  • api (10)
Subscribe to Community Feed
  1. 1
  2. 2
  3. 3
  4. →
  • 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 >