Intelligently Deduplicating Records in Rails

I recently needed to write a deduplicate method in a Rails app I built. In the application, each artist has_one song. However, over the course of several months, several songs had been added to the database with the same artist_id as an existing song.

Based on this helpful post, my deduplicate method looked like this:

Deduplicating Records with the Same Parent ID
class Song
  def self.deduplicate
    grouped = all.group_by { |song| song.artist_id }
    grouped.values.each do |artist_songs|
      first_one = artist_songs.shift
      artist_songs.each { |dup| dup.destroy }

This method groups every song by the song’s artist. For groupings with more than one song (i.e. songs that have the same artist_id), it keeps the first song and deletes all the rest.

This works great, but it naively decides which duplicate record to destroy and which to keep.

To make the deduplicating method “smarter” we can use sort and sort_by to influence which duplicate will be kept. For example, if we wanted to keep the duplicate song with the highest play count, we could add this line before the shift method call:

artist_songs.sort! {|a,b| b.play_count <=> a.play_count }

This would ensure that the song “kept” using the shift method is the song with the highest play count.

It’s also possible to sort records by boolean values using sort_by. This was useful for my method, because in cases where an artist had two songs, I preferred to keep the song that had been reviewed by a trusted editor vs. one that had not.

The sort method doesn’t work with booleans, so we instead use sort_by and replace the booleans with integers to achieve the sort. I used the following line of code before the shift call:

artist_songs.sort_by! { |song| song.reviewed ? 0 : 1 }

Now, I have a concise, reusable method I can use to intelligently de-duplicate my songs.

Charles Worthington (@cew821) is a freelance product designer living in Washington, DC. He would love to hear from you!

Free Design Idea: Fixing Conference Call Frustration With Software

Conference calls are an unfortunate fact of life. No one loves their conference call system, but even in the age of Skype,, Google+ Hangouts, and countless other ways to collaborate, conference lines remain the standard way for remote teams to communicate. And for good reason: access is universal, and you can participate while driving 65 MPH down the interstate.

One of the most fustrating parts of conference call systems is getting dialed in. If you are anything like me, your dial in process probably works like this:

Software to the Rescue

The dialer user experience should be adapted to better handle the conference call scenario. Here is one example of how this could work:

In many cases, it should be possible for the phone to detect when a user is trying to enter a conference call. Indicators would include initiating a phone call from inside a meeting reminder containing the words “conference call”, “bridge”, “passcode”, “meeting ID”, and the like. Meetings with multiple attendees and a phone number in the location field would be another good sign that the user wants to join a conference call.

In these cases, the dialer should open with the keypad open and the OS’s best guess at the conference passcode listed above the keypad.

A feature like this would prevent a lot of frustration, and save me literally SECONDS each week. If any mobile OS product people are reading this, please discuss this implementing this idea on your next product design call!

Charles Worthington (@cew821) is a freelance product designer living in Washington, DC. He would love to hear from you!

Rebuilding Gray Duck Labs With Octopress

When I chose to leave my awesome strategy consulting job to pursue a freelancing career in product design and development, creating a brand to represent myself was one of the first projects I worked on. In a way, I was my own first “client.”

Gray Duck Labs was the outcome of this effort. I created a portfolio of branded documents, including a letterhead, a slide and wireframing template, business cards, and of course, a web site.

Since this effort coincided with a personal push to refresh my web development skills, I took the opportunity to design and code my own site, including writing my own blogging engine in Ruby on Rails. Initially I was happy with the result (I kept a copy live on Heroku if you’re interested). As time passed, however, I became frustrated with the limitations of the blog engine I had created. For example, my engine lacked:

  • Social sharing buttons
  • An article index
  • Article tagging
  • Named page routes
  • Comments

None of these features are revolutionary. In fact, these are problems that have been solved many times over. As I became busy with actual client work, I found less appeal in the idea of writing these features from scratch “for fun.”

Enter Octopress. Octopress is a Ruby framework that extends Jekyll to allow you to generate a static site that includes many features that would normally require a dynamic web application.

Read on →
Copyright © 2013 Gray Duck Labs LLC. | Powered by Octopress | View source on GitHub