by Dan DeMeyere - @dandemeyere
One of the biggest advantages to using Ruby on Rails as your web framework is the open source community. They unselfishly release new gems every day. They build the best tutorials for free and they commit to the latest Rails builds on a daily basis. The only variable left in the equation when you're building a Rails app is knowing what tools to use when approaching a project implementation. Having a solid toolbox at your disposal is essential to furthering your professional development as it allows you to take on more challenging projects that are outside your comfort zone.
When I first started developing with Rails, I was blown away by my CTO's ability to nonchalantly take on challenging projects. The project or feature would seem outlandish and at times borderline impossible, but he would say something like "we'll figure something out" and somehow he always did. It seemed like magic. After watching closely for many months, I came to realize he had three things: a positive outlook, a solid toolbox, and a creative imagination. The combination of the three were a potent arsenal for tackling epic projects. He wouldn't think about why it couldn't be done - he would start in the ideal world that everything's possible and begin brainstorming from there.
Having a good outlook and creative imagination is not something you can attain from reading a blog post, but you can always add more tools to that handy toolbox. Here are four new additions to my toolbox; hopefully one of these will help you one day when you come across a new project.
Storing your ActiveRecord Objects in Redis
Speed is important. Rails contains a fair amount of overhead and it's considered one of the harder frameworks to scale. It isn't an issue when you're website is small, but as you grow you'll discover some of the earlier code that was written in your app won't hold up as the user base grows. This results in feature re-writes and becoming more clever with your implementation. One of the first tools to reach for when attempting to speed something up (outside of profiling your DB queries) is cacheing. We use memcached at thredUP, but the problem with memcache is that the data isn't persistent. If your memcache server goes down, you can lose all the cached data within it. This makes memcache only feasible for information that can afford to be lost. What about data that needs to be written to the DB? You can't reliably do it with memcache, but you can with Redis.
The tool I linked to above is a gem that the fine folks of Gowalla, recently acquired by Facebook, wrote to accommodate quick writes and reads of an ActiveRecord object. Their example is 'liking' something. You have to be able to like something quickly and pull back information on that like such as how many others have liked it and who they are. Personally I've been wanting to re-write thredUP's in-house notification system for a while as it hits the database on every logged-in page load and this is going to be the first tool I reach for when that time comes.
Lazy Evaluation and Method Chaining
Most people know about method chaining in Ruby, especially within the context of ActiveRecord methods. Most people also know that an ActiveRecord call does not hit the database while it's still an ActiveRecord::Relation object, which is an example of lazy evaluation. The real tool comes from using both of these together.
The best example I can give is compound filtering. If you go to an e-commerce website and select 'Sort By: Lowest Price' and 'Gender -> Men', those are options that will compound to filter your results. One way of implementing this is having a nasty 'if params[:sort] = "Lowest Price" && params[:gender] = "Gender"' block for every possible filtering scenario. That is obviously not ideal. But if you were to add some named_scopes that build conditions for each individual filter and method chain all the compounding filters onto a ActiveRecord::Relation object that executes its call to the DB at the end, then that would be a clean way of doing it.
ActiveRecord Key Value Stores
Key value stores are awesome. They're super simple and super fast. To get geeky for a second, searching with key value stores in big O notation have a time of O(1) (that's the fastest). I like to hack together Hash look-up objects in Ruby all the time to speed up checking whether a ActiveRecord ID is in a collection. The alternative is using an array (assuming it can't be looked up in the DB) and even if the array is sorted and the array look-up call is using a simple B-tree algorithm, the notation is still O(log n). You just can't beat key value stores for look-ups.
The link I referenced is leveraging the method_missing method of a class as a way to arbitrarily set key values. I would never use something like this on a heavily used model such as User as using method_missing like that is dangerous, but it does make sense in context of ApplicationSettings. Either way, it's a clever implementation for dynamically setting class attributes and it opens up your imagination for ways in which it can be used.
Have a tool you would like to share? I'd love to hear about it below in the comments.