Ruby 1.9 Hash-tricks
user = { name: 'Evan', age: 27}
puts "My name is #{data[:name]} and I am #{data[:age]} years old."
puts "My name is %{name} and I am %{age} years old." % data
user = { name: 'Evan', age: 27}
puts "My name is #{data[:name]} and I am #{data[:age]} years old."
puts "My name is %{name} and I am %{age} years old." % data
One of my earliest freelancing gigs circa 2007: http://www.schemakonsult.com . Written in CakePHP(!) and using tables for HTML layouts! Yes, tables. Back then, I refused to listen to all those hippie web designer talks about the bad practice of using tables as a layout tool.
I'm actually proud that it's still running 5 years later.

Something I picked up somewhere:
Coding is about how you should write,
Programming is about how you SHOULDN'T!Coding as about the Language and Syntax,
Programming is about the Paradigm, the Thought ProcessCoding is represented by the 'Writing' Metaphor,
Programming is epitomized by the 'Construction' metaphorCoding defines the Solution,
Programming defines the Problem too!Coding creates the Implementation,
Programming creates the InterfaceCoding is about "Getting it done...",
Programming is about "Getting to know it!"Coding gets you Paid,
Programming makes you Satisfied.Coding is what we HAVE to do,
Programming is what we SHOULD be doing!
"It's more like they're observing time. I think these guys show up at important moments. Um, historical, technological, scientific. But it's rare. Maybe two dozen different definite occurrences in the past 5,000 years of human history. But recently, I've charted twenty-six sightings in the past three months alone. It kind of makes you wonder." - Fringe
The observer pattern is probably a programming practice that is very under-appreciated in Ruby on Rails. Even with ActiveModel::Observer, Rails programmers have a tendency to use ActiveModel callbacks, even for actions that the subject couldn't probably have a care for.
But observers are there to keep the things as orderly as possible. They do not necessarily have to interfere with the subject, but even in such cases, the subject shouldn't really know what the observer is doing, or that there is any observer at all. And yes, that goes the same for observers in programming and those creepy bald guys in Fringe. And for stalkers, too.
I've started this crusade to clean up our codebase for Infinite.ly, and one of my many actions is to elevate the use of observer patterns in our models.
Take the code for our Rule model below. We wrote so that each time a Rule record is created, it makes an HTTP request to the Gnip API and create a corresponding Gnip rule over there, and when that Rule is deleted in our database, it fires another request to delete the corresponding Gnip rule. In the beginning, the code probably looked a lot like this:
# app/models/rule.rb
class Rule
include Mongoid::Document
after_save :create_gnip_rule
after_destroy :delete_gnip_rule
...
protected
def create_gnip_rule
# Several lines of code to prepare the Gnip rules
# and send them to the Gnip API
end
def delete_gnip_rule
# Several lines of code to prepare the Gnip rules
# and delete them from the Gnip API
end
end
The next iteration of the code eliminated the tedious HTTP request methods from the Rule model, so that it utilizes methods from a separate GnipRule class to create/delete Gnip rules:
# app/models/rule.rb
class Rule
include Mongoid::Document
after_save :create_gnip_rule
after_destroy :delete_gnip_rule
...
protected
def create_gnip_rule
# Prepare keywords
GnipRule.create_rule(keywords)
end
def delete_gnip_rule
# Prepare keywords
GnipRule.delete_rule(keywords)
end
end
It gets better. We decide to separate the code for Gnip interfacing away from the basic Rule class, and simply the functionalities in through ActiveSupport::Concern:
# app/models/rule.rb
class Rule
include Mongoid::Document
include Rule::GnipInterface
...
end
# app/models/rule/gnip_interface.rb
class Rule
module GnipInterface
extend ActiveSupport::Concern
included do
after_save :create_gnip_rule
after_destroy :delete_gnip_rule
end
protected
def create_gnip_rule
# Prepare keywords
GnipRule.create_rule(keywords)
end
def delete_gnip_rule
# Prepare keywords
GnipRule.delete_rule(keywords)
end
end
end
From a coding perspective, this is actually pretty clean. We've succeeded at separating the code that's responsible for dealing with Gnip rules away from the subject (which is the Rule).
But from a programmer's point of view, this is simply not ideal. We're supposed to separate the logic, not just the code. ActiveSupport::Concern tries to emulate a kind of separation-of-concern, but when it comes down to it, the Rule object is still aware that it's directly interacting with Gnip, and although it has no control over the latter, it had been made responsible for whatever Gnip does.
In comes the observer pattern.
# app/models/rule.rb
class Rule
include Mongoid::Document
...
end
# app/observers/gnip_observer.rb
class GnipObserver < Mongoid::Observer
observe :rule
def after_create(rule)
# Prepare keywords from rule
GnipRule.create_rule(keywords)
end
def after_destroy(rule)
# Prepare keywords from rule
GnipRule.delete_rule(keywords)
end
end
Now Rule is totally unaware that there's a GnipObserver doing all that heavy lifting on Gnip after it's created or deleted.
Observers are just one of those few things that make programming interesting. And Rails made it exciting to write these with ActiveModel::Observer (Mongoid::Observer actually just inherits from ActiveModel::Observer). Every Rails programmer should know when to use it, so you can keep both your code and your program logic clean.
I decided to change the theme for my sandbox, and went for the purely minimalistic style.
I also upgraded this site to Rails 3.1 RC 5, so I guess I'll be doing my part for the Rails 3.1 bug-mashing through this site.
So many things has been happening, I can barely wrap my mind around them. Rails 3.1, Coffeescript, Compass/Blueprint CSS, and the Dragonfly file upload system. And here I thought I was trying to keep it down in the name of minimalism.
It took like two hours, but I finally got syntax highlighting working for the site.
I probably spent most of those two hours experimenting with various syntax highlighters like Harsh, and Coderay, not realizing there's a Railscast for the very same thing that I'm trying to achieve with Pygments, and it was posted only a couple of weeks ago!
Now I can post code snippets!
class Post
include Mongoid::Document
include Mongoid::Slug
include Mongoid::Taggable
include Mongoid::Timestamps
field :title, :type => String
field :content, :type => String
slug :title
validates :title, :presence => true, :uniqueness => true
validates :content, :presence => true
default_scope order_by([:created_at, :desc])
end
Too bad there's still no Pygments support for Slim...
I had to generate a stylesheet for this using the Sunburst theme from Textmate. It's a rather tedious process involving (1) converting the Textmate theme into a Vim color theme, then (2) running the vim2pygments.py script against the Vim theme, and finally (3) generating a CSS version with nothing else but the pygmentize command. Someone has to streamline this process sooner or later.
The whole ordeal is documented here. If you clone the whole Pygments repository from Bitbucket (using Mercurial), there's a bundled vim2pygments.py in scripts/ already, so no need to clone the github repo above just for the script.
Most people don't like distractions. They want to be constantly focusing on a particular job. I think it's terribly boring.
Which is why I need a distraction. I'm starting to find myself highly absorbed at work even at 3 in the morning, or forfeiting a run or a workout just coz' I feel this need to finish whatever work I'm doing. It's unhealthy to be so engrossed with work, however one tries to justify that it's work that's enjoyable.
I used to have a distraction. It was called online gaming. Specifically, World of Warcraft. That turned out to be a big distraction from everything else in life. And as much as I wanted to have time off from work, WoW eventually became another work for me. Especially with a guild that's constantly trying to be at the top of the WoW raiding scene. I found myself constantly getting stressed about being at home on time for a raid invite. And then I'd sit in front of the computer for hours as I and 24 other people, most of whom I've never met in person, tackle and struggle blowing up various pixelated digital monsters.
So, I quit. I think that was a wise move. But now, I find myself with no distraction, save for the occasional nights where I'd go head off with friends at some nearby watering hole. But mostly, I find myself sitting in front of a computer. This time, instead of killing pixelated dragons, I'm struggling with algorithms and code structures. It's boring.
I need a new distraction.
It's been a couple of weeks since I've bought a VPS and a domain name after a drunken stupor, thinking I can always blame it on the alcohol if I don't follow through with what I intend to do with it: start another blog, this time for good, and use this server as a sandbox for my quirky ideas. The server's practically been running since last Friday at around 4am in the morning, and the domain name has been propagated shortly after. It was a barren wasteland.
So, now, I found myself with nothing to do but stare at pixels again. Instead of doing that, however, I decided to populate this arid desolate server with some life. And thus, this blog is born.
Some information about the things I'm using to run this experiment: