Fixing the Broken Pipes: Updating RubyGems

Posted by andy, Tue Oct 14 14:30:00 UTC 2008

Why do we need the plumber?

If you're like me you might slip into a comfort zone and not keep up with all the updates to gems and plugins, especially since github has taken plugin/gem development and forking viral. Usually that's not much of a problem. Unless, of course, the change is to the gem package manager itself.

I'm not sure exactly what changed. What I know is that any time I tried to do a '(sudo) gem install my-cool-gem' it failed with an error that looked like this


Bulk updating Gem source index for: http://gems.rubyforge.org/
Bulk updating Gem source index for: http://gems.github.org/
ERROR: While executing gem ... (Gem::RemoteFetcher::FetchError)
     Errno::EPIPE: Broken pipe reading http://gems.rubyforge.org/gems/...some-poor-gem.gem

As best as google has been able to help me find the problem lay in the the increasingly large number of gems available. The large, uncompressed source of gems times out the connection. Fortunately that appears to be fixed in the latest version of rubygems. Version 1.3.0 was released yesterday. But now you've got a chicken-and-egg problem if you have relied on gems to update itself -- the Broken Pipe problem prevents you from getting the version that doesn't have the Broken Pipe problem.

Installing the gem locally

The simple answer to the question is to install the gem from a local source rather than a remote source. It works the same as the tried and true "gem install my-cool-gem" with just one extra step. Here's what I did specifically to fix the issue with the gem package manager.

  1. Navigate over to the rubygems download page at rubyforge.
  2. Download the latest rubygems-update gem (currently rubygems-update-1.3.0.gem)
  3. Move the gem somewhere handy in case you want to install it again.
    Personally I created a Gems subfolder and moved the gem from ~/Desktop to ~/Gems.
  4. Install the gem locally using a locally named source:
    sudo gem install rubygems-update -n ~/Gems
  5. Once the gem update is installed you still have one more step! (Emphasis for my own needs -- I keep forgetting this). From the command line:
    update_rubygems

Once I updated to rubygems v 1.3.0 the Broken Pipe Problem disappeared on my Ubuntu box. Hope the same is true for you!

6 comments | Filed Under: | Tags:

Early October Meeting - 10/14 at Noon

Posted by andy, Wed Oct 08 13:00:00 UTC 2008

Essential Ruby for Rails Nubies

You saw the video and created your blog in fifteen minutes. You read the first dozen chapters of the Agile Web Development book and have running depot or tried to get Ruby on Rails: Up and Running but struggled when things got deeper. Now what?

This months talk will be a preview of the talk that I'll be giving at the South Carolina Ruby Conference the following Saturday on Essential Ruby Idioms for Rails Developers. We'll dust off some of the black magic in Ruby that can help Rails a joy to develop while keeping your code clean and concise. Please come and contribute your insights into what makes Ruby such a joy to use.

Once again we'll be meeting at Immedion. If you need directions you can find them here

Update: Slides available

You can get the slides here.

0 comments | Filed Under: Meetings Rails | Tags:

Check out STI Revisited

Posted by andy, Wed Oct 01 13:00:00 UTC 2008

I just added a revision of my earlier post about Single Table Inheritance (STI), along with making the code available as a plugin from github. The article lays out the basic ideas behind STI, the potential need for a factory method, and the way that alias_method_chain can bring that about.

0 comments | Filed Under: | Tags:

[CANCELLED] September Meeting: Unobtrusive Javascript with Low Pro

Posted by ryan, Thu Sep 18 15:30:00 UTC 2008

UPDATE: The meeting this month has been cancelled. We just didn’t have enough people to make it out. We’ll shoot to be on track for the regular time in October.

When: Tuesday, September 23, 2008

Ryan is going to walk through how to make your Rails apps less obnoxious. Using Low Pro by Dan Webb we will refactor some of rails native ajax helpers that cludge up your source code with random bits of javascript to the http backward compatible, ajax enhanced, cleaned up source version of the same feature.

The start time has moved up to 11:45am so we can chat before the presentation begins at 12:00pm. If you’re pressed for time at lunch, feel free to come right at 12:00pm.

FREE LUNCH

Tek System will provide lunch. Please let us know if you’re planning to be there (on the mailing list) so we can get a good headcount. We’re looking at sandwiches or pizza. It will be a surprise! ;)

Location

Immedion will be graciously hosting us again. Click here for directions.

0 comments | Filed Under: Meetings | Tags:

August Meeting is over dinner instead

Posted by ryan, Wed Aug 27 13:50:00 UTC 2008

We will be having dinner Wednesday night at 6:30pm at California Dreamin off Pelham Rd. in lieu of our normal meeting this month. Please RSVP on the mailing list. Hope you can make it.

0 comments | Filed Under: Meetings | Tags:

July Meeting - Tues 7/22 @ 12pm

Posted by ryan, Fri Jul 11 22:56:00 UTC 2008

UPDATE: FREE LUNCH! Lunch will be provided by Tek Systems. See below for details.

Topic: Rails 2.1 Roundtable

With the release of Rails 2.1, there are a number of new tools at developers disposal. Ryan will walk through an overview of new tip & tricks so you too can be on the cutting edge of Rails development again.

Doors are open at 11:45am so we can chat before the presentation begins at 12:00pm. If you’re pressed for time at lunch, feel free to come right at 12:00pm.

Location

Immedion will be graciously hosting our group. Click here for directions.

Lunch

We WILL have a sponsored lunch. I’ll need a headcount by Monday. Please let us know through the mailing list. Thanks!

0 comments | Filed Under: Meetings | Tags:

Problem with named_scope and :include?

Posted by andy, Thu Jun 26 12:30:00 UTC 2008

Recently I've been using the great Rails 2.1 addition called named_scope to help simplify the process of building queries with meaningful names. Certainly you could do something similar by creating a custom method, but as I wrote earlier, the advantage of named_scope is that the scopes are composable: you can chain them together to build ever more powerful queries.

That's why I've been really frustrated trying to get named scopes to work with the :include option. In one scenario I have been trying to sort a collection by a field that exists in an included table. If I were doing freight-forwarding the models involved look something like this.

class Customer < ActiveRecord::Base
  has_many :product_offerings
  has_many :products, :through=>:product_offerings
end

class Product
  has_many :product_offerings
end

class ProductOffering
  belongs_to :customer
  belongs_to :product

  named_scope :by_name, :include=>:product, :order=>:name
  named_scope :for_customers, lambda{|customer_ids| {:conditions=>{:customer_id=>customer_ids}}}
end

The objective I have in mind is to build a named_scope that allows me to list all the products for a particular customer alphabetically by the name of the product so each customer can check their inventory. In the day and age where holding companies are involved an individual user may be authorized for several companies and thus want to be able to get a unified inventory list for all the companies for whom he works. That's where the second named_scope comes into play. I'd like to be able to do this:

# all the product offerings listed by product name
ProductOffering.by_name

# all the product offerings for a set of customers
ProductOffering.for_customers([1, 2, 3])

# all the product offerings by name for a user's companies
ProductOffering.by_name.for_customers(@current_user.customer_ids)

But it doesn't work. For some reason the :include option seems to get dropped and I end up getting SQL errors reporting an unknown column name. I've found one stray comment that suggests that you may be able to fix the issue by adding the conditions necessary to make the SQL join work. That is we could expand the named_scope to something like

named_scope :by_name, :include=>:product, :order=>:name, :conditions=>["products.id = product_offerings.product_id"]

That's ugly. Really ugly. It also pushes perilously close to letting ProductOffering peek into Product too much. If you begin to go that route be careful because you'll be on the slippery slope of a brittle solution that won't survive refactoring.

The simple solution is to bypass :include in favor of :join. I don't understand why :join works more reliably but I'm sure the answer is down there in the source code if you want to dig around. I suspect that the answer lies in the way that Rails 2.1 breaks joins into two distinct fetches now in order to reduce the cost of spinning up redundant ActiveRecord instances (see the Relationship Optimised Eager Loading discussion.). Whatever the case, the workable, concise solution looks like this:

named_scope :by_name, :joins=>:product, :order=>:name

If you already need to include conditions on the join table you can probably continue along as you normally would. In this situation the only requirement on the join table is that the IDs match so I prefer the concise solution.

1 comment | Filed Under: | Tags:

June Meeting Cancelled

Posted by ryan, Thu Jun 19 14:10:00 UTC 2008

Just a quick note to let you know that the June meeting has been canceled. Keep a look out for announcements for some geek dinners this summer.

0 comments | Filed Under: Meetings | Tags:

New in Rails 2.1: Timestamped migrations

Posted by andy, Mon Jun 02 22:00:00 UTC 2008

What was wrong with migrations?

If you've been part of any development team that was larger than the "Army of One" you've probably run into an issue with migrations. It's happened to me a few times: one member of the teams goes head-down on some problem and it takes longer than expected. Not wanting to check in 'broken'' code the patch builds up for a while... and so do the migrations to fix db issues. Finally ready, the change gets checked in and ... poof... What worked no longer works. Why?

While Mr. Fix-It was head down the trunk was updated with other migrations. But these migrations had overlapping numbers so when they merged into the code base it was unpredictable which ones would be run on any given system. To be clear, the migrations will be run in a very definitie order. They're run in alphanumeric order, but only one migration of a specific 'version' will be executed. As a result, which migrations are run on your system depends on how many you'd already checked out and run and the alphabetical naming of each script. Now it's up to you and your team to rename all the migrations, backing them out one by one and adding them back to make sure all the database changes are applied appropriately. Yikes!

Enter Sandman

Disclaimer: I've only heard 'Sandman' when certain closers enter baseball games but I thought someone would appreciate the reference

The new timestamped migrations may put all these issues to rest. Instead of prefixing the migrations with 001, 002, 003, etc the prefix will now be a timestamp. So, the result of running a 'script/generate scaffod MyObject attribute1:string attribute2:integer' will be a file with a name like 20080601214508_create_my_object. The likelihood that you and a teammate create a migration at the exact same time is pretty small so the 'level collisions' are almost surely a thing of the past.

Tracking revisions, not the version

Even better, though, is that the schema_info table will now track revisions, not only the latest version. That is, every migration that is run via rake db:migrate will be recorded in the database. As a result, whenever Mr. Fix-It decides to enlighten the rest of the team with his update, a rake db:migrate will be able to identify the individual migrations that have not been run whether they were on Mr. Fix-It's machine (when he finally updates from trunk/master) or on a teammates' machine (when the patch is loaded).

Even better, there are new rake db:migrate:up and rake db:migrate:down commands. These commands accept an individual migration 'version' (the time stamp) and either run it (up) or back it out (down). Remember that table that you created and decided you'd overengineered? Now it's a lot easier to back that one out.

Could it get even better?

Yes, it could get better. Those of you who've read The Rails Way (Obie Fernandez, Addison-Wesley Professional Series, 2007) may have come across a recommendation to accumulate migration changes until they are pushed to production. That is, rather than create three migrations for a table and some additional fields while the table is in development, there is a recommendation to have one create script that gets updated until it's pushed to production. I've tried this on a couple of apps and really liked the approach because it cuts down on the 'noise' in the migration collections. I'm willing to accept the argument that migrations are not really necessary for tracking database changes until they change something beyond development.

What could be even better that the current implementation of the timestamped migration would be if it could detect these changes in the migration files. It should be possible to check the creation and update times of the files to see if they've been updated and then validate the updated time in the migrations db. This particular idea has some drawbacks, particularly if a production migration were ever touched accidentally.

0 comments | Filed Under: Rails | Tags: