It’s not often that Japanese Yukihiro “Matz” Matsumoto, the creator of the Ruby programming language, visits Europe, and his visits to Denmark are even less frequent. When I saw that Matz was coming to speak at the Ruby Fools conference in Copenhagen, was coming to my very own home town, I knew I couldn’t miss that opportunity.
Matz delivered his keynote presentation in the morning at the second and final day of the conference. When he entered the room, there was no hush of: Look, it’s the creator of Ruby. Whoah! That wasn’t because Matz isn’t man to respect, admire and perhaps even worship for his language design skills, but simply because Matz had already been around for the entire first day of conference, watching the talks with the rest of us, and willingly talking to everyone. By day two, we had gotten the message: Matz was one of us. A completely down to earth guy, extremely friendly, smiling and - make no mistake - very intelligent.
Matz started out by explaining that if he looked a bit tired, it was because he had spent too much time last night hacking away at Ruby. He then went on to say - in complete agreement with Dave Thomas’ keynote, by the way - that Ruby on Rails had changed the lifes of the people in the Ruby community a lot, that it had even changed Ruby. He went on to ask how many in crowd knew Ruby before Rails came along - only a few raised their hands - and who had got to know Ruby through Rails - many people raised their hands at this.
Matz underlined that he sees himself first and foremost as a language designer. He listed the many Ruby implementations being developed currently: YARV, JRuby, Rubinius and IronRuby, and said that this allowed him to focus on language issues rather than on implementation. But on the other hand he really liked to implement his language designs as well, so he had mixed feelings towards it all.
Following this, the Japanese language designer went through a historical walkthrough of programming languages, and how Ruby was - of course - at the top of chain of evolution, taking the best from Lisp, Smalltalk and Perl. He explained how he started the project of Ruby in early 1993. The regression in Japan meant that Matz - while not unemployed - didn’t have many assignments at work, so he secretly started to hack away at Ruby at the office.
The goal with Ruby was, and still is, to enjoy programming. Matz enjoyed designing and implementing Ruby, and we all enjoy coding in Ruby. He released the first version of Ruby by the end of 1995 - almost 3 years after he began his project. Ruby achieved enough success as an open source project to get Matz a job as a full open source software developer at a large Japanese company 1997, and in 1999 Matz released the first book on Ruby, with the obvious title “Ruby”. By this time the world really started to notice Ruby, and the Japanese book attempted to translate the book from Japanese to English, but since they were only used to translate the other way, the translation efforts failed miserably.
This was when they approached Dave Thomas, asking him to write an English Ruby book from scratch, and out of that came - in 2000 - “Programming Ruby”, or - as it is simply known as by friends - “Pickaxe”, named after the cover illustration. Since no other books on Ruby existed at the time, it was necessary to make it both a reference and a tutorial book. Matz had tried to do that himself, he explained, and was not very satisfied with the result, but Dave Thomas pulled it off!
Matz then asked: Why use Ruby? Well, we have Rails of course, no need to explain that, Matz said, but the two real reasons to use Ruby is productivity and joy. Productivity is emphasized more and more; the IT markets grow, but the budgets stay fixed and the schedules shrink! To accommodate this, we need our tools to allow higher productivity, and the programming language is one such tool. The language, however, also determines the way we think, and thus shapes the entire project, Matz said with a reference to the Sapir-Whorf hypothesis.
The second reason to use Ruby is joy. “Joy is the primary goal of Ruby”, Matz said. “I designed Ruby for myself to make me feel better and enjoy programming more. I want programmers all over the world to feel the same way.” You just got to love this guy! He also compared Ruby to Python, and said that one big difference is that Python seeks the one true way of doing things and wants everything to be organized, while Ruby people mostly care about how they feel about programming.
Matz went on to review the current status of Ruby. When looking at the current Ruby implementations, he admitted that JRuby was definitely faster than MRI (Matz’s Ruby Interpreter) and some times even faster than the current implementation of YARV (Yet Another Ruby VM, the “official” Ruby 1.9 VM). On the other hand he said that YARV was the fastest Ruby implementation on Earth, and that some benchmarks proved it to be 20 times faster than MRI! And, he added, it can get even faster.
When it comes to Ruby 1.9, Matz is busy clarifying the edges and corners of the language, and making the lives of Ruby implementors miserable by adding new features. He explained of few of the new features in Ruby 1.9. The first was enumerators: “Loop” methods such as each, map and find now returns enumerators. This has several benefits. For one thing, a method such as each_with_index would also be handy in other “loop” methods, i.e. it would be nice to have map_with_index and find_with_index. It would not, however, be very DRY to implement each of these methods seperately, so instead, the new feature of return an enumerator allows us to build up a chain of enumerators:
ary.map.with_index { |x, i| .. }
ary.find.with_index { |x, i| .. }
Both map and find returns enumerators, which support the with_index method amongst many others. This also allow us to use enumerators as external iterators, storing a the enumerators in variables and i.e. do this:
e1 = [1, 2, 3, 4].each
e2 = [10, 11, 4].each
loop {
p e1.next+e2.next
}
# prints 11, 13, 7
Notice how the e1 iterator has one more element than e2. The loop construct catches the exception that is thrown when next is called the fourth time on e2 and silently exits the loop.
Another very interesting addition in Ruby 1.9 is fibers. Matz explained fibers to be cooperative, light-weight threads that switches context explicitly. I wish I could explain this new concept in Ruby better, but I just haven’t really understood it yet. Hold no doubts, however, that fibers is an upcoming buzzword in the Ruby community!
He went to explain the huge efforts that has gone into full support for multilinguinization (M17N) in Ruby 1.9. Matz is a man with very strong opinions on Unicode, and he explained in detail how UTF-8, UTF-16 or UTF-32 was all far from being perfect. Encoding is a tradeoff between liability and performance, but they seem to have found a well-working extensible encoding model for Ruby 1.9. Matz didn’t go into details about that, because as he said: “Probably I talked too much about Unicode - it makes me angry every day.”
Matz finished off his keynote with a look into the future of Ruby. Unfortunately he was almost out of time by that point, so we were taken very fast through some slides some very exiting thoughts and future prospects for Ruby. I didn’t catch too many of them, but one thing I should mention is what Matz called method combination in his slides. It is a kind of aspect-oriented programming that allows pre and post hooks around a method, instead of using alias_method to achieve this end.
And then … Goruby?
Update: The slides from the keynote has been made available. They should allow us to take a closer at look at points about Ruby’s future.
The Ruby Fools 2008 conference is the first large-scale conference in Denmark dedicated to purely to Ruby. The opening keynote was done by Dave Thomas, and once again he managed to both inspire and provoke. This time, the pragmatic author took a starting point in the name of conference, and gave a talk with the topic: I’m a Ruby Fool.
Dave had structured his speak around the four major reasons for why he is a Ruby Fool. The first reason was “I’m in love”. He stated that not only is it a good thing to love your software tools, in fact you must love your software tools. He explained that the job as a programmer is one of the most difficult jobs of all, and compared it to the job of poet: We can create pretty much anything we want, but that also means that we are faced with the blank paper. His point was that if you don’t love your tools, it will show in your work.
Asking why he loves Ruby, Dave Thomas said, is like asking why he loves his wife or his kids. Nevertheless, he gave couple of reasons. One was that Ruby helps him to be expressive - it doesn’t tell him what to do. In Ruby, there is not one right way to achieve a result:
for i in 0..9 puts i end
10.times do |i| puts i end
(0..9).each do |i| puts i end
puts (0..9).to_a
puts *0..9
Dave also mentioned the fact that Ruby is a multi-faceted language as a reason. Not only can he do object oriented programming, but also procedural, functional and prototype based. The last one is where an object is constructed from Object.new and methods and fields are added on the fly. His other reasons to love Ruby was that it makes him productive, it is transparent and that it thinks the way he thinks.
Dave Thomas’ second for being a Ruby fool was that he likes imperfection. He different people on why imperfection is desirable:
Dave underlined that Ruby is not perfect - it is inconsistent. “If you want Matz to reject a change to the language”, Dave Thomas said, “say that it will make it more orthogonal”. This resulted in burst of laughter from the front row where Matz was sitting.
A third reason for being a Ruby Fool, Dave explained, was that he had to try to keep up. He showed how the Ruby distribution had grown from a few hundred kilobytes to six megabytes in version 1.9.0. “Is that scary?”, Dave Thomas asked, “Well, speaking to someone whose book documents every single method of Ruby, the answer is: Yes!”.
He went on to describe some of the new features in Rais 1.9.0 such as fibers, enumerators and the new regular expression engine. I won’t go into details on this here, since I expect to learn much more about these new features in Matz’s keynote tommorrow.
The fourth and final reason that Dave Thomas mentioned for being a Ruby Fool, was that he thought there was a community. He compared the early Ruby community to a small settlement in the old American wild west. One family would start out by settling down because the horse died or the wife didn’t want to go any further. Slowly, more settlers would join the settlement if they liked what you had done with place.
But suddenly, someone would find GOLD!, and the small town would be invaded by gamblers and prostiutes and grow hundred-fold. This is what happened to Ruby once Rails was released. The RailsConf this year is expected to sell out at 2000 participants. But that doesn’t matter, since Ruby is not the community - Ruby is just a resource, Ruby is the gold.
Communities are groups of people. You should choose the people you associate with carefully, Dave Thomas said, and always remember: Have fun!
One of my first hobby projects in Ruby on Rails, and for sure the longest living, is called Dinnerlyzer. It is a small, simple, pink (!) application that my girlfriend has used to plan our meals and the required shopping for several years. So far she is the only user, but a while ago I found myself wanting to add a user model and open up the application for multiple users. This meant that I had a lot of objects (recipes, ingredients, shopping lists, etc.) that needed to be associated with a user - the owner. It also meant that some objects should be shared between users (like the ingredients) while other should be private (like the shopping lists). This, in turn, meant that I stood with the prospect of adding a lot of filtering and setting of the correct user in my controllers.
Last week, I was hacking away at another hobby project with a couple of friends (one that will of course make us all zillionaires at some point in the future), where we found ourself wanting to be able to run the same application for multiple sites, but using the same physical backend. This meant the introduction of a Site object, associating almost all existing objects with a specific site, and - again - the prospect of adding a lot of filtering and setting of the correct site in the controllers.
In both cases I could have chosen to just go into the controllers and add the appropriate code to make sure all lookups and deletes was filtered by User or Site, respectively, and that all inserts and updates got these entities tagged on as well, but it just didn’t seem very DRY. It was too much work, it was not fun, and it was repeating myself.
My first impulse was to use observers. It is a Rails classic to use a UserObserver to make sure that fields such as creator_id or updater_id are set the currently active user. This is, however, done per class and not per controller, so if you want to differentiate, say, to filter on the owning user depending on which action has been invoked, you are generally out of luck. (Generally, because you can of course always hack your way to a solution.)
Then I asked Uncle Google for help, and - lo and behold - I found the Scoped Access plugin. Rails has had the with_scope method for a long time, but to my understanding it is not quite as powerful and DRY compared to this plugin. Let me give an example:
In Dinnerlyzer, I needed to restrict all access to recipes per user. I installed the Scoped Access plugin, and added this code to my RecipeController:
class RecipesController < ApplicationController
scoped_access Recipe
..
protected
def method_scoping
ScopedAccess::ClassScoping.new(Recipe, :user_id => current_user.id)
end
end
The scoped_access call at the top ensures that the method method_scoping is called to return the appropriate scope for all requests on the Recipe object. Not just lookups, but also creation, editing and deletion.
In another controller, I wanted all users to be able to browse and view all ingredients in the application, but only to be able to edit and delete ingredients added by themselves. This was done as simple as:
scoped_access Ingredient, :except => [:index, :show]
In the other application, we were able to employ a similar strategy, allowing us to very fast and in a quite DRY way to add these access restrictions to our controllers.
Hello, I'm Casper Fabricius. I have developed for the web for 8 years, and have been enjoying Ruby on Rails for the past 3.
My experience covers communities, shopping solutions, multi-language sites, heavy back-end lifting and a wide selection of more traditional websites. I currently favor Radiant CMS as a platform, and I am an expert Radiant extension developer.
I am based in Copenhagen, Denmark, but I take assignments from across the globe. Feel free to study my resumé, featured projects and - of course - to hire me.