Dan PodsedlyDan Podsedly
Third Party Tools for Pivotal Tracker
edit Posted by Dan Podsedly on Tuesday December 30, 2008 at 05:30PM

We released the first version of the Pivotal Tracker API a couple of months ago, and already there is a growing list of useful 3rd party tools out there:

Pivotal Tracker for Ruby

This is a ruby wrapper for the API, written by our friends at Mobile Commons.

http://mcommons.com/developers/pivotal-tracker-for-ruby

Email Integration

Also from Mobile Commons, this tool allows your to automatically create Tracker stories from inbound emails.

http://mcommons.com/developers/pivotal-tracker-email-integration

GitHub Post Receive Hook

This is web service that you run on your own server, written by Chris Bailey. It automatically updates stories in your project(s) based on GitHub commit comments:

http://codeintensity.blogspot.com/2008/12/github-post-receive-hook-for-pivotal.html

Pickler

Synchronize stories in Pivotal Tracker with Cucumber features. If you haven't heard of it yet, Cucumber is a really cool app that can execute plain-text documents as automated functional tests.

http://www.github.com/tpope/pickler/tree/master

More Tools

There are more, most of them live in GitHub:

http://www.github.com/search?q=pivotal+tracker

If you have written something you'd like to share, or know of other useful tools, let us know! Also, we're planning on making the API better, and would love your feedback.

Rajan AgaskarRajan Agaskar
Standup 12/30/08
edit Posted by Rajan Agaskar on Tuesday December 30, 2008 at 05:23PM

Interesting Things

  • Ruby Hash is really, really, really fast

If you're building a data structure and you need it to be perfomant, Ruby Hash comes highly recommended from Steve Conover. If you're doing a dance and you need it to be awesome, I highly recommend the Robot. Or maybe the Cabbage Patch.

  • Counter cache, fixtures, and invalid data

Invalid counter cache data can cause unexpected behavior. For example: size() returning a bad count or associations asserting they're empty when they aren't. In this case, the invalid counter cache data was caused by bad or missing fixture values, a situation that was not caught out by the debugger. With this in mind, it may be useful to resort to puts/p statements if you suspect the counter cache is the source of the problem.

  • Count or Size methods may return incorrect values from associations or named scopes using GROUP BYs

When calling 'count', or 'size' on an association, Rails replaces the select of the actual query with a COUNT(*), and strips GROUP BY statements. This can cause the returned count to differ from the actual number of records. A simple (and expensive) workaround is to use .length, which will force the association to be loaded and then return its count. A better method is to pass a :select value to count which selects a COUNT(DISTINCT(foo)) where foo is the column you are grouping by. It is worth nothing that COUNTing DISTINCT records is much less of a performance hit then actually returning their values, so the resulting query is faster than you might expect.

  • first and last on has_many associations

This has been previously mentioned in this space, but as we're on the topic of unexpected ActiveRecord behaviors, it's worth reiterating. If you have model Foo, which has many Bars, calling foo.bar.first will always go to the database. This means, for example, that the following statements will not have the expected result:

foo.bar.first.some_value = 'baz' foo.bar.first.save

You would normally expect this to set some_value on foo.bar.first to 'baz' and then save it, but the foo.bar.first object that has some_value is blown away by the foo.bar.first.save statement, which again retrieves the first object from the database (and then saves it). last behaves in a similar manner. A workaround is to always load the results of first or last into an variable and then work with it. In other words:

my_foo = foo.bar.first my_foo.some_value = 'baz' my_foo.save

For a much more thorough treatment of this subject, please see Frederick Cheung's post First, foremost, and [0].

ActiveRecord::BaseWithoutTable is very handy for when you want ActiveRecord validatioons on a model that does not have a corresponding table (for example, a feedback form).

Steve ConoverSteve Conover
Agile and Trust
edit Posted by Steve Conover on Tuesday December 30, 2008 at 05:01AM

Edward pointed out the great article by Kevin Matheny, featured in BusinessWeek, on Agile, and our experience on BestBuy Remix.

I'd like to highlight this passage:

Trust is tied closely to how you deal with change. Often, extending trust is hard for businesspeople working on technology projects, because we don’t know how to do the work. We often look to the documentation — requirements, design specifications, and the like — to give us the feeling of control over the outcome. Don’t bother. If you can’t trust your team to deliver, you have the wrong team. Find people you can trust, and then let them do the work. Talk every day, and make sure that the development team has direct access to someone who will be using the product every day after release. For Remix, we’ve never had a formal project plan, never had a requirements-gathering session, never created a requirements document. We chose the right partners, told them what we needed, and got to work. We have control over the outcomes, but we’re not worried about trying to control the details of how we get there.

Of course without trust, any project - "agile" or not - is at risk. But practices typically associated with agile let you go further with trust: everyone is in close communication*, and all levels of the project - from test-driven code written by developers, to regular demos to the client of the latest features - are oriented around fast feedback.

In other words, you the customer trust us in part because what we're doing is visible and tangible to you. If we're going in a direction you didn't intend, or what the team planned a few weeks ago just doesn't seem relevant anymore, we all talk and we correct course.

* for close communication, see Pivotal Tracker

Edward HieattEdward Hieatt
Best Buy & Pivotal Labs
edit Posted by Edward Hieatt on Monday December 29, 2008 at 11:31PM

Kevin Matheny, Senior E-Biz Architect at Best Buy, has an excellent article today on BusinessWeek.com about Best Buy's take on Agile software development and Best Buy's experiences as a client of Pivotal Labs. As he mentions in the article, Pivotal Labs has been helping Best Buy build "Remix", an API for the BestBuy.com product catalog. Kevin describes the agile methods that Pivotal Labs uses and how they've helped with what he calls "Corporate Agility", which he describes as "working components instead of complete solutions, expecting and responding to change instead of trying to eliminate it, and trust rather than control." He also describes how Pivotal Tracker fits into Pivotal's agile process:

For example, I recently added a story to the tracker for Remix that read simply "flag products as new if their start display date is less than 30 days in the past." That's all the up-front documentation needed for Pivotal Labs, a development company that specializes in agile software development, to code that function into Remix. Any additional information can be gathered in the daily 15-minute team meetings or in a longer follow-up if more time is required.

Thanks for the mention, Kevin, and we're very glad that the project is proving to be successful. Pivot Steve Conover is at the helm.

Steve ConoverSteve Conover
net/http alternatives
edit Posted by Steve Conover on Monday December 29, 2008 at 09:00PM

net/http is slow. (and so are libraries that depend on it, like open-uri)

Performance Disclaimer: this ought to matter in your app, measurably, before you do anything about it. If you profile and ruby-prof is showing a bunch of classes like BufferedRead and Timeout at the top of the list, your app qualifies. And in addition if you know that your app is dependent on data transfer over http (let's say you're interacting with a Solr server, and you're storing sizable documents in Solr), you should be aware of the problem.

Otherwise net/http or open-uri might be just fine for you.

The problems with net/http, and benchmarks of ruby http client lbraries are nicely written about in An analysis of Ruby 1.8.x HTTP client performance.

Some good alternatives:

Our findings matched the article referenced above - the alternatives have pros and cons but each was at least 10x faster than net/http for transfers of 50-300k response bodies.

The fastest solution we found was curb, reusing the Curl::Easy object:

require "curb"

curl = Curl::Easy.new

2.times do
    curl.url = "http://www.pivotaltracker.com"
    curl.perform
    puts curl.body_str
end

Rajan AgaskarRajan Agaskar
Standup 12/29/08
edit Posted by Rajan Agaskar on Monday December 29, 2008 at 05:11PM

Interesting Things

  • Net::HTTP is slow

Recommended alternatives: Curb, httpclient, rfuzz.

Please see Steve Conover's writeup for more details.

  • Marshall Dump/Load encoding issues foiled by Base 64.

When storing to a string via marshal_dump, it can be handy to encode to Base 64 first. The same string -- once marshal-loaded and Base 64 decoded -- should be free of any encoding and/or escaping errors. Is there anything Base 64 can't do?*

* the answer I am looking for here is "win a knife fight against tigers."

Adam MilliganAdam Milligan
Keeping your errors in line
edit Posted by Adam Milligan on Saturday December 27, 2008 at 09:44PM

How many times has this happened to you? You get a cool design for your website, and you spend a bunch of time lining up all of your images and roundy-corner widgets and input boxes just... so..., and everything looks great. But, then you submit a form without typing in your favorite ice cream (a required field, of course), and suddenly your layout is splattered about like an extra large scoop of rocky road in the hands of a two year old. It's enough to make you want to stab your eyes out with a hedge trimmer.

Adam MilliganAdam Milligan
has_one-ish :through
edit Posted by Adam Milligan on Saturday December 27, 2008 at 09:06PM

Rails has had the has_one :through association for a while now, and you probably use it on occasion. But, has it ever given you the heebie-jeebies a little bit? Maybe something happens now and then that doesn't seem quite right? Well, the reason for this is that HasOneThroughAssociation, the class that ActiveRecord uses (shockingly) to implement has_one :through associations, is a subclass of HasManyThroughAssociation.

Whhaaaaaaaaaat?

Yes, oddly enough, a has_one :through association is a collection that is special-cased to always return just one element. Seems kind of dirty, doesn't it?

Adam MilliganAdam Milligan
#method_missing makes me eat my words
edit Posted by Adam Milligan on Saturday December 27, 2008 at 07:06PM

A while back I wrote about private methods in ActiveRecord objects, and how Rails 2.2 makes them behave as they should. ActiveRecord associations will no longer respond to private methods defined on their targets; however, my colleague Joseph pointed out that they also no longer respond to methods defined via #method_missing on their targets. Which sucks horse poop through a straw, to some extent.

Rajan AgaskarRajan Agaskar
Standup 12/24/08
edit Posted by Rajan Agaskar on Wednesday December 24, 2008 at 05:14PM

Interesting Things

  • Rails 2.2 Exception Notifier

Setting the Exception Notifier sender address outside the post load block in Rails 2.2 can cause long load times. Like, 6 minutes long. Why? GLOBAL WARMING! Which is to say we aren't sure, but it probably involves class pre-loading*.

* The natural corollary being, of course, that class pre-loading causes hurricanes.

Other articles: