Yesterday I read a post over at the EngineYard blog about a use case for Redis (in the name of being a polyglot, trying new things, etc.), and I just had to scratch my head. I love Redis — it rocks my world — but that example was too much for me. If you just want to store a set of ids somewhere to avoid normalization headaches, introducing Redis is overkill... just do it in MySQL!
The example was the classic one of non-recipirocal friendships (like twitter) where person A can follow (or friend) person B but person B doesn't have to follow (or friend) person A. While there's a tried-and-true schema that can easily handle this in your plain-vanilla SQL store, sometimes that causes a bit of implementation friction when you just want a quick list of friends. So I give you the "new hotness" sets in the "old and busted" MySQL database:
First, the schema:
create_table "users", :force => true do |t| t.string "name" t.text "friend_list" t.datetime "created_at" t.datetime "updated_at" end
And then some data:
And finally the model:
Oh noes! An interpolated string in the SQL! Yes, I know, our knee-jerk reaction is that this is a really bad thing, but thanks to attr_protected and coercing the id to an integer in the follow and unfollow methods, it's safe, really. :) If it gives you too much anxiety, though, you can use a placeholder and just pass in friend_list.split(',') as the data.
Will this perform as well as Redis when it comes to updating sets of ids? Probably not. Will it do for the vast majority of Rails apps out there? Yes. And if you're lucky enough to have an app that has this code as a major bottleneck, then you can go to town with Redis, and with only minor changes to this model. Until then, you can be happy living in the familiarity of MySQL-land, and keep your deployment environment that much simpler.