Sliced Software

About

Thomas Mango writes software, has a bulldog, listens to Long Island Hardcore music and eats sandwiches.

He is currently working on Firefly, The Check-in Service for Twitter and Limited Pressing, An Online Store Community.

Gmail Archiving in Apple’s Mail.app

Update: The developer of Archive emailed me to mention that you can easily pass [Gmail]/All Mail directly into defaults write by using the -string flag.

To get running:

  1. Quit Mail.
  2. Download and install the Archive plugin.
  3. Run:
    • defaults write com.apple.mail ArchiveMailboxName -string "[Gmail]/All Mail"
  4. Open Mail and start archiving.

This approach is obviously much easier than my previous approach.

Original, outdated post:

Please note: I’m running 10.6.4 and Apple Mail 4.3.

I’ve been using Mail.app for my hosted Google App accounts for a while now and although it works okay, I’ve been really wanting an easy way to Archive email. I want to hit a keyboard shortcut or a button and have my emails moved to Gmail’s All Mail folder.

After searching for a while, I finally came across a great plugin, Archive, a button for Apple Mail, that adds a menu item, keyboard shortcut and toolbar button to archive the selected messages. By default it will move the messages to a folder called Archive. With a regular IMAP account this would be fine, but when you’re using Gmail or Google App accounts, you want the messages moved to [Gmail]/All Mail.

The Archive plugin has a defaults write com.apple.mail ArchiveMailboxName preference that you can override, but there are all sorts of problems when trying to write “[Gmail]/All Mail” to it.

To get around this, I put together a quick shell script that writes “[Gmail]/All Mail” to a temporary file and passes that file into echo which is passed through xargs into defaults write. It shouldn’t be this hard, but it is.

How to get running:

  1. Quit Mail.
  2. Download and install the Archive plugin.
  3. Download my script http://cl.ly/1da2d54afbbcba3abed3.
  4. Make sure the configure_archive script is executable:
    • chmod +x configure_archive.sh
  5. Run it:
    • ./configure_archive.sh
  6. Open Mail and start archiving.

Here’s the shell script:

#!/bin/bash

echo "[Gmail]/All Mail" > /tmp/archive_mail_plugin_config

archive_mail_plugin_config=`cat /tmp/archive_mail_plugin_config`

echo \'$archive_mail_plugin_config\' | xargs -0 defaults write com.apple.mail ArchiveMailboxName

rm /tmp/archive_mail_plugin_config

Testing for Booleans

I just released a new plugin called to_b. Just like my other public projects on github, this plugin is extremely simple and is meant to help with something I’ve found very annoying: the lack of a to_b method.

Installing it in your Rails project will add a to_b method to NilClass, TrueClass, FalseClass, Fixnum and String. I’ve found this most useful when providing optional boolean parameters in API methods. I explain this situation a bit more in the README, which I’ll embed below.

README

A simple plugin that adds a .to_b method to various classes to aide in testing for boolean values against variously typed objects.

Why nil, false and true

If you look at the source, you’ll note that nil.to_b returns nil, rather than false. Additionally, a string like ‘notaboolean’.to_b also returns nil. This was done on purpose. I always ensure all the boolean columns in my database are created with :null => false to avoid any issues relating to null values in boolean fields. However, to_b returning nil in certain circumstances allows me the flexibility when using this in conjunction with an API to accept nil, false and true values for specific parameters.

An example of why I want the ability to test for nil, false and true is that if a boolean parameter is left out I want my SQL to search WHERE true OR false, if the parameter is set to true I want it to search WHERE true and if the parameter is false, false. It is simply easier to have a scope like the following:

named_scope :with_tip, lambda {|value| value.to_b.nil? ? {} : {:conditions => {:tip => value.to_b}}}

Rather than explicitly searching WHERE true OR false, I simply leave out the condition. When the value is true or false, I include the condition.

Examples

>> true.to_b
=> true

>> false.to_b
=> false

>> nil.to_b
=> nil

>> 'true'.to_b
=> true

>> 'TRUE '.to_b
=> true

>> 'false'.to_b
=> false

>> 'F'.to_b
=> false

>> 'random'.to_b
=> nil

>> 1.to_b
=> true

>> 0.to_b
=> false

>> 5.to_b
=> nil

Geico’s Payment Form: Indentation Matters

While paying my car insurance on Geico’s website this morning, I was faced with the same payment form that bothers me every month. Actually, it’s only one section of the form: the saved account section:

Every time I come to this form, I instinctively check the box above my saved bank account information. However, if you read the label attached the checkbox you’ll see that the checkbox actually lets you use a different account.

The fact that the checkbox is above your saved account details and your saved account details are indented, leads you to believe that the checkbox is tied to that account.

I mentioned this on Twitter and, within an hour, @geico_service replied and said they’d tell the website team. I have no idea if they’ll fix it or not, but I figured that was my chance. I edited the html of the form quickly and sent them a mockup of what I always expect to see in that area:

It’s a really minor change, but I think it helps a lot. The original form had the intention of allowing you to continue without doing anything. Your account information is saved so if you want to use it, don’t click anything. I think my mockup here drives that point home more.

You have two options, the default is to use your saved account (notice the radio button is above the indented account details) and the second option, that isn’t selected by default, is below the saved account details and allows you to use a different account.

Little things like this can go a long way when designing a form in your web application.

The more you think about how to design and implement something, the less your users should have to. Otherwise, you’re wasting time.

Safari 5 Extension: Google.com Cleanup

Update: After using this extension for a while, I think the better way to explain it is to just say that it will always show you the standard google logo (rather than the vanity logos) and it will always hide the Google Chrome advertisement that shows up in the top righthand corner.

Original: I use Google’s “Keyboard Shortcuts” search experiment, which lets you navigate search results using just your keyboard. You can join the experiment by visiting Google Experimental Search. I rarely use my mouse, so this is a fantastic timesaver.

One annoying side effect since Google changed their logo is that the special Google Experimental logo doesn’t fit properly on Google’s front page - it’s distorted. Another annoying thing lately (that probably has nothing to do with the search experiment) is that the Google Chrome advertisement shown in the top right hand corner never goes away for good. Every time you refresh google.com, it comes back.

I decided to fix these two minor annoyances using Safari 5’s new extension system. It’s only a single line of javascript and a single CSS rule, but it works great and makes opening a new tab much more enjoyable for me (yes, I use google.com as my new window and new tab page).

If you’d like, you can download the extension.

And here are before and after screenshots to show what the extension actually does. Enjoy.

Update (07/15/2010): Fixed a bug that caused the replacement logo to be stretched to the incorrect size when google.com is showing a vanity logo (which they seem to do every other day). The replacement logo will now always show at the correct size.

If the three month old code you wrote doesn’t depress you, you’re doing it wrong.

Thoughts on Draft

Earlier this week, 37signals released their first iPad application. Their app, called Draft, is billed as a “straightforward sketch app for iPad” and is being sold for $10.

Reading on, I can see that:

“It only comes in black. You can draw in white or red.”

And:

“It automatically saves whatever you draw.”

At this point, I was baffled. I’m roughly three full screens down and three screenshots deep and it looks a lot like Adobe Ideas (which is free) and a host of other apps that are already available.

But further down the page, there was more:

“You can share sketches via email or Campfire.”

And there we go. There had to be a reason they were charging $10 for this app, we just had to find it.

Now, the problem I have is with the way they’re marketing it. It’s a “sketch app” but oh it also let’s you “share via Campfire”. And judging from the hundreds of comments on their announcement post, there were a lot of people calling them crazy for charging so much for an app that “doesn’t do anything more than Adobe Ideas”. Yet, it does do more and honestly, what are the chances that the minds behind Basecamp, Rework and SVN, aren’t damn sure of what they’re doing?

But I’m getting ahead of myself. I should explain why I’m even writing about this. Over the past few years, I’ve started thinking more about building products than building applications. Not just “can this be done” or “what can be added”, but what makes this a product and how do you sell it. And by sell it, I mean “sell it” for either money or just getting people to buy into the idea. A lot of things have contributed to my thinking more about whole products over the years, and reading what 37signals has had to say is certainly one of those things.

Back to Draft

Let’s first make something clear: the people behind 37signals are incredibly successful and know what they’re doing. They know how to give you what you need and they know how to make you want to take out your credit card. They do a lot of things well, and making money is seriously high on that list.

With that aside, I think they could have launched (and can market) Draft in a much more effective way: by changing the name to “Draft for Campfire”. The only people who are going to buy this app are people who use Campfire. There just simply isn’t any reason to buy this over cheaper sketch apps, unless you use Campfire. And 37signals is clearly directing this at paying, Campfire users. If you had the choice, why would you even want people who won’t spend money on apps, when you have existing customers that probably pay you upwards of $150/year? Existing Campfire users: that’s who it’s useful to and that’s who, I can only assume, they want using it.

So, Instead of taking the criticism, which 37signals does a great job at, by changing the name to “Draft for Campfire”, I think that most people bashing them on that blog post would realize right away the point of the app. It’s no longer a sketch app that also can share via Campfire, it’s a sketch app for sharing via Campfire.

But it’s not just about negative feedback, it’s also about their marketing page. Their current marketing page does an awful job at immediately conveying to me the reason as to why I should buy this app for ten dollars. The fact that it can share via Campfire (mentioned very low on the page), feels a lot different than if the product was billed as for sharing via Campfire right off the bat - even though it’s the exact same app.

It’s a small change, but I’d bet it makes a big difference to a lot of people landing on that page. Then again, I haven’t written two books or launched a host of insanely successful applications, so what the hell do I know?

Transferring a Private Repository on Github

I recently had to transfer a private git repository that was being hosted on Github. It turned out to be embarrassingly easy to transfer the repository while keeping the history intact, but I figured I’d document it in case others were wondering.

What Didn’t Really Work

The first thing I tried was a fork. I added the receiver’s Github account as a collaborator to the private repository. Then, I forked the project on the receiver’s Github account. Afterwards, I removed the receiver as a collaborator from the original project and removed the original account as a collaborator on the newly forked project (which is automatically added by Github).

More or less, this did the job. The newly forked project was it’s own repository and neither repository owner could see the other repository. The only issue was that the new repository still said “forked from {original account}”. The receiver wasn’t happy about this and to be honest, it was a little crude being that they purchased the codebase.

The Correct Way

The correct way to do this is basically just as easy.

  • Create a new repository on Github under the receiver’s account.
  • Add someone with access to the original repository as a collaborator to the newly created repository owned by the receiver.
  • Duplicate your project directory locally (as someone who has access to both repositories).
    • cp ./projects/{project_name} ./projects/{project_name}_backup
  • Change into the project and remove the existing remote origin that points at the original repository.
    • cd projects/{project_name}
    • git remote rm origin
  • Add the new remote origin (see Github’s excellent first run screen) that points to the newly created repository owned by the receiver.
    • git remote add origin git@github.com:{receiver}/{repository_name}.git
  • Push to the new repository.
    • git push origin master
  • Delete your local copy pointing to the new repository.
    • cd ..
    • rm -rf ./projects/{project_name}
    • mv ./projects/{prject_name}_backup ./projects/{project_name}

This isn’t rocket science, but I figured it would help someone.

Resque in Production

Over at Firefly (more about Firefly soon), we’re using a wonderful background queue called Resque. Resque was built by Chris Wanstrath of Github fame and runs on top of Redis. It’s fantastic and I absolutely love it. If you haven’t had a chance to try it, go check it out.

When setting up Resque in production, I ran into a few issues that weren’t extremely obvious to me. I ended up working through them in the end and thought I’d write something up to help others out in the future.

Monitoring with God

Resque comes bundled with a config file for god, but I had an issue with the way it would start up a worker. My example is only using a single worker, but you can combine my method with the bundled one. Here’s how I did it:

# Redis
%w{6379}.each do |port|
  God.watch do |w|
    w.name = "redis"
    w.interval = 30.seconds
    w.start = "/etc/init.d/redis start"
    w.stop = "/etc/init.d/redis stop"
    w.restart = "/etc/init.d/redis restart"
    w.start_grace = 10.seconds
    w.restart_grace = 10.seconds

    w.start_if do |start|
      start.condition(:process_running) do |c|
          c.interval = 5.seconds
          c.running = false
      end
    end
  end
end

# Resque
God.watch do |w|
  w.name = "resque-1.8.0"
  w.interval = 30.seconds
  w.start = "cd /var/www/apps/firefly/current && rake environment RAILS_ENV=production resque:work QUEUE=high,medium,low"
  w.start_grace = 10.seconds
  
  # retart if memory gets too high
  w.transition(:up, :restart) do |on|
    on.condition(:memory_usage) do |c|
      c.above = 350.megabytes
      c.times = 2
    end
  end
  
  # determine the state on startup
  w.transition(:init, { true => :up, false => :start }) do |on|
    on.condition(:process_running) do |c|
      c.running = true
    end
  end
  
  # determine when process has finished starting
  w.transition([:start, :restart], :up) do |on|
    on.condition(:process_running) do |c|
      c.running = true
      c.interval = 5.seconds
    end
    
    # failsafe
    on.condition(:tries) do |c|
      c.times = 5
      c.transition = :start
      c.interval = 5.seconds
    end
  end
  
  # start if process is not running
  w.transition(:up, :start) do |on|
    on.condition(:process_running) do |c|
      c.running = false
    end
  end
end

Restarting Workers on Deploy

The other issue I ran into was that I needed my workers to restart each time I deployed. Because Resque loads your application’s environment, a new deploy with changed models, would mean that your existing Resque workers are running outdated code. The way I handled this was to QUIT my workers and let god start them back up (using the updated codebase).

...

# Restart Passenger
deploy.task :restart, :roles => :app do
  ...
  
  # Restart the resque workers
  run "cd #{current_path} && rake queue:restart_workers RAILS_ENV=production"
end
view raw deploy.rb This Gist brought to you by GitHub.
namespace :queue do
  task :restart_workers => :environment do
    pids = Array.new
    
    Resque.workers.each do |worker|
      pids.concat(worker.worker_pids)
    end
    
    system("kill -QUIT #{pids.join(' ')} && rm /var/run/god/resque-1.8.0.pid")
  end
end
view raw resque.rake This Gist brought to you by GitHub.

Conclusion

At first, I wasn’t really happy about quitting and restarting my workers this way, but after reviewing how Resque handled shutting down workers, it seemed like an okay approach. If you have any tips on how the environment can be reloaded without waiting for god to start new workers up, I’d like to hear them, so shoot me an email.

Small Victories

I often find myself at the start of very large projects that are scheduled to ship in way less time than is seemingly necessary to complete them. However, I don’t think this is such a bad thing.

The fastest way to get something out the door is to set an arbitrary ship date. I could iterate over the same algorithm or interface for weeks, perfecting it, if I had the time. But, if I did that, I’d never actually ship anything. And when it comes down to it, if you don’t ship software, you may as well not write software.

At the start of a big project, I lay out the major things that need to be done. I write them all down in a list on a big whiteboard next to my desk. I set a date that isn’t very far away, a date I’d love to get this stuff out the door by, not necessarily a date that would give me enough time to feel comfortable. That’s the key, you shouldn’t have so much time that you feel comfortable that everything will be perfect. I’m not sure where I read it, but someone once wrote, if you aren’t embarrassed even a little when you ship something, you didn’t ship it soon enough.

Once I get started on the project, I cross things off the list on my whiteboard, I don’t erase them. I make sure that the list is somewhat general at first. I try my best not to stay on one area of the project for too long. If I notice I’m spending too much time on one thing, it usually means I’m obsessing over some small detail. I step back, figure out what I need to do to round out the area and make it good enough to ship. Then, I take all of the small details that the perfectionist inside me would really like to finish, and I add those to a second list on my whiteboard.

I keep iterating like this, moving from large area to large area and then circling back and crossing off smaller details where time permits. The best part of this is that as you move from large area to large area and cross things off, you start to get on a roll. Looking up at a huge whiteboard with tons of things crossed off gives you the feeling of accomplishment. I’d rather cross off ten small to-do items in a day than one large to-do item in two days. And let me be clear, it isn’t starting with a large to-do list. Large to-do lists never get done. You start with a small to-do list and as you cross off things because they’re good enough, you add much smaller to-do items to another list. Don’t keep adding things unless you’re also crossing things off.

But, it isn’t just the feeling of accomplishment. Because you’re worrying about the details later, the entire project progresses forward faster. If you need to ship something large in two weeks, you can still ship it if the majority of things across the board are done without worrying about completing every little tiny thing in each section before moving on to the next section.

I usually end up being able to complete almost everything in my arbitrary timeframe, but by doing things this way, it lets me easily evaluate the necessity of specific items. I believe that constantly adjusting scope to what’s important now rather than blindly implementing some predetermined “feature list” is the only way to ship software on time. Who knows, by the time you ship, you may circle back to some little fringe feature that you realize isn’t even necessary anymore.

Set a date and ship the damn thing.

Looking for really old posts? Until they are here at tumblr, see here!