Rails + Backbone.js + Backbone-relational

Playing around with Rails and Backbone.js for the last few weeks has been nothing but fun. Both libraries have features and functionality that almost seem like magic. At the same time, they have their limitations as well. For instance, I've really felt the need for a way to express relations within Backbone. This would enable a one-to-one mapping between Rails and Backbone models and would, in general, make things a lot simpler. The Backbone docs quite clearly mention that they will not be adding direct support for nested models/relations, and one has to look elsewhere for it. Searching around will lead you to the Backbone-relational library, which is a Github project and well maintained. The documentation, however, is a bit lacking and there are no demo/tutorials either (the lack of a tutorial is an open bug against the project) And thus, I decided to build a demo app using Rails, Backbone.js and Backbone-relational.

To quickly get started, I used the help of scaffolding and the rails-backbone gem. The rails-backbone gem provides rails like scaffolding to create a basic structure for your backbone app. Although not necessary (and probably overkill for this demo) it is an easy way to get things running quickly, and you also don't need to worry about structuring your code later. (warning: this gem generates Coffeescript, which may or may not be a good thing) For this demo, I have two models, Posts and Comments. Both have a field to hold some text content. The rails associations are defined as follows - a Post "has_many" Comments and a Comment "belongs_to" a Post. By following the instructions on the rails-backbone documentation, you can generate the code for both models, for both rails as well as backbone. (Scaffolding is not something I'd recommend in general, but is quite handy in this case) At this point of time, you could verify things are working fine by hitting localhost:3000/posts .

To use Backbone-relational, first get the JS file from the Github project, plonk it somewhere in the include path (vendor/assets/javascripts might be a good option) and edit your application.js file so that it gets picked up. Next, we edit the models as shown below. The models extend Backbone.RelationalModel instead of Backbone.model, and you also set the relations option within the model. In this case, the Post model has a "HasMany" relation with Comments, and Comments automatically has a relation of type "HasOne" set for Posts. Since a Post can have many comments related to it, they are stored in a CommentsCollection, which is specified by the CollectionType option.

The Backbone Post model and collection are defined as follows

class RailsBackboneRelational.Models.Post extends Backbone.RelationalModel
  paramRoot: 'post'
  defaults:
    title: null
  relations: [
    type: Backbone.HasMany
    key: 'comments'
    relatedModel: 'RailsBackboneRelational.Models.Comment'
    collectionType: 'RailsBackboneRelational.Collections.CommentsCollection'
    includeInJSON: false
    reverseRelation:
      key: 'post_id',
      includeInJSON: 'id'
  ]
class RailsBackboneRelational.Collections.PostsCollection extends Backbone.Collection
  model: RailsBackboneRelational.Models.Post
  url: '/posts'
The Comment model is defined as follows
class RailsBackboneRelational.Models.Comment extends Backbone.RelationalModel
  paramRoot: 'comment'
  defaults:
    content: null
class RailsBackboneRelational.Collections.CommentsCollection extends Backbone.Collection
  model: RailsBackboneRelational.Models.Comment
  url: '/comments'

You can now refer to the Comments in a Post using regular Backbone methods, for eg. post.get('comments') will return a CommentsCollection object. This collection is nothing but the set of Comments "related" to that particular post. Similarly, you could do the reverse, and access the parent post from a Comment using something like comment.get('post'). In this case, the reverse relation key is post_id, and you'd have to do comment.get('post_id') instead. This is slightly misleading, as it returns a Post object, and not just the post_id. However, if you call a toJSON() on the comment model, it will include only the id field of the post object (this is specified by the includeInJSON option) Rails only needs a post_id field to create and associate a new comment with an existing post, and so we can ignore the rest of the attributes. In short, make sure the key and includeInJSON options in reverseRelation correspond to what Rails is expecting. Similarly, calling a toJSON() on the Post model will return only the parent Post object, and all nested comments will be ignored because of the 'includeInJSON: false' option. Also, initializing the Posts collection from the Rails view now becomes as easy as changing @posts.to_json.html_safe to @posts.to_json({:include => :comments}).html_safe , and BackboneRelational automatically takes care of the rest by initializing the nested Comment models as well (this is because the createModels option is set to true by default)

The rails-backbone gem also includes a couple of other JS files that are of note, backbone_datalink.js and backbone_rails_sync.js. The first binds change event handlers to all generated views that have forms/input fields, while the second just overrides the default Backbone.Sync function to make it work seamlessly with Rails.

You can see this demo live at http://rails-backbone-relational.herokuapp.com/posts and the code at https://github.com/rohitnair/rails-backbone-relational You can create, edit and delete posts. You can also create and delete comments related to each post. A majority of my modifications to the scaffold generated code are on the view and template files. The post model also uses the above mentioned backbone_datalink lib to grab updated values from the form, while the comment model simply grabs the value in the input box using a jQuery .val() call.

Resources/Docs:
Backbone.js documentation
Example Backbone.js Todo application with annotated source
rails-backbone gem (github)
Backbone-relational (github)

Mining Bitcoins for Fun (and very little profitability)

So what do you do with $60 worth of Amazon EC2 credits that expire in a few days? Why yes, you think of ways to waste them! (and give the evil, big corporation the least amount of satisfaction). I could have donated computing resources to Science or even used them for my own research project. But none of that comes close to making a few Bitcoins, in the hope that one day the world's economy will crumble and you'll be a billionaire thanks to this virtual currency.

I decided to go for the meanest and most expensive EC2 instance type (the cg1.4xlarge Cluster GPU instance that costs $2.10 per hour) Mining bitcoins is compute intensive, and you almost definitely need some GPU power, although it appears that Nvidia GPUs are not best for this particular kind of computation. Next, I created an account on deepbit and followed the instructions mentioned here to install all the necessary software/libraries. As of now, you might need to do a few things differently. The following additional steps were enough to get things working for me.

# Install source for current package before trying to run the nVidia installers
yum -y install kernel-devel-$(uname -r)
# Download and run latest installer, and point installer to source directory which was installed above
bash devdriver_3.2_linux_64_260.19.26.run --update --kernel-source-path=/usr/src/kernels/2.6.35.14-97.44.amzn1.x86_64
# use updated syntax for poclbm.py
screen -d -m python poclbm.py username:password@deepbit.net:8332 -v -w 256 --device 0

And finally, some numbers. I got 28 hours worth of EC2 compute time and an average of around 200 MH/s using the instance. What does that translate to? According to this profitability calculator, 200MH/s can earn you around 0.1462 BTC. In 24 hours. In other words, 60$ of EC2 compute power got me less than 0.2 BTC (which is barely worth a glorious $1) Oh well, it was a fun experiment, and IMHO, totally worth it! :D

Now served by nginx!

A few months back, my blog web server(apache) randomly stopped responding to HTTP requests.(My EC2 instance once stopped responding to pings as well, but that was an entirely different issue) The error log said that apache had hit MaxClients. This was surprising considering that my server/blog gets virtually zero traffic. A quick restart and things seemed to be back to normal. But the issue kept repeating, and I had to come up with a long term fix. I could have spent some time trying to debug the issue, and tinker with apache's default settings (which might not be the best for an EC2 Micro Instance). But I decided to go the easier route and just switched to nginx. I had absolutely no experience of working with nginx, but the term "lightweight" had always been associated with it in my mind, and it seemed to be an ideal choice for the 613MB of memory that an EC2 Micro Instance provides. Read up a bit on setting it up, tried a few things with the configuration and things were up and running in a few minutes. The blog has been fairly stable since and I've hardly noticed any downtime. The memory usage, as expected, is pretty low, and it's noticeably faster as well!

Would you use airbnb?

Airbnb is certainly getting a lot of attention these days. And also a billion dollar valuation. For those who don't know, it's a service which allows you to "book" rooms/houses/couches as if they were hotel rooms. The difference being that you pay a real person, not a business. And sometimes, this person is living in that same apartment and acts as a host. I personally used it because hotels in San Francisco are mostly too expensive, and living with a host would have given me access to valuable local information.

As someone who's used airbnb, I've tried to explain the concept to quite a few people. Most people were surprised at the idea that someone could rent out their room to a complete stranger. Which brings us to the topic of reviews on airbnb. Now that I look back, I realize that I'd seen only positive reviews (I must mention that hosts can review their guests too. And yes, I got reviewed as well) Doesn't this boil down to the fact that you're reviewing real people and their homes and not evil, private businesses? Aren't most people nice? At least when you're paying them? For example, I saw this in one of the reviews on airbnb
"He had two tiny problems we had to work with, the shower head was awful and one of the windows wouldn't fully close"
"Look past the window and shower and everything is amazing and perfect."

Would people have "looked past" such things had it been a hotel? You can in fact see hundreds of negative reviews of hotels on sites like Tripadvisor for much less. The Wi-Fi in my room was broken for a couple of days, but I still ended up giving a mostly positive review. Had it been a hotel, I probably would have whined and cursed them all day. And written bad things about them on Twitter/Yelp/Tripadvisor/every goddamn site I could find.

People are just too nice to say bad things about a person and his home, especially in public. For this reason, I feel airbnb's review system is flawed. Or rather, the idea is right, but people are just not straightforward enough to use the system right. At the same time, you need to be considerably open-minded to use a service like this, both as a host and a guest. Maybe that translates to more flexibility and lower expectations, and in turn more positive reviews.

Something better than nothing?

It's been more than eight month since I posted something here. Eight bloody months. This in spite of several jobless periods in those eight months including one week of doing absolutely nothing at home in Ernakulam. Clearly, blogging is not my cup of tea. Or maybe it's just twitter getting all those lines popping up in my head. Add to that my extreme laziness and this state of the blog is quite expected. Well, i've decided not to be too fancy or creative and at least post things that come easily to me, namely reviews and football. I had started putting my restaurant reviews on Burrp! (one great site) as i'm pretty sure they would get more readers there than on my blog :) I might duplicate some of it, but I guess having some updates here is better than having none at all. Also hoping to come up with a post for Real Madrid's almost unreal transfer season. The Galacticos are back baby! :)

PS: I contribute on Burrp! with the username "rohitnair"