This is absurdly mixing up dates, but I thought I should put up my slides for my talk at Delhi here as well. It’s about caching, and how a simple solution can enable page caching (and its speeds) to be used in a lot of situations. You’ll need the audio of my talk as well. The title is inspired from Do Androids Dream of Electric Sheep?, a brilliant novella by Philip K. Dick. 🙂
Tag: ruby+rails
About Ruby and Rails
Barcamp Hyderabad Three: Eclectic Java
Just a quick note (will expand later, hopefully) to let you know that Barcamp Hyderabad 3 happened and I was there 🙂 ‘Twas a fun event, and a good two days away from work.
A request to unconference organizers tho: no wifi sucks big time.
I’ve stopped working on JRuby, but I’m keeping an active RSS eye on the project. It seems very promising. Meanwhile, my slides are up on SlideShare.
Java + Ruby
I’m going to write a bit about Ruby in Java land. Much of this post stems from the Sun stall at FOSS.in: to put it mildly, it was perhaps the most enthusiastic stall I’ve seen at a conference ever. The energy of the guys there was incredible and their enthusiasm to show things off (and Sun does have a lot of nice things to show off: dtrace, ZFS, glassfish) really made me give a second glance to the entire Java + Ruby thing: JRuby, or a Ruby implementation in Java, and Rails deployment via the Java Enterprise stack. I’ve been playing around with it for a day, and I’ve got just one thing to say. It’s cool 🙂
A bit of a background: I’m not a Java guy. Repeat, not a Java guy. So when people say that the Java toolset is amazing, I’ve always not understood what they meant. Who needs toolsets, widgets, a GUI, an administrative console; when you’ve got SSH & shell scripting? The last four months developing SlideShare however, have been a bit of a revelation: managing servers is a tough job. Our current stack includes a lighttpd->pound->mongrel chain, and monit to watch these processes and start them off if something goes wrong. Lots of glue code, and solutions that seem hacks now (a separate uploader mongrel, anyone?). Anyways, the role of a sysadmin sucks: big time, and the toolsets to manage a traditional *nix environment requires too much of manual work. [Stuff such as Puppet might negate this, but I digress…]. So it was kinda really nice to switch on Glassfish, drop a .war into an autodeploy directory and watch the application come alive. And have an actual GUI console to manage all this stuff, read up on the logs, configure routes & services, etc.
I’ve not done much: just installed Glassfish, played around with asadmin start-domain domain1
and the console, and then installing Jruby and the easy Java + Ruby integration. Look at this code, for e.g.:
#!/usr/bin/env jruby require 'java' set = java.util.TreeSet.new set.add "foo" set.add "Bar" set.add "baz" set.each do |v| puts "value: #{v}" end string = java.lang.String.new string = "Vishnu" puts string
Sweet ain’t it? One of Ruby’s selling points has always been that it’s easier to drop into a low level language (C) and write extensions for expensive functionality, thus negating Ruby’s slow performance. But stuff like the code sample above should make it pure nirvana for expensive operations. I haven’t compared speeds yet: I’ll do that soon using a simple Web framework like Camping & then a simple Rails app (i.e. Camping/WebBrick on Ruby and JRuby and Camping/Mongrel vs Camping/Glassfish: if I can get it running). JRuby isn’t perfect yet: Rails applications aren’t officially supported, but I hope to get a useful app deployed on localhost soon, and if there’s interest, deploy it to my slice. It’s an upward slope though for me, since the whole Java deployment scene [making a WAR] seems so bloody complicated (why, oh why?) but a good indicator for good Ruby/Rails deployment on JRuby would be to just type in rake deploy
and have your code get into the whole Glassfish stack.
Ruby Magic: Metaprogramming
Rails, if you’ve used it, has a rather elegant way of manipulating time. Stuff like 1.hours
and 2.minutes.from_now
just work. Let’s see how Ruby modules can be extended really really easily:
#! /usr/bin/env ruby class Integer def seconds self end def minutes seconds * 60 end def hours minutes * 60 end def days hours * 24 end def months days * 30 end def years months * 12 end def from_now Time.now + self end def before Time.now - self end end class String def palindrome? self == self.reverse end end class Time def leap_year? (year % 4).zero? and ((not (year % 100).zero?) or (year % 1000).zero?) end end class TrueClass def say "is" end end class FalseClass def say "is not" end end #2 is an Integer puts 2.minutes.from_now #"vishnu" is a String puts "vishnu".palindrome? puts "malayalam".palindrome? puts 2.years.from_now.leap_year? #Check if n years before is a leap year puts "How many years before?" year = Integer(readline) puts "#{Time.now.year - year} #{year.years.before.leap_year?.say} a leap year."
The interesting thing about Ruby is not that metaprogramming is possible, but Ruby makes it really easy to do it.
Ruby Magic: Blocks
I’ve been using Ruby a lot lately, and recently had to implement a “related” objects feature in Rails. You know, “Related Videos”, “Related Pages”, etc. I decided to sort them by objects that have the most common tags. Try this one-liner:
#Inside video.rb Model, Related videos def related(count=5) tags.collect { |tag| tag.videos }.flatten.uniq.sort_by { |video| (video.tags & tags).length }.delete_if { |video| self == video }.reverse[0..count-1] end
Let’s try dissecting that:
tags.collect { |tag| tag.videos }
Collects all videos associated with the current object’s tags into an array of arrays (each array representing the slideshows for a particular tag).
.flatten.uniq
Flatten that array (make it a single dimensional array, preserving logical order) and then eliminate duplicates
.sort_by { |video| (video.tags & tags).length }
sort_by sorts the arrays by a particular attribute. So for each video in the array, video.tags & tags
gives the intersection of tags for the video under consideration, and the current object’s tags. Because of .length
, the sort_by function sorts by the number of such intersecting tags.
.delete_if { |video| self == video }
And, remove self references.
.reverse
Sorting is by default ascending, so reverse the array, and:
[0..count-1]
return only the first n elements.
So, you’d call it by something like video = Video.find(1)
and @related_videos = video.related
.
The interesting thing is that, I never ever was a programmer given to verbose lengths of code like this. Doing this in any other language would feel so clunky. But in Ruby, it somehow feels natural. Like you can read through the code in your head and have it make perfect sense.