April 2006 Archives

pat eyler

AddThis Social Bookmark Button

(Reposted from my blog, at Steve Mallet’s request)

I was IMing with a friend today, and asked him if he was paying attention to the Coverity scan. He told me he wasn’t, and I jokingly commented that it had the potential to be as addictive as fantasy baseball.

Steve Mallett

AddThis Social Bookmark Button

Yoichiro Hasebe has sent in this link to a Japanese translation of ONLamp’s seminal Rolling with Ruby on Rails - Part2 article.

If anyone is Japanese to English and the reverse capable & notices any error Yoichiro would love to hear from you.

Kampai!

pat eyler

AddThis Social Bookmark Button

Recently, there’s been an outbreak of regularly scheduled hacking
nights within Ruby Brigades. As far as I know, this started a couple
of years ago with the Seattle.rb (and they’re still going strong).
The general idea is that if you hold your meetings on a regular night
(say the 4th Tuesday of the month), then interested Rubyists could
gather on the same weeknight during the non-meeting weeks (so every
Tuesday except the 4th in our example) to hack on Ruby projects.

Gregory Brown

AddThis Social Bookmark Button

It seems that I can never manage to sit through a class at my university without getting sidetracked. One of my favorite diversions is reading through Ruby’s standard library, and today I decided to check out open-uri’s source.

Many of us have used open-uri to open up a web page. I think it’s super cool that something like open("google.com").read magically becomes possible with Tanaka Akira’s library.

However, one thing I never considered was that open-uri could help us open other things too. Take a look at this.

By default, Kernel#open cannot open arbitrary things.

sandal@harmonix:~$ irb --simple-prompt
>> class A
>>   def open
>>     "you opened it!"
>>   end
>> end
=> nil
>> open(A.new)
TypeError: can't convert A into String
        from (irb):6:in `open'
        from (irb):6
        from :0

However, by simply requiring open-uri, you are in business!

>> require "open-uri"
=> true
>> open(A.new)
=> "you opened it!"

Now, I realize that this is far from amazing, but it’s still cool to think that because a lot of ruby code is duck typed really well, you can use it for purposes other than what it is explicitly meant to do.

For the curious, open-uri will cause Kernel#open to accept arguments and a block as well, so feel free to define your open() method in your classes as you please.

So here is a little challenge for those who read this blog… Find something in the standard library that can be used in a different way than it is intended. Post it in the comments here, so people can see just how flexible Ruby really is. :)

AddThis Social Bookmark Button

TRUGhat: Toronto Ruby User’s Group hackathon

TRUGhat is TRUG’s hackathon or codefest. In a hackathon, a group of people get together and will either work toward a common goal, or simply work in a common area on code that interests them. For our first TRUGhat, we have agreed upon a common goal.

During a codefest or hackathon, there’s always lots of snacks available, and it’s common for the perfect developer’s food–pizza, of course–to be delivered.

The goal is for TRUG to have two TRUGhat events a year. Ruby developers of all skill levels will be welcomed.

TRUGhat 2006:1

When?

TRUGhat 2006:1 will be held on 6 May 2006, from 10:00 A.M. to 7:00 P.M.

Since we’re all learning something on this first TRUGhat, we probably won’t get started programming until 11:00 A.M.

Where?

Tucows has generously provided the space and network availability for this event at its offices in Toronto, at 96 Mowat Avenue, one block west of Dufferin, south of King. Transit accessibility is good, with both the King West streetcar and the Dufferin bus passing near the office. Parking is plentiful for those who will be driving. Map

Who?

The Tucows space can handle a total of fifteen people, with thirteen places available. If you’re interested in joining us, please put your name below and join the mailing list. UPDATE: This list is incorrect. Use the TRUG wiki and join with the list at sewm.

What?

The current plan is to implement the functionality of libarchive and possibly libtar for Ruby. The primary goal is pure Ruby support with a secondary goal of Ruby/C bindings so that those who have the requisite libraries can take advantage of the C code for performance reasons.

More?

Some of the details are still being worked out, but Austin Ziegler has already committed to buying pizza for whomever does show up. Check out the mailing list or the TRUGhat wiki page for more information.

AddThis Social Bookmark Button

280 people showed up for Canada on Rails, the sold-out, first ever, Ruby on Rails conference in Vancouver, BC this past weekend.

The talks were superb. And I was really impressed with the way everything turned out, and truely couldn’t have asked for better feedback from the attendees.

Those who attended, may have noticed a few cameras rolling while the presentations were going on. I didn’t get a chance to mention it during the event itself, but there is a DVD in the works that will be released within the next 3 months or so (aiming for RailsConf). The discs will be jam packed with all the media (audio/video/stills/etc) we collected during the two days of talks.

So for all those that missed this event and are interested in getting notified when the DVD is out, sign up for the newsletter on canadaonrails.com and we will be in touch with you the moment more info is available.

If you want to check out some of the photos that were taken during the event, head on over to Flickr.

Thanks again for everyone that made it out, and see you all in Europe, for Italy on Rails this Fall.

UPDATE: If anyone has posted a summary of the Canada on Rails YVR06 Conference, please send a trackback to this post so there is a collection of thoughts people can reference at ease.

Gregory Brown

AddThis Social Bookmark Button

Now, be forewarned my gentle Nuby friend, I am not going to be explaining symbols here. Though the question is asked on a weekly basis on RubyTalk and other places, and the general consensus is “They’re named numbers… they’re handy to work with, and they aren’t the same thing as Strings, so just use ‘em when it feels right”, I am going to point out a simple little pitfall that you might want to be careful with.

If you want some primer reading on Symbols, there are already a few on this blog alone, and many more discussions in the RubyTalk archives. In fact, most of the top links from a google search for “Ruby Symbols” should get you on the right track.

So today’s topic is memory management. Though Ruby’s garbage collection makes it pretty easy for us to not even think of this topic day to day, occasionally, the topic must rear it’s ugly head, If for nothing else, it is to remind us why we took that stupid “Intermediate C Programming” course or it’s equivalant where seemingly innocuous things such as dynamic arrays were potential sources of memory leaks.

In Ruby, you see a lot of Hashes which use Symbols for their keys. It’s mostly because

{ :my => :super, :duper => :hash, :looks => :cooler, :this => :way }
{ "than" => "it", "does" => "this", "way" => "..." }

and because symbols are really fast little deallies to be working with.

If your hash is going to be used internally, you never need to worry about anyone except programmers indexing your data, and if they want a persons[:phone_number] , they can just ask using Symbols. But what if you were using a Hash to store some data accessible via a web form, or a command line application? Then you’d have to convert the Strings to Symbols.

Of course, that is very, very easy. "hello".to_sym happily will generate you a Symbol :hello.

So it’s very tempting to put something like this in your code:

do_something_funky_with(my_hash[some_string.to_sym])

High fives all around and you can happily use Symbols internally and let people type into text boxes or scribble bits of Cuneiform which get translated to strings which then are converted to symbols for indexing and you’re getting at your data as easy as pie. Ruby’s garbage collection will happily do away with those converted strings, won’t it?

The unfortunate answer is no. Symbols are designed so that once they spring into existence, they never die. Not of a natural death, anyway. With sufficient validation and sparse use of these immortal little constructs, no problem will ever arise. However, leave the floodgates open and the flood will come.

Take a look at the memory usage in a simple little irb session I was running:

At start:

sandal@harmonix:~$ pmap 24683 | grep total
 total     5980K

I then run this bit of code.

>> a = "a"
=> "a"
>> 10000.times { a.succ! }
=> 10000
>> a
=> "ntq"

You wouldn’t expect substantial memory growth here and you don’t find any at all:

sandal@harmonix:~$ pmap 24683 | grep total
 total     5980K

A minor change is made. I convert the values to symbols after I iterate to the next letter. But I don’t store the value of this anywhere, so you’d expect it to just disappear peacefully.

>> a = "a"
=> "a"
>> 10000.times { a.succ!.to_sym }
=> 10000
>> a
=> "ntq"

But, alas.. it is not so.

sandal@harmonix:~$ pmap 24683 | grep total
 total     6244K

We’ve grown by 264k! Now this may seem tiny, but imagine this on the end of a long running high volume server process that accepted user input… even potentially that of spambots and malicious Skr1ptk1ddz trying to crack in to set up the l33t35t w4r3z site.

Now we’ve got ourself a memory leak, and that is generally considered A Bad Thing.

This memory doesn’t get released, either. I ran these tests right before I started blogging, and with irb still running and unchanged, running pmap still shows me at exactly 6244K.

If you already have a grasp for symbols and what they are and how they should be used, it’s not very hard to see why this problem is something that’s not really a problem, but just something you need to be careful about. It’s also important to note that symbols get mapped one to one to unique values, and if you call the same symbol again, it’s not going to suck up more memory. This makes them completely safe to use if you just protect yourself a bit.

So that’s your NubyGem for the day… If you’re dealing with user input, it’s probably better not to convert it to symbols. But if you do, be sure to validate before your conversion, to avoid creating something like :some_really_l33t_symbols_that_will_eventually_starve_this_process.

Next time… we’ll get immediate with values. Anyone with a specific question or experience to share might want to email me, because I’m trying to find a good example for this upcoming article.

Gregory Brown

AddThis Social Bookmark Button

Introduction

Over the next few weeks, I will be posting short little blog entries about things that I’ve found myself tripping over when I first learned Ruby. They will be minimal little blurps that will hopefully help new users either understand a trap they’ve fallen into, or help them avoid a trap.

I hope the RubyGems folks forgive me for the terrible pun, but these are meant to be little gems of information for those new to Ruby. If you are an experienced rubyist, these posts will probably bore you, so be warned!

The Hash Initialization Problem

One fairly common need in programming is to set a default value for keys to map to in a hash. For example, if you are dealing with a hash of a bunch of numbers, you might just want a key that isn’t there to map to zero.

There are two different ways you can use the hash constructor to do this. One is to just pass the number in as a parameter, like Hash.new(0) and the other is to use a block such as
Hash.new { |h,k| h[k] = 0 }

Now, in this simple example, these two pieces of code do the same thing from a users perspective. Both result in the ability to get results like this:

>> a[:foo]
=> 0
>> a[:foo] += 1
=> 1
>> a[:foo]
=> 1
>> a[:bar]
=> 0

Now, as a lazy coder who didn’t initially have a strong grasp of blocks when I first started using Ruby, I much prefered the parameter form. However, there is a subtle difference between the two that can be very problematic if you aren’t careful.

The thing that is important to know is that the parameter form will return the same exact object for all the default values. Though the example before used a Fixnum, which is an immediate value, if you use something like… say a string, it’s not so simple. Take a look at the two chunks of code below, and note the difference.

irb(main):001:0> a = Hash.new("")
=> {}
irb(main):002:0> a[:foo]
=> ""
irb(main):003:0> a[:foo] << "bar"
=> "bar"
irb(main):004:0> a[:foo]
=> "bar"
irb(main):005:0> a[:train]
=> "bar"
irb(main):006:0> a = Hash.new { |h,k| h[k] = "" }
=> {}
irb(main):007:0> a[:foo]
=> ""
irb(main):008:0> a[:foo] << "bar"
=> "bar"
irb(main):009:0> a[:foo]
=> "bar"
irb(main):010:0> a[:train]
=> ""

See? The first bit of code shares a common string object, where the second bit creates a new string for each new key which is not mapped to a value. Though you might find the first behavior useful at times, it is usually the case that the second is what is desired, and this is the rule of thumb I go by to keep from getting snagged:

If I am using an immediate value for my default, I tend to use the parameter method. Otherwise, I tend to use the block form, especially when dealing with any type of collection or string.

Anyway, I hope this helps people understand what the two different initializers do and prevents some gotchas. Happy Hacking!

Steve Mallett

AddThis Social Bookmark Button

Despite so many of the Ruby on Rails rock stars developing on the OS X platform there’s little documentation on the production deployment process on OS X Server.

Well, not any more. Luke Burton spells out the process for doing just that on MacDevCenter.

pat eyler

AddThis Social Bookmark Button

A while ago, I posted an article about Rails in a development race. Well the results are in, and although the Rails team didn’t win, the results are encouraging. Their write up of their second place finish can be found here.

Just as a reminder, the Rails team hadn’t done any professional work with Rails at the time of the competition. In fact, in their write up, they talk about learning as they went. They even mention that this was their first time working together.

A couple of statements puzzled me, especially “Because of the limited amount of time we didn’t implement many tests which hurt us a couple of times during the judging. Simple typos yielded syntax errors at runtime.” In my experience, writing tests first speeds things up, and eliminates these kinds of problems. (Especially if you use a tool like autotest.)

I, for one, am excited to see what happens next year.

pat eyler

AddThis Social Bookmark Button

Recently, Sean Carley and I have been hacking on ParseTree as we play with some static analysis. Sean has started writing up some of our adventure.