Anton Zolotov

I'm a software developer, entrepreneur and CEO of GunpowderLabs, a web and mobile development consultancy. Contact me.

32 Awesome Mac OS X Apps to Make You More Productive

  1. Alfred — I mostly use this as an application-launcher and file-opener.

  2. AppZapper — Uninstalls apps completely (along with its extra files).

  3. Balsamiq — Wireframing on the desktop.

  4. Boom — Boost your Mac’s volume. Especially useful for Movies downloaded on iTunes which tend to be too quiet on the speakers.

  5. Caffeine — Toggle your Mac’s ability to go to sleep on and off. Useful during presentations.

  6. Cloak — Simple VPN to secure your connections on public wifi.

  7. Soulver — Calculator on steroids. And crack.

  8. DayOne — Beautiful journal.

  9. Divvy — Awesome window management tool. I used it to arrange windows on my large monitor.

  10. Evernote — To jot stuff down on the go.

  11. Fantastical — Menu-bar calendar for convenient access.

  12. Flint — Campfire client. We use campfire as our group chat.

  13. f.lux — Adjusts your screen’s color temperature to match the sun.

  14. GoToMeeting — For screensharing and conferences.

  15. LittleSnapper — Organize screenshots of stuff you like.

  16. MindJet — Mindmapping.

  17. OmniGraffle — Diagramming tool. There’s a huge ecosystem of stencils and templates available. Many use it for wireframing & UX.

  18. OpenOffice — Faster than Microsoft Office sometimes.

  19. SizeUp — Defines keyboard shortcuts to arrange windows and split the screen in two.

  20. MacVim — Desktop version of the popular terminal text editor.

  21. Adobe Creative Cloud — Photoshop, Illustrator, and all the other Adobe apps in one SaaS package.

  22. Fluid — This is one of my favorite apps. I creates a .app file that launches a predetermined URL, essentially creating a desktop version of the web app. I use it for Pivotal Tracker.

  23. Adium — I use this for GChat and AIM, but it supports a range of other protocols.

  24. Skype

  25. Reeder — The best RSS Reader out there.

  26. Cloud — Drag and drop file sharing.

  27. Skitch — This used to be great (I still have version 1.0.11). The newer versions have gotten horrible reviews.

  28. iAWriter — Distraction-free minimalistic editor with Markdown support.

  29. Byword — Very similar to iAWriter.

  30. PathFinder — Finder replacement. I never use the standard finder anymore.

  31. Hazel — Create rules and actions for file processing. I recently started using this to group my scanned files into folders based on year and date.

  32. Google Chrome — My web browser


How to Find and Delete Orphaned Records with Ruby on Rails

Let’s say you have an application where a User can subscribe to a Channel. With ActiveRecord associations, it would look something like this:

# app/models/subscription.rb
class Subscription < ActiveRecord::Base
  belongs_to :channel
  belongs_to :user
end

# app/models/user.rb
class User < ActiveRecord::Base
  has_many :subscriptions
  has_many :users, through: :subscriptions
end

# app/models/channel.rb
class Channel < ActiveRecord::Base
  has_many :subscriptions
  has_many :users, through: :subscriptions
end

Unfortunately, someone forgot to add dependent: :destroy to the has_many :subscriptions. When a user or channel was deleted, an orphaned subscription was left behind.

This issue was fixed by dependent: :destroy, but there was still a large number of orphaned records lingering around.

There are three ways you can use to remove the orphaned records.

Approach #1 — Bad

Subscription.find_each do |subscription|
  if subscription.channel.nil? || subscription.user.nil?
    subscription.destroy
  end
end

This executes a separate SQL query for each record, checks whether it is orphaned, and destroys it if it is.

Approach #2 — Better, but still pretty bad

Subscription.all.each do |subscription|
  if subscription.channel.nil? || subscription.user.nil?
    subscription.destroy
  end
end

This loads all records into memory, and then iterates over them performing the same check as above.

Approach #3 — Good

Subscription.where([
  "user_id NOT IN (?) OR channel_id NOT IN (?)",
  User.pluck("id"),
  Channel.pluck("id")
]).destroy_all

This approach first gets the IDs of all Users and Channels, and then executes one query to find all Subscriptions that don’t belong to either a User or a Query.

Benchmarks

Let’s take a look at how long it takes in each case.

When you run it on 2596 subscriptions, out of which 1058 are orphaned, you get:

          user       system     total    real
bad       3.020000   0.160000   3.180000 (  4.058246)
better    2.950000   0.170000   3.120000 (  3.982329)
good      0.010000   0.000000   0.010000 (  0.030346)

Even as the number of subscriptions is reduced, Subscription.all.each remains faster than Subscriptions.find_each, because it performs less SQL queries.

With 10 subscriptions, the results were

          user       system     total    real
bad       0.010000   0.000000   0.010000 (  0.022374)
beter     0.010000   0.010000   0.020000 (  0.017584)
good      0.010000   0.000000   0.010000 (  0.014330)

Conclusion

Approach #3 is a whopping 134 times faster than approach #1.

While the time difference in our scenario was only 4 seconds, it could be hours for millions of records.

This demonstrates how important refactoring is to the development process. Refactoring your code furthers your understanding of the technologies you work with. It also illustrates how important it is to minimize the SQL queries performed within your web application. If this was an action initiated by the user, the difference in the request time would be 4.02 seeconds vs. 30 ms.


Two Easy Ways to Improve Login Form Usability

First, focus on the first field of the form when it loads. This allows the user to start typing right away, go through the form with the TAB key, and sign in faster. I see a lot of forms that don’t do that, and don’t even allow you to jump to the first field with the TAB key, forcing you to perform an additional action by grabbing the mouse and clicking inside the field.

Second, don’t clear the entire form when the user does not authenticate successfully. If I typed my password incorrectly, I should not have to retype my email address as well. When the user does not authenticate completely, leave all information except for the password intact, and focus on the first field.


Delete local git branches that have been merged into the currently checked out branch

git branch --merged | grep -v "\*" | xargs -n 1 git branch -d

This is a pain to type each time, so I made it an alias in my .zshrc:

alias git-clean-merged-branches='git branch --merged | grep -v "\*" | xargs -n 1 git branch -d'

Easy, right?


Dear Programmer, I have an idea →

The perfect response to the old ‘I need a technical co-founder’ email.

  • If you want to snag a developer you’re going to have to bring some value to the table. The developer is going to be asking himself, “why do I need you to execute this idea?” I could just build it myself..
  • So, either you need to:
  1. Have some way to pay the developer.
  2. Have an impressive track record of expertise / success in the relevant industry.
  3. Have considerable technical skills.
  4. Have considerable design skills.

A Faster Facebook for iOS →

Finally, Facebook made the move to (more) native iOS.

Today we’re announcing an update to the Facebook app for iPhone and iPad that makes keeping up with friends faster and easier. Facebook 5.0 for iOS is twice as fast as the previous version when launching the app, scrolling through news feed and opening photos in feed.

I just tried it out — it is much faster. Perfect example of when native is a much better choice than HTML5 & JavaScript.


Frozen Rails Helsinki 2012

I’m attending Frozen Rails 2012, a Ruby on Rails conference in Helsinki from September 20-21st, 2012. If you’re going to be there, get in touch, I love meeting fellow developers. If you’re not going — you should. The speakers are great.


Remove Unused Images With Git →

We’re cleaning up a project that has loads of unused files and CSS rules. This nifty trick I found on Pivotal Blabs uses git to check whether your images are used anywhere in your git repository, and removes them if they’re not.

for FILE in $(git ls-files ./app/assets/images); do 
    git grep $(basename "$FILE") > /dev/null || git rm "$FILE"
done

Head over to Pivotal Blabs for the full post.


The Problem with Vim →

Vim has reduced me to a pathetic teary wreck every time I have to use a text editor that isn’t vim.

Vim is awesome. I also wrote this in Vim.


Leaked Unibody iPhone →

I’m fairly convinced this is what the next iPhone will look like. If true, this design will be noteworthy for being the first unibody iPhone, making it the thinnest, strongest, and lightest housing to date.

I definitely want one.


The difference between mocks and stubs

A stub replaces a method with code that returns a specified result.

let(:user) { User.create! }
controller.stub(:current_user).and_return(user)

A mock is a stub with an expectation that the method gets called.

User.should_receive(:find).with(1).and_return(user)

Copy a Remote File to S3 with Ruby

require 'net/http'

AWS::S3::Base.establish_connection!({
  access_key_id: 'your-access-key-id',
  secret_access_key: 'your-secret-access-key'
})

# Use the Google Logo as an example
#
url = URI("https://www.google.com/images/srpr/logo3w.png")

Net::HTTP.start(url.host) do |http|
  resp = http.get(url.path)
  AWS::S3::S3Object.store(File.basename(url.path), resp.body, 'yourbucketname', access: :public_read)
end

Heroku Releases $50 Production Database →

Finally, all my dreams have come true:

Today, we are launching into public beta two new plans: Crane and Kappa. These plans are part of our production tier, offering the same monitoring, operations, support, and data protection features as our more expensive plans.

Crane is available for $50 per month and features a 400 mb cache. Kappa is $100 per month and features a 800 mb cache.

I have a ton of apps for which the shared database is too slow, but the $200 Ronin database is too expensive. These two plans fill the gap perfectly.


Backbone.js Rocks

Here are my favorite things about Backbone.js:

It’s lightweight

Backbone.js weighs in at 16.3 KB (minified), it’s dependency Underscore.js at 12.2 KB.

It makes your apps faster

Rendering views in Rails is slow. By using Rails as an API, you can spread the rendering workload on your user’s browsers, rather than putting it all on your servers. The result? - blazing fast applications that are easy to cache. Diasporate rewrote their newsfeed with Backbone and loved it.

One of the most frequent requests from my clients is higher speed. Nobody wants to wait for a page to reload to see their changes anymore.

It doesn’t force anything on you

There are many ways in which you can use Backbone.js. You can write a completely client-side application that communicates to the back-end via a JSON API. Or you can enhance your existing pages with dynamically loaded resources, such as sidebars.

It pushes you towards a cleaner separation between data and presentation.

Your controllers become responsible for just one thing: delivering data. That makes them incredibly easy to test. Code that’s easy to test is easy to change and maintain.

It’s extensible

Even if you’re not a JavaScript wizard, Backbone.js is trivial to extend. There’s already a solid library of plugins out there.


How Not To Sort By Average Rating →

You are a web programmer. You have users. Your users rate stuff on your site. You want to put the highest-rated stuff at the top and lowest-rated at the bottom. You need some sort of “score” to sort by.

Evan Miller describes an accurate scoring algorithm and how to implement it.


Rubber Duck Problem Solving →

The critical part of rubber duck problem solving is to totally commit to asking a thorough, detailed question of this imaginary person or inanimate object. Yes, even if you end up throwing the question away because you eventually realize that you made some dumb mistake. The effort of walking an imaginary someone through your problem, step by step and in some detail, is what will often lead you to your answer. But if you aren’t willing to put the effort into fully explaining the problem and how you’ve attacked it, you can’t reap the benefits of thinking deeply about your own problem before you ask others to.


Which new iPad should I get? →

My iPad 2 version of this post has been extremely popular for the last year. It’s time for the same choice with the iPad 3 (a.k.a. the “third-generation iPad”).


Rails Scripts: Clone Heroku Database to Development

Sometimes, you need to quickly clone your production database to your local environment. Taps is an option, but at 10 minutes, it’s way too slow for some of my databases.

The faster option is to create a Postgres dump for your database, download it, and import it locally. Initially, I used this code, which lived in each project’s readme, and copied it into the terminal.

heroku pgbackups:capture --expire --remote production
curl -o latest.dump `heroku pgbackups:url --remote production`
pg_restore --verbose --clean --no-acl --no-owner -h localhost \
    -U azolotov -d project_development latest.dump
rm latest.dump

That’s better, but not good enough, because the snippet has to be modified for each project, and user who uses it.

The better solution

I wanted a short script that is run with one command. It should have sensible defaults that can be overriden and gather all information from it’s environment.

Here’s what I came up with:

#!/usr/bin/env ruby

module Heroku
  class Db < Thor
    method_option :keep,   :type => :boolean, :default => false
    method_option :remote, :type => :string,  :default => "production"
    method_option :host,   :type => :string,  :default => "localhost"
    method_option :user,   :type => :string,  :default => `whoami`
    method_option :dbname, :type => :string
    method_option :dump,   :type => :string,  :default => "latest.dump"

    desc "clone", "clone a remote heroku database to the local environment"
    def clone
      puts "Cloning production database to local environment. This might take a few minutes\n"
      puts "(1/4) capturing production database snapshot..."
      puts `heroku pgbackups:capture --expire --remote #{options[:remote]}`
      puts "(2/4) downloading snapshot..."
      puts `curl -o #{options[:dump]} \`heroku pgbackups:url --remote #{options[:remote]}\``
      puts "(3/4) restoring snapshot..."
      puts `pg_restore --verbose --clean --no-acl --no-owner -h #{options[:host]} -U #{options[:user]} -d #{options[:dbname] || dbname} #{options[:dump]}`
      unless options[:keep]
        puts "(4/4) cleaning up..."
        puts `rm #{options[:dump]}`
      else
        puts "(4/4) skipping cleaning..."
      end
    end

    no_tasks do
      def dbname
        YAML.load_file('config/database.yml')["development"]["database"]
      end
    end
  end
end

Thor

I use thor because it’s very lightweight and makes passsing options to the script a breeze. From thor’s description:

Thor is a simple and efficient tool for building self-documenting command line utilities. It removes the pain of parsing command line options, writing “USAGE:” banners, and can also be used as an alternative to the Rake build tool. The syntax is Rake-like, so it should be familiar to most Rake users.

Usage

Make sure you have thor installed

gem install thor

Put the script in your Rails root directory, and run it with

thor heroku:db:clone

Assumptions

  • The production application lives under the git remote production.
  • The database host is localhost.
  • The database user is the same as the currently logged in user.
  • Import into the development database as specified in config/database.yml.
  • We don’t need the dump file after importing it.

Configuration

If those assumptions don’t match your environment, you can override them:

To keep the dump file after importing it:

thor heroku:db:clone --keep

To change the name of the remote:

thor heroku:db:clone --remote staging

To change the name of the user:

thor heroku:db:clone --user bob

TSA: Fail →

Frankly, the professional experience I have had with TSA has frightened me. Once, when approaching screening for a flight on official FBI business, I showed my badge as I had done for decades in order to bypass screening. (You can be envious, but remember, I was one less person in line.) I was asked for my form which showed that I was armed. I was unarmed on this flight because my ultimate destination was a foreign country. I was told, “Then you have to be screened.” This logic startled me, so I asked, “If I tell you I have a high-powered weapon, you will let me bypass screening, but if I tell you I’m unarmed, then I have to be screened?” The answer? “Yes. Exactly.” Another time, I was bypassing screening (again on official FBI business) with my .40 caliber semi-automatic pistol, and a TSA officer noticed the clip of my pocket knife. “You can’t bring a knife on board,” he said. I looked at him incredulously and asked, “The semi-automatic pistol is okay, but you don’t trust me with a knife?” His response was equal parts predictable and frightening, “But knives are not allowed on the planes.”

Great and insightful account of everything that’s wrong with the TSA by a former FBI agent and counter terrorism specialist.


Fusion Ads: A Great Source for Top Notch Blogs

By controlling the quality and relevancy of the sites on our network, we preserve the integrity of the network’s target audience. Sites and services on Fusion are the best in their class – chosen based on their exceptional content and established readership.

Fusion Ads is an ad network only displays ads on a small number of hand-picked blogs of

designers, developers, publishers, creative professionals, and tastemakers in tech-related circles.

So there you go, someone has done all the hard work of curating a list of great writers for you. Go on, check them out.