What I wish a Ruby programmer had told me one year ago

Apr 2010

Warning: Biased content follows.

Scroll down if you just want to skip to my wise words.

One year ago, I started coding for real again. I dumped wasting times on stupid games and so on. I like building websites, so I started by going back to the roots. HTML & CSS which I had coded when I was about 10, and it didn't take me long before I had moved from tables to div tags and all. I learned myself to hand-code it, and not rely on software like Dreamweaver. Resulting in better, more compact and valid HTML. I had played around with PHP when I was about 11, so I decided to build some stuff in it again.

I should never have done that, I have realized. I used about 4 months in PHP, picking up bad habits. At some point, I found myself reaching points where I saw PHP solutions plain stupid. I didn't have experience with any other languages, but I knew there had to be better ways. So I decided to dive into Python, and later look at the Django web framework. So I did.

After a few days playing around with Python, I felt okay with it. I didn't love Python, but it was fairly simple, and from the simple Django examples I felt confident I was ready to proceed and expand my literacy in Python via Django. After following the basic tutorials, I felt Django was already superior to PHP.

I had heard about this evil language called Ruby and some framework called Rails, I had not considered it though because of three (stupid) reasons:

  • Highest ratio of smug fanboys
  • End-statements
  • Ruby had become popular due to Rails, not the other way around as it is with Django

So a Saturday night, I turned off the light, locked the door and sealed the windows. It was time to check out this Japanese creation. The fanboys all over the web seemed to recommend this fabulous book called Why's (poignant) guide to Ruby. I installed Ruby, and dove into the book.

A few hours later, I had forgotten everything about Python. Stupid language. Ruby was where it was at, and I instantly started recommending it to all my code-buddies. It's such an awesome language, why not spread the joy? They said I was a fanboy, and told me to gtfo. And I quickly realized what had happened.

  • Ruby is evil

Ruby is indeed evil. So evil. Extremely evil. But why so evil? Because it's so beautiful. The syntax is so elegant, everything are objects. Everything makes sense. The Ruby-way of doing things is so sexy.

I quickly headed over to #ruby and asked them what I should do to practise my all-so-awesome Ruby skills, and some guy recommended me coding a todo-app. It seemed it was the new semi-advanced-but-no-so-advanced hello world. So I did, and here's the extremely awesome output (be prepared, it's extremely bad code and you should NEVER do something like this in Ruby):

class Todo
  def initialize(*argv)
    @argv = argv

    begin
      send(@argv[0])
    rescue TypeError
      list
    rescue NoMethodError
      puts "Command #{@argv[0]} not found.\n\n"
      help
    end
  end

  # Lists help information
  def help
    puts <<-help
Commands for Todo.rb:
   add [task name] - Add a new task
   list - Lists all tasks
   done [task id] - Complete a task
   help - Prints out this information
    help
  end

  # Add task
  def add
    unless @argv[1]
      puts "Lacking argument [name]"
      exit
    end

    # Append task to file
    contents = File.read('todo.td')

    File.open('todo.td', 'w') do |f|
      todo = contents + @argv[1] + "\n"
      f.write(todo)
    end
  end

  # List all tasks
  def list
    # Read content
    contents = File.read('todo.td')
    puts "No tasks" unless contents

    # Show it with ids
    i = 0
    contents.each_line do |todo|
      i += 1
      puts "##{i} - #{todo}"
    end
  end

  # Finished a task
  def done
    unless @argv[1]
      puts "Lacking argument [id]"
      exit
    end

    # Put tasks into an array
    todos = File.read('todo.td').split("\n")

    unless todos
      puts "No tasks"
      exit
    end

    puts "Completed task: " + todos[@argv[1].to_i - 1]

    # Delete task from array and make string
    todos.delete_at(@argv[1].to_i - 1)
    content = todos.join("\n")

    # Update file
    File.open('todo.td', 'w') do |f|
      f.write(content)
    end
  end
end

todo = Todo.new(*ARGV)

Proudly I showed it to the guy who recommended me to create a Todo-app. "Look at this! Ruby is so narwhal!" It took him a while to reply. It would've taken me a while to reply too if somebody showed me such code. It looks like some Bash code, in an object oriented language. Woah. So this guy, he was very helpful and told me he'd make a skeleton for the app. and make me fill in the holes/methods, it was something like this:

class TodoList
  def self.load(file)
      # read the file, create a list, create items, add them
  end

  def initialize
  end

  def add(item)
  end

  def write(file)
    # write the file, only write the undone items
  end

  def [](id)
    @list[id]
  end
end

class TodoItem
# provide reader and setter for name and state

  def initialize(name)
    # store name
    # set state to undone
  end
end

# ---
# the library will be used like this:
# list = TodoList.load("todo.td")
# list[0].done = true
# list.add TodoItem.new("another cool item")
# list.write("todo.td")
#

So I did. It took a while to adapt from the bad PHP-style, to the Ruby-style. I ended up with this. And then I added an interface. And then meta-programming. And then I was in love.

So the title of this post is "What I wish a Ruby programmer had told me one year ago..", and that's quite an intro. Since what I wish a Ruby programmer had told me is not much, but could've saved me 4 months in company with PHP.

Here's what I'll tell anyone asking me how they should get into programming:

"First, learn Ruby (buy a book). Play around, create a Todo-app. Create simple programs to handle system tasks for you. But always remember to use classes, and separate the interface from the functionality. In the end this will be pain, you'll always think about making it appear Rubyish, but at some point - it becomes natural. And when it has become natural, you go create a Gem. If you create a big Gem, with much functionality - split it into more Gems, and make it require those. Or use other peoples Gems. If you want to move on with developing web applications, start out simple. Check out a lightweight framework like Sinatra, it's cool and very fun to work with. Move on to Rails if you want, it takes longer to learn, but it is much faster to develop in."

And perhaps point them towards Linux, if they are up for it:

"I do not believe Windows is the best development platform in the world for Ruby. I recommend you to try out Linux (or OS X, if you've got the money for it). Start with a simple distribution, like Ubuntu. And then I recommend something like Arch Linux whenever you feel like you are ready for something more advanced, assuming you want to learn more about how Linux works!"

Note: I'm biased. And I know it. Ruby is not a language for everyone, and PHP is not a bad language - it's just not for me. Neither is Python a bad language - it's just not for me. Windows is not a bad operating system - It's just not for me. I advise you to try different languages/operating systems, and eventually find the one you feel at home in.

This post has been translated into Spanish by Maria Ramos.