why i like ruby or ruby the language of the lazy programmer
This is quite funny. A friend, Perl addicted, is now learning Ruby. He really enjoys the language but made a interesting observation: Ruby is a language for lazy programmers!
Well, I have to agree... You know, I love saving keystrokes and achieving more by writing less. And this is so true with Ruby.
Let me give a really simple example, comparing with java - don't get me wrong... I love java, specially the platform, but it fits well here since I've always been a Java guy.
Imagine you have a Phone class with the attributes number and type, which can indicate whether the phone is a land line or a mobile phone. Then you got an array filled with phone classes and you want to narrow it by creating a new array only with mobile phones.
In Java, such a class could look very much like this:
public class Phone {
private String number;
private String type;
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
Quite simple, isn't it? But we are telling the compiler many things we actually shouldn't need to. This class is a java bean and as such, among other things, it needs a pair of getters and setters for each of its attributes.
Now, on with our example, the same class, in ruby, looks like this:
class Phone
attr_accessor :number, :type
end
Yeah, I know the feeling. This class has exactly what we need: the two attributes with its own pairs of getters and setters each. But we didn't need to inform it in the verbose way Java has teached us. Cleaner, period.
Now to the code that actually returns the new array containing only mobile numbers. In java, we can do it in two different ways.
Using an ArrayList:
//Create two phone objects, one land line and one mobile
...
// Add them to an array
ArrayListphones = new ArrayList ();
phones.add(land);
phones.add(mobile);
//Return an array only with mobile numbers:
private static ArrayListselectMobilePhones(ArrayList phones) {
ArrayList<Phone> mobiles = new ArrayList<Phone>();
for (Phone phone : phones) {
if (phone.getType().equals("mobile")) {
mobiles.add(phone);
}
}
return mobiles;
}
Or using ordinary arrays:
// Assume the same phone objects here
...
//Add them to the array
Phone[] phones = new Phone[]{land, mobile};
//Return an array only with mobile numbers:
Phone[] mobiles = new Phone[a.length];
for (int i = 0; i < a.length; i++) {
if (a[i].getType().equals("mobile")) {
mobiles[i] = a[i];
}
}
And you're good to go. Actually this code with an ArrayList here only looks good thanks to generics. But this is another matter. Let's take a look at the ruby code that accomplishes de same task:
//Create two phone objects, one land line and one mobile
...
//Add them to an array
phones = [land, mobile]
//Return an array only with mobile numbers:
mobiles = phones.select { |phone|
phone.type == "mobile"
}
See the difference? Java is a great language but too verbose at times. This is a really simple example but if you take the same principle to a bigger app... yeah, you see where I'm going.
The bottom line... Ruby may be the language of the lazy programmer, as my friend pointed out. But I don't mind being called lazy as long as I can type less and be more productive. Do you? :)
euruko 2008 european rubyconf prague
On friday I'll be heading Prague for the European RubyConf.
Anyone is going? :)
Almost 300 attendees already registered for the event. And a few very interesting people will be speaking there like Matz and DHH (this one, through skype).
Besides that, the organization staff is scheduling 2 parties, friday and saturday, for the attendees.
Networking comes to mind, doesn't it? I think it will be a great opportunity to meet interesting and bright people.
So, see u in Prague!
qcon 2008 domain specific languages
Today was the first day of the conference and it started with a tutorial about DSL's with Martin Fowler, Neal Ford and Rebecca Parsons. We also had as attendants Ola Bini, core developer of JRuby, and others. My expectations were pretty high and the presentation didn't let me down. I'll try to put here toghether my impressions and some notes I took while I was there.
Marting Fowler started discussing what DSL's are and giving some examples that many of us use in our day to day Job. Like the XML configuration files in the Java world. It is a kind of DSL, it has it's own keywords and syntax in order to express some information that will be used , for instance, to configure an underlying framework.
The problem with XML is that it becomes hard to see the overall behavior behind it. It's not very fluent to understand the purpose of an XML file just by looking at it for the first time. There is too much "noise". Things that get into the way of the readability. - YAML files are an much more readable alternatives to XML.
The same happens with a standard framework api code. Let's take for instance a sample API configuration code written in Java to tackle the domain of hotel reservations. A framework like this could have the following implementation:
HotelService hotelService = new HotelService();
PersonService personService = new HotelService();
Hotel hotel = hotelService.findById(1);
Person guest = personService.findById(10) ;
Reservation reservation = new Reservation() ;
reservation.setFrom("2008-03-10") ;
reservation.setTo("2008-03-14");
reservation.setGuests(new Person[]{guest});
hotelService.book(hotel, reservation);
Of course implementations of this simple example may vary but we can see here some of the readability problems. One approach we could use for that is to develop a Fluent Interface to wrap this API. This was one of the techniques explored during the tutorial and the actual fluent interface could now look somewhat similar with this:
new Hotel(1)
.book()
.forGuests({
person.find(10)
})
.rooms(1)
.from("2008-03-10")
.to("2008-03-10");
Much more readable, huh? One of the main benefits of using DSL's they highlighted in the tutorial is the simplicity of code you can achieve. You can actually show this code to a business person and he can understand it. This is a kind of internal DSL.
But there is still a bit of noise in this code. The the parenthesis which are not always desirable, and the use of double quotes for dates. But, this is Java code, and Java doesn't give too much room for you on the DSL subject. Here was when the speakers changed their focus a bit to Ruby. It's dynamic nature and metaprogramming techniques provides a powerful flexibility that allows for a looser syntax.
So in ruby the previous interface could look like this now:
Hotel.find(1) .book(1.room).forGuests {
Person.find(10)
}.from(march.10.2008).to(march.10.2008)
We got rid of the double quotes and the code looks more fluent, like a normal english sentence. I doubt a business guy woudn't understand what this code is doing. With this, we can get closer to the business guys, with a common vocabulary, and fill the gap between us.
This is just one of the ways we could have written this code and is not the actual example used in the tutorial. The syntax also really depends on how readable you wanna make your code. I'll provide those later when they release the digital format of the presentation.
So one of the flows that the development of an internal DSL can get is to build a framework and define the DSL on top of it. But we should also keep in mind that DSL's shouldn't be general purpose programming languages. They should be created to tackle a specific kind of domain problem, so we would have a whole system made of small DSL's.
Another interesting subject that was touched is testing. How do you test DSL's?
The suggested approach, and that I think is quite reasonable, is to have separate tests for the underlying framework and another to test the DSL and its parser you can assure you have the expected behaviour of both parts.
This is really just a summary of my thoughts and of what happened there. I'm not going into too much details right now but if you found something too abstract - and it is! ;) - feel free to ask details. I'll be more than happy to help.
This is definetly an interesting subject and now I'll head to play more with all that. :)
PS; This is not the whole presentation, just the best of it from my stand point. Other subjects include External DSL's which can actually involve you coding Lexers, Parsers and Compilers. It's usually not worth the hassle. And it's too complicated anyway, that's why I left it out from this post.
qcon 2008 london
Next week I'll be at QCon, in London, so if any of you are going to the conference and would like meet up for a couple of beers and a tech talk, please don't hesitate to drop a message.
For those of you who have never heard of QCon before, it is a really nice event to play along with some of the most popular names in the software engineering community. This year's conference features people like Martin Fowler, Neal Ford, Erich Gamma and much more.
So stay tuned, the conference takes place during the whole week and I'll try and keep you posted about what's happening over there.
C u in London!
openid
I think I've been really lucky lately. In my new job I'm getting to work with many interesting things and OpenID is just one of them.
We are investing high in Ruby on Rails and we have now a few internal applications in development stages. Our manager wanted the ability to let people log in to our rails applications(for now) using their OpenID accounts.
It was a funny task, as I knew very little about OpenID. The idea actually is really good. Instead of creating a new user account on each new service/site you'd like to subscribe to, you create a single user account in a OpenID provider - like MyOpenID - and use this identity to authenticate yourself in the services/sites that support this protocol.
What do we earn from that? Well, in my opinion, we can get a couple of benefits:
- You don't need to memorize 723 logins and 723 passwords (if you really care about creating different passwords for all of your user accounts)
- You don't authenticate yourself to the service you're attempting to use. This service actually asks to your provider if your identity is valid, and you authenticate yourself there. Nowhere else.
I strongly recommend you visit the OpenID to understand more about it.
But, back to the problem, we needed to put it working in a rails app. And that's when I found the ruby-openid library, provided by OpenID Enabled.
It is a complete library, really well documented that provides an abstraction layer both for consumer and server applications.
My first step was to develop the consumer. That's what you need if you are going to provide your users with OpenID authentication in your web site. The ruby-openid library comes with several samples that really helped me out here. They were developed using Ruby On Rails and are a really good start point.
After this step, I was asked to evaluate the possibility of being a OpenID provider. At first I thought it would be a really complicated task, but again this ruby library had a great example of a simple provider. The drawback is that the samples were developed in an older version of Rails ( < 2.x ) . So I had to freeze the Rails version to 1.2.5 so I could run the provider sample code.
I am now working on porting this code to Rails 2.x, into one of our applications and it's been flowing well so far. Just wanted to share this library for those of you trying something similar. It is really worth a look.
dbunit and hibernate
I never paid too much attention on testing database stuff. While working with java, the closest I got to something workable was using the test case abstractions provided by the Spring framework. It ensures that each test method runs in its own transaction that is rolled back after the test's execution.
Fair enough. I used the setUp() method on my TestCase to configure some records so I could work with them, removing all of them in the tearDown() method. It was quite simple and worked.
But I always felt something strange with this solution. First of all, I had to add another framework just for that. - Actually I was using spring for dependency injection, but if I wasn't, it wouldn't be a nice option. And another thing that bothered me, is that you cannot guarantee that your database is in a known state.
After I started to work with Ruby - and Rails - I discovered the testing fixtures. It is a really nice way to set up your testing data without having to worry about your database state. - If you don't know what I'm talking about, follow the above link first.
Then I received a message from a co-worker saying he was having some trouble in using DBUnit with Hibernate, and asked for some help. I've heard of DBUnit before but never tried it myself. It was a very good opportunity to take a better look into it.
The basic idea after all is very similar to that of the Rails Fixtures: You have some sort of external file - XML in this case - where you set up the testing data. So the framework takes care of erasing the database, inserting your test data and returning it to its original state.
So far so good, DBUnit's default Classes works with JDBC, DataSources and JNDIDatasources, but not with Hibernate. The effort to put them working together is minimal and is documented in their web site.
I decided to share how this can be done with hibernate and in the end, you would have a test case similar to this one:
rails 20 xml data type and db2
[2008/04/30] Update: The ibm_db gem has been updated to support the new Rails 2.0 style migration. Now you can just use t.xml and it will work. Look here for more info. Thanks to Mario Briggs for pointing me to the update.
---
In my new job we work with XML data natively stored on DB2. I have done some test with Rails and DB2 a few weeks ago and it's pretty interesting, specially the easiness that Rails deals with XML.
We decided to test some new features of DB2 9.5 and I decided to test them with Rails 2.0.
So I created a new Rails app, configured the database.yml to use the idm_db gem and fired:$ rake db:create
The output is nice but, the database isn't there! I suppose it's something with the gem that needs to be updated. But really don't know about it. It just doesn't work. But this will not hold us down. I will just create the database by hand and keep going with my tests.
After that, I created a new model XmlDocument, which has a column named data, of type XML. According to the new migrations syntax, my model's migration would look something similar with this:class CreateXmlDocuments < ActiveRecord::Migration
def self.up
create_table :xml_documents do |t|
t.xml :data
t.timestamps
end
end
def self.down
drop_table :xml_documents
end
end
Right? Ok, I fired up a terminal and lauched:$ rake db:migrate
The output? Here it is:== 3 CreateXmlDocuments: migrating ============================================
-- create_table(:xml_documents)
rake aborted!
undefined method `xml' for #
Yes, a big nice exception! The new migration syntax doesn't allow you to do t.xml! But please don't ask me why! :p
The solution? Well, although it's weird - imo - , it's also easy. You can mix the new and the old syntax in the same file. So our model's migration will now look like this:class CreateXmlDocuments < ActiveRecord::Migration
def self.up
create_table :xml_documents do |t|
t.column :data, :xml
t.timestamps
end
end
def self.down
drop_table :xml_documents
end
end
And that's it! We're ready to go! I didn't find anything else different so far, besides what I described here. Hope this helps!
rails 20 scaffold
Following the Rails 2.0 hype, I've been playing around with it and decided to share a first impression: Scaffolding is gone!
But wait, before you knock your head against the wall, let me tell you something: I lied :)
Scaffolding is not really gone. It's just changed a bit.
How can I tell? Well, as a good developer I thought: "I'll just create a scaffold with the new version and see what's different"
I fired up a terminal, created a news rails application and generated a new model:$ script/generate model Contact name:string email:string
- yes you can do this in rails 2.0, and these fields get into your model's migration!
Now the I have a new model, it's time for a controller to manage it:$ script/generate controller Contacts
So your controller would look something like this huh?class ContactsController < ApplicationController
scaffold :contact
end
Well, too bad! The method scaffold is gone from ActionController::Base! And I'm not lying this time!
Now that the dynamic scaffold is gone, we're left with the static one.
Ok, let's try it then:$ script/generate scaffold contact
And it won't work again! ;) At the end of the output, you will get something like this:Another migration is already named create_contacts: db/migrate/001_create_contacts.rb
It really means that if your model is meant to be used by a scaffold, you better generate it in the same line. It will fail, afaik, if the model previously existed. Destroy yout model and controller, and execute the following:$ script/generate scaffold Contact name:string email:string
Done! Just run your migrations, startup your server and your new scaffold in rails 2.0 will be working gracefully!
It took me a while to discover this changes because I didn't find it well documented. But maybe I was not looking in the right places. :)
spring 25 dependency injection that doesnt hurt
Dependency injection - DIÂ - Â is a great thing. Really. The hability to tweak implementations without touching your code is awesome and the DI frameworks, like spring, saves you a lot of coding. No more service locators stuff.
But, and there is always a but, you're left with a bunch of XML configuration. And I hate it. Not that XML files are bad... the thing is that everything nowadays has its own set of XML configurarion files. And Spring is not different.
rubyworks production stack for rails
Well, we all know how hard, or at least cumbersome, it can be to set up a production environment to deploy your applications. Besides all the hardware stuff like storages, links, routers you are still left with a huge amount of software configuration to handle. This often includes configuring things like clusters, load balancing and services monitoring - Including notification of interested parts in case of any failure. Pieces of software you have to tie up and make them work together.
But hey, ruby lovers, you may have a better way to get this going! Released by ThoughtWorks, RubyWorks is, as quoted from their website, a production application stack for Ruby On Rails applications. I decided to give it a try and I really enjoyed it.
First of all I didn't want to mess with my actual configuration so I installed a new vm with Virtual Box. It has Ubuntu 7.10 on it, with 256MB of memory.
After installing RubyWorks - instructions on their website -, you get a new skeleton rails app up and running, being served by 4 mongrels that defaults to production environment! Impressed? There is more. A HAProxy is also set up in front of your mongrel servers acting as a load balancer.
Well, you probably want to monitor all that stuff huh? A monit web interface is waiting for your call on port 2812! It monitors all your mongrel servers - four by default - and your HAProxy, allowing you to measure CPU and Memory usage, among other things.
The coolest thing here is that all these softwares you would have to setup by hand are already working together, ready for production! Well, is it?
Going a little deeper, I deployed a database backed application to test this stack's performance.
I used Siege to stress the app and I am very happy with the results! I compared it with a single mongrel running on production env and no proxy at all.
It is worth mentioning that having 4 mongrels running took my vm to 77% of memory usage, while a single mongrel took it to 38%.