All posts by Brian Morearty

You Should Update One Gem at a Time with Bundler. Here’s How.

[Update: added example of updating the sextant gem, which causes Rails to be updated as well.]

[Another update: see the comment below from Andy Waite about an official, approved, documented way to update as few gems as possible.]

Hey Ruby developers,

When you run bundle update to update your gems, it updates all of them at once. If your app stops working or your tests start failing, it can be pretty hard to figure out which gem update broke it.

There are a couple of solutions I’ve seen people use to solve this. Neither of them is that great:

  1. Lock the versions numbers in your Gemfile. But hey, that’s a pain and it’s what Gemfile.lock is for. Locking the version numbers in the Gemfile should be the exception, not the rule.
  2. Run bundle update gemname.

You might think bundle update gemname would just update that gem. But no, it also updates the gem’s dependencies—whether they have to be updated or not.  In fact, updating a third party gem can even upgrade you to a new version of Rails behind your back.

Here’s what the Bundler doc says about bundle update gemname:

UPDATING A LIST OF GEMS

Sometimes, you want to update a single gem in the Gemfile(5), and leave the rest of the gems that you specified locked to the versions in the Gemfile.lock.

For instance, in the scenario above, imagine that nokogiri releases version 1.4.4, and you want to update it without updating Rails and all of its dependencies. To do this, run bundle update nokogiri.

Bundler will update nokogiri and any of its dependencies, but leave alone Rails and its dependencies.

Yeah, sure, that sounds nice. But read that last sentence again: “Bundler will update nokogiri and any of its dependencies.” Well, heck. Some gems depend on a ton of other gems. And why not? Nothing wrong with that. And it makes sense to update the dependencies if something new is required for the update to work. But Bundler updates them no matter what. And now you’re back to the problem I stated at the beginning: even if you intend to update only a single gem, you still end up updating a whole boatload of gems. So when your app breaks or your tests fail, it takes a lot of time to figure out why.

Want an example of an unexpected side-effect of bundle update? I have a good one. Let’s say you’ve installed the sextant gem into your Rails app so you can see your Rails routes in development mode by navigating to /rails/routes. (It saves time compared to rake routes since the environment is already loaded.) In this example you are on Rails 3.2.2 and sextant 0.1.2. Now you run bundle update sextant to update to 0.1.3. Do you know what you just did? You upgraded Rails from 3.2.2 to 3.2.6. I don’t know about you, but I don’t like having my version of Rails updated just because I got the latest version of some little helpful gem.

When writing this blog post I tried a few scenarios. I found something else interesting:

With bundle update gemnameeven if there is no newer version of that gem, it will still update everything the gem depends on.

Here’s an example. My app has version 0.3.4 of haml-rails, which at the moment is the newest version. I run:

bundle update haml-rails

After that, git diff informs me that my Gemfile.lock now has newer versions of the journey, json, multi_json, and sprockets gems. Even though it didn’t find an update to haml-rails.

The Solution: bundle update ––source gemname

Bundler has a solution, but in my opinion it’s hard to understand the documentation.

Here’s what you do:

bundle update ––source gemname

I started diving into Bundler’s code and specs to see exactly what this does but it was taking more time than I wanted to spend. But I’ve been using this for more than a year and it works great. I recommend this be your default way to update a gem. If it doesn’t work due to a dependency conflict with other gems then you can always fall back on bundle update gemname.

As far as I can tell, using ––source is the equivalent of the following, but without all the work and headache:

  1. Specifying version numbers for everything in your Gemfile.
  2. When you want to update a gem, running gem list -r gemname to find out its latest version number.
  3. Changing the version number in your Gemfile for just that one gem.
  4. Running bundle install.
If you look at bundle update‘s documentation for ––source, it doesn’t help much. Here’s what it says:

OPTIONS

––source=<name>

The name of a :git or :path source used in the Gemfile(5). For instance, with a :git source of http://github.com/rails/rails.git, you would call bundle update ––source rails

By the way, the bundle update documentation does mention conservatively updating dependencies. Here is what it has to say: “For more information, see the CONSERVATIVE UPDATING section of bundle install(1) bundle-install.1.html.” The bundle install section on conservative updating does indeed describe how to update dependencies conservatively. However, this section assumes you are specifying version numbers in your Gemfile. As I mentioned above, I prefer to do that only as an exception.

See ya.

How to Find a Record in ActiveRecord Using either an ID Or an Object

Have you ever written written code in an ActiveRecord model where you wanted the caller to be able to pass in either an object or an id?

In this example you want to know if a user has read a post. Your join table, readings, tells you which users have read each post.

class Post
  has_many :readings

  def read_by?(user_or_id)
    readings.where(:id =>
                     Fixnum === user_or_id ?
                     user_or_id :
                     user_or_id.id).exists?
  end
end

Good news: you don’t have to go through all that. ActiveRecord checks for you if the object is a number or a model. You can simplify the code quite a bit.

In this rewritten version the user parameter of the read_by? method can be either a user object or a user id:

class Post
  has_many :readings

  def read_by?(user)
    readings.where(:id => user).exists?
  end
end

How to Make HTML5 Autofocus Work in IE

If you want to use HTML5’s autofocus attribute and make it work in all browsers, here’s an easy way to do it in one line of jQuery. This code will bail out and do nothing if the browser supports HTML5 autofocus.

$(function() {
  $('[autofocus]:not(:focus)').eq(0).focus();
}

How it Works

  1. [autofocus]: Find all attributes with the autofocus attribute…
  2. :not(:focus): …but not the ones that are already focused. This results in a list of length 0 in any HTML5-capable browser, so nothing more will happen.
  3. .eq(0): Get the first one since it doesn’t make sense to focus multiple elements.
  4. .focus(): Set focus to it.

Send a Page from Safari to Opera Mini When You Need to Reflow Text on the iPhone

You’re on your iPhone surfing the tweets and you come across a link to an article or discussion you want to read. You click it and start reading. But the text is too small so you two-finger zoom. But that makes the text too wide for the screen, even in landscape mode. And now you’re stuck feeling like a blooming idiot swiping your finger side to side down this long page while you try to read it. It distracts you from the thing you’re trying to read and it takes too long.

I Like Stuff That’s Not Horizontal Scrolling

The iPhone’s Safari browser can’t re-flow text in wide columns on web pages. For people like me, this is a deal-breaker. Scrolling side-to-side over and over again just to read a web page is time-consuming and annoying. It’s the primary reason I switched to Android a year and a half ago. Android’s browser fixes this problem exactly the way you would want: if you two-finger zoom into some text it immediately re-flows the text to fit the new screen size. I love it.

In iOS 5, Apple finally introduced Reader mode. A little “Reader” icon appears in the URL bar of some pages. Clicking it enlarges and reflows the text for better readability. It’s nice–when it works. Apple says “Reader in Safari smartly recognizes when there’s an article on the page,” but unfortunately it’s not as smart as they claim. There are plenty of pages where the text is too wide but the Reader icon doesn’t appear, so you’re still stuck scrolling side-to-side as you attempt to read.

For an example of a page that doesn’t re-flow nicely and doesn’t offer Reader mode, use your iPhone and try reading this discussion of Safari text re-flow on the Apple Support Communities site.

Opera Mini to the Rescue

There are other browsers that can claim they can reflow text on the iPhone. I’ve tried a bunch of them. The one I find does the best job of re-flowing text with minimal hassle on a wide variety of pages is Opera Mini, which is free and fast.

Here is the aforementioned discussion thread. The first picture is in Safari after zooming in to a readable font size. The second is Opera after doing the same. See the difference? In Safari you have to scroll side to side to read it. In Opera you don’t.

To enable text re-flow, go to Settings and turn on the “Text Wrapping” setting.

But Safari is the iPhone’s Default Browser

So that’s all well and good but what about that little story about surfing the twitterverse and clicking a link? Whenever you click a URL in any other app like email, Twitter, Facebook, etc., the iPhone will open the page in Safari. Apple doesn’t give you a choice. You can’t tell it to open in Opera. Sure, you could click in the URL, then long-click it, then choose Select All, then choose Copy, then launch Opera, then click the Opera URL bar, then click Paste. But by the end of all that it’s time to go to bed.

Well I just figured out a little workaround that costs nothing and lets you send any page from Safari to Opera in two clicks. So at any time you’re two clicks away from reflowing your text.

The trick is to use a bookmarklet I made called Send to Opera.

  1. First click: the Bookmark icon.
  2. Second click: the Send to Opera bookmarklet.

To add it, go to this Send to Opera page and follow the instructions.

How does it work? It simply inserts the letter “o” at the beginning of the URL. For example if the URL is http://104.237.154.7/, Send to Opera tells the browser to open ohttp://104.237.154.7/. With an O at the front, the request is sent to Opera.

Cool, huh?

19-Minute Video: CoffeeScript for Rubyists

If you’re a Ruby programmer and want a quick little intro to CoffeeScript so you can decide whether you might want to use it, check out the 19-minute talk I gave last week at a really fun Code Social meetup at RocketSpace in San Francisco. The talk was “CoffeeScript for Rubyists.”

Abstract

Is CoffeeScript really so great? Why use it instead of good ol’ JavaScript? Which of my favorite syntax goodies does it steal from Ruby? It looks Pythony with all that significant whitespace. How can I use it in my pre-3.1 Rails project? How do I convert my legacy JavaScript? Why is Internet Explorer no good at exploring the Internet? Brian Morearty answers most of these questions. He’s a Ruby aficionado who has used CoffeeScript for his client-side coding for a few months. In this talk he does a quick demo of how to install CoffeeScript, convert your JavaScript to CoffeeScript, and include it in a pre-Rails-3.1 application. But most of the talk is on details of the language, including stuff it stole from Ruby that make it just dang fun for a Rubyist to program in CoffeeScript. And he even covers one thing that is *gasp* better than Ruby.

Slides

Here are the slides for this CoffeeScript talk.

Video

And here’s the video:

How to Free Up Inactive (Blue) Memory in Mac OS X

Want to turn Activity Monitor’s “blue” (inactive) memory to “green” (free) on your Mac without closing any programs?

Run Terminal and type:

  $ purge

My memory went from  to  the last time I did this. Not too shabby. (Why did it also clear up some Active Memory? I have no idea.)

That’s all you have to do. It can take up to a minute. While purge is running your system will be slow. After that, with all that free memory, it’ll be zippier than before.

Don’t listen to all the remarkably obnoxious fanboys or official Apple support pages telling you just to leave Inactive Memory alone because it will be freed up quickly if it is needed, or that the system knows better than you do when to free memory. Trust your experience. In my experience it will not and it does not. 

Here is the purge man page:

PURGE(8)                  BSD System Manager's Manual                 PURGE(8)

NAME
     purge -- force disk cache to be purged (flushed and emptied)

SYNOPSIS
     purge

DESCRIPTION
     Purge can be used to approximate initial boot conditions with a cold disk buffer
     cache for performance analysis. It does not affect anonymous memory that has been
     allocated through malloc, vm_allocate, etc.

SEE ALSO
     sync(8), malloc(3)

Use Spin for Faster Test Iterations

RAILS TESTS - Y U NO EVEN START YET?!

Do you ever re-run the same Rails test file over & over while working on a feature and trying to “make it green?” Change the code, run the test, change the code, run the test, etc. (I’m talking about when you want to re-run a specific test, not using guard to autodetect which tests to run.)

When you do that you have to wait a long time for the Rails environment and your app’s initializers to load. You pay this price every time you re-run the test—even if you’re not changing your initializers. I get ants in my pants sitting around waiting for the environment to load.

I just learned about a new gem that doesn’t require any changes to your tests and that speeds up this test-code-test-code cycle by only loading your environment once: it’s called spin.

https://github.com/jstorimer/spin

Basically you do this:

  • In one terminal window type spin serve. This launches the spin server, which waits for commands over a socket.
  • In another terminal, when you want to run the tests in a single file, type spin push path/to/testfile.rb
  • You can push multiple filenames at once if you like.
  • One limitation: it does not let you use the :linenum syntax that rspec uses to run just one test in a file.

That’s it. I tried it on a test file that takes 8 seconds (after everything has been loaded). Total time to load and run this file went down from 26 seconds to 13 seconds when I used spin.

I looked at the source. It’s short and simple. Here’s how it works:

  • spin serve preloads your app’s config/application.rb.
  • Then it waits for commands on a socket.
  • When a command comes in it forks a new process and runs tests in the fork. The fork doesn’t have to reload the Rails environment or initializers because they’re already loaded.
  • When done, the fork just exits and spin is ready for a new command.

Remember that if you do change your initializers or anything else that is loaded by application.rb you should restart the spin server. Another time you may want to restart it: after checking out a different branch in git.

Safe and easy. Faster tests. What could be better?

Dear GitHub: Please Improve Your Notifications

An Open Letter to GitHub

[Update 8/6/2012: good news. GitHub has just released a complete overhaul of their notification system. After reading the blog post about it, it looks as if they have fixed most or all of the issues I raised in this post. It looks like a lot of thought and hard work went into this change. Thanks for listening, GitHub.]

Dear GitHub,

Hi guys!

Guess what: GitHub’s great. Yeah, you know that.

But hey: could you please fix GitHub notifications? They seriously suck. No, really, I mean it. They’re the worst. Sorry, I don’t mean to hurt your feelings. I know a human being designed the notification system.

GitHub notifications are a productivity sink. Despite having fifteen checkboxes for customization in the Notification Center, I still can’t make them work in a way that helps me. Don’t get me wrong, I am not asking you to fix it by adding more checkboxes to the list. I am asking for an overhaul of how the notification system works. Below I will try to clearly lay out the problems I see and what I would like the system to do instead. The overall goal is to change notifications from a productivity sink to a productivity boon. Continue reading

Best Presentations of RailsConf 2011

Hey all,

Yesterday evening I got back from RailsConf 2011. It was a lot of fun and I saw a lot of really good presentations with good technical content, and some that were both useful and funny (double dream hands and Ke$ha).

But I also missed some of the best talks. O’Reilly has posted some of the videos and is working on posting more.

But how to decide which ones to watch?

On the plane ride home I wrote a one-page site to answer that question. It scrapes the star ratings from O’Reilly (hope you guys don’t mind!) and shows the sessions with the highest-rated ones at the top. I didn’t have wifi so I had to guess what CSS selectors I should use to scrape the RailsConf site. Once I got home I fixed the selectors, polished it up, and pushed it to Heroku.

Here it is: the Best of RailsConf 2011.

If you find problems, please fork and improve it.

Hello, Entrepreneur. (And Consultant.)

The last time I changed jobs it was the spring of 1999, in the glory days of the dot-com frenzy. I decided to leave my job at an enterprise software company that shall remain unnamed (but it starts with “O” and ends with “racle.”) Enterprise software was not where my heart was. I thought about joining a startup and I talked to a bunch of them, but they all said the same thing when I asked about their business model: we’re not making any money but don’t worry, we’ve got millions of customers.

I knew we were in a bubble. Don’t get me wrong—I’m no soothsayer and I couldn’t tell you exactly when the bubble would burst, but it was clear it would. So I joined Intuit, the only company I interviewed with that was actually making a profit.

It turned out to be a pretty good choice.

The nearly 12 years I worked at Intuit were amazing. The QuickBooks team warmly welcomed me. I worked with fantastic people. I became the tech lead for the UI Toolkit team. I worked on a lot of elegant little touches that make the user experience more delightful, like a better quickfill (autocomplete) control. I trained engineers on how to build great user interfaces. I stayed there til 2005 when I decided to try something new, but Intuit is such a great place to work that I just transferred to another group. I moved around a couple more times, always staying in the Small Business Division, and since 2008 I have been doing web development in Intuit’s Grow Your Business division. This is the group that makes Intuit Websites.

I recently decided the time has come again to change jobs. But this time is different. Instead of looking for a job as an employee somewhere else, I’ve decided to do something I’ve been thinking about for a number of years: I am becoming a software entrepreneur and consultant/trainer.

Both? Well, yeah—I’ll be spending 30 hours a week consulting and training (focusing on Ruby on Rails and JavaScript) and the remaining time starting my own business.

My Startup

During my “entrepreneur” time I am creating a website with tools and community for small real estate investors. I am an investor myself, having bought houses and condos in Southern California, Arizona, and even Melbourne, Australia. When I got started with investing I was willing to invest anywhere in the U.S., but I had one big question:

Which market should I invest in?

The answer depended on what was I looking for in a real estate investment. Some investors look for equity growth, others for cash flow. Some look for a market on an upswing, others for a market in a trough. Some look for job growth, some for immigration, some for vacancy rates, and on and on. The thing is, all this data is available for free from the U.S. Government but it’s really hard for a small real estate investor to find. And once they’ve found it, it’s also hard to collate it and get a quick answer to the simple question of which market to invest in. Real estate agents can be helpful but unless you happen to find one who specializes in finding investing opportunities around the country, they won’t really know what to recommend. In that case they’re likely just to tell you that their own market is a good one to invest in.

So a few years ago I started working on a web app to solve this problem and recruited my friend Ed to help out. Think of it as Kayak for small real estate investors: you give it your criteria, drag some sliders, check some boxes, and it shows you the results. Except instead of showing you flights it shows markets. It’s fast and easy and you don’t need to pore through thousands of lines of data from government reports. The web app does all that for you instantly.

Working on the app was fun and we got a lot done over several months but it was hard to find enough time for that when we also had full-time jobs and families we wanted to see. But now that I’m consulting 30 hours a week instead working 40 hours a week, that leaves me more time every day. So I’m working on the app for real estate investors again.

I’ll make an announcement here when it’s ready to try. Subscribe to my blog so you don’t miss it. (Go here and click the Subscribe button in the right hand column.)

My Consulting and Training Business

To keep the lights on I am also doing Ruby on Rails consulting and training. I can make web apps work great on mobile phones and desktop browsers with a single code base, scale Rails apps, and a bunch more. See my About page if you’d like more info on my services, and my Contact page if you want to contact me about work.

I Like Stuff That’s Fun

I’m already having a ton of fun and I’ve barely started. It’s great to be working with Ruby on Rails full-time, controlling my destiny, and creating my future. And I’m really enjoying my first consulting gig.

Stay tuned.