25th April - 1st May 2005

Ruby Weekly News is a summary of the week’s activity on the ruby-talk mailing list / the comp.lang.ruby newsgroup, brought to you by Tim Sutherland.

Articles and Announcements

  • Ishii-san died
  • daigo announced to RedHanded “Masaru Ishii, a great Japanese Rubyist, died at the rail disaster, where 106 people died. He introduced RubyUnit with the author, Suketa-san. It was the predecessor of the current Test::Unit in Ruby 1.8.”

    “I love unit testing. I pay his last respects.”

User Group News

  • Omaha, NE Ruby User's Group First Meeting
  • Blaine Buxton announced a new user group – for Omaha, Nebraska, U.S.

    The first meeting was on the second of May 2005.

  • Seattle.rb Meeting Tonight
  • Ryan Davis announced the April 28th 2005 meeting of the Seattle.rb user group.

    The plan was for Ryan to talk about profilers, then demonstrate some “very very cool stuff”. “Eric will also be demonstrating his code metric analyzer for SVN.”

  • tulsa.rb
  • Tim Morgan and others were looking for other Rubyists in Tulsa, Oklahoma in the U.S., to “create a Tulsa Ruby Brigade.”

    (Interestingly, they were using 43 Things to co-ordinate.)

Quote of the Week

Threads

Ruby and IDE

A thread discussing Ruby IDEs popped up again.

Much of it compared graphical IDEs like Eclipse with Emacs and vi(m).

Austin Ziegler had some interesting comments; “Type-based code completion is the very thing that will NOT work in Ruby. It *can't*. The best you can get is a “statistically likely” code completion that may break under a lot of circumstances.”

“IMO, a good Ruby IDE will support debugging; have ri and rdoc information easily and quickly available, and that’s about it.”

determining when inside 'class << self'

Ara.T.Howard wondered if it was possible to implement a method inside_metaclass? so that
class << foo
  p inside_metaclass? #=> true
end
p inside_metaclass? #=> false

(Note: There is no consensus that these things should be called “metaclasses”. A variety of names were discussed in a thread covered last week, Article: Seeing Metaclasses Clearly.)

Mark Hubbart noticed that “metaclasses have a peculiar inspect value”, and provided an implementation of inside_metaclass? that parses the inspect output. “This code is breakable, but probably only if you try to”.

Carlos came up with

self.is_a?(Class) && !self.ancestors.include?(self)
George Ogata gave a C implementation that uses
FL_TEST(self, FL_SINGLETON)

The above is a robust solution, unlike the previous suggestions which can be broken by someone e.g. changing Class#inspect or Module#ancestors.

Robert Klemme wrote a pure-Ruby implementation that attempts to call self.allocate, and if it fails, checks the exception message to see if it is “can’t create instance of virtual class”.

Along the way, Mark Hubbart had discovered that if you dup a metaclass, you gain the ability to instantiate it.

Mark found this surprising, and George Ogata explained that “duping a metaclass doesn’t really return a metaclass. That is, it is no longer a thing tied to one object; it’s just a free-roaming class like any other.”

“What you may have noticed is that #dup-ing a class doesn’t copy it’s singleton-class-ness, but #clone-ing does. Replace your `dup’ with `clone’, and you’ll get an error, since you can’t instantiate the clone”.

There was further discussion of this behaviour.

Hash as Checklist

basi had a Hash like:
h = {
  "one" => true,
  "two" => true,
  "three" => true,
  "four" => true,
  "five" => true
} 

“But typing the dummy value “true” is a waste of effort, and there’s an ugliness in there. Is there a better way to design a simple checklist?”

Assaph Mehr gave the answer:
require 'set'
s = Set.new %w{one two three four}
s.member? 'one'   # true
s.member? 'seven' # false

Days in month

Dan Fitzpatrick wanted to know whether there is a method in Date or Time to tell you what the last day of the month is.

The answer was “no”, but Ken Kunz posted

class Date
  def days_in_month
    Date.civil(year, month, -1).day
  end
end

BLOG: zenprofile (& berkeley) & zenoptimize

Ryan Davis blogged about a couple of tools he was developing.

The first was zenprofile, a new profiler which “tries to strike a balance between code readability and speed”.

The profiler bundled with Ruby 1.8 (profile.rb) is very slow. On the other hand, it’s implementation is simple – 65 lines of pure Ruby code. (It uses set_trace_func to wrap all method calls.)

Shugo Maeda’s ruby-prof is a newer library that is much faster – thirty times faster in some cases. It is also more complex – 701 lines of code which is a mixture of C and Ruby.

Ryan attempted to rewrite ruby-prof to be pure Ruby code, but found that it was using too many Ruby internals for this to be easy. Instead, he ported the 65-line profile.rb to C. (Using RubyInline.) The result was 182 lines of C code that was almost as fast as Shugo’s (perhaps two times slower).

The second tool was zenoptimizer. It uses ruby2c, RubyInline and “a lightweight version of zenprofile” to create a library that will automatically optimise performance critical sections of code in your program when you use ruby -rzenoptimizer your_prog.rb.

Rails + Amrita, Rails + XTemplate?

Greg McIntyre asked “Has anybody thought about putting Amrita/XTemplate support in Rails?”

Jeff Barczewski said that DHH had added templating support to Rails, based on work from Jamis Buck. (As far as he could recall.)

This provides hooks for invoking whatever templating engine you wish to use.

KDE 'applets' in Ruby?

Phil Tomson recalled an announcement some months ago about writing KDE applets in Ruby.

It turned out that that wasn’t really what he wanted, but Richard Dale gave a good example for adding an icon to the system tray. He also showed how to start konsole with a DCOP call – all in Ruby.

The examples used Korundum, the Ruby bindings for the KDE libraries.

Building Ruby extensions on OS X Tiger

Richard Kilmer forwarded a message from Tony Arnold explaining how to build native extensions for the Ruby shipped with Mac OS X Tiger. (It involved editing rbconfig.rb.) Chad Fowler gave the following alternative solution:
sudo gem install fixrbconfig
sudo fixrbconfig 

There were some comments as to what the exact values of various flags like LIBRUBY_LDSHARED should be.

Chad indicated he may release another version of his “fixer upper gem” to improve on these.

Reporting Ruby Bugs

Michael Schonberg wanted to know where he should go to report Ruby bugs.

Tim Hunter said one option was on RubyForge – “In the upper-right corner of the page, under “Support/Links” is the link “Report a Ruby Bug””.

ruby and COM

Joel VanderWerf asked “What’s the best way to work with a COM interface from ruby?” “Is COM functionality built into the win32ole lib that ships with ruby now?”

Adelle Hartley: “Yes.”

ActiveRecord auto populated columns

Brandon Campbell knew of some fields that would be added automatically by ActiveRecord (which is used by Rails) - created_on and updated_by.

Where could he find the full list of fields that are added?

Chris McGrath pointed out the MagicFieldNames page on the Rails wiki.

Rails on JRuby?

John Wells asked about the possibility of using Rails with JRuby (an implementation of Ruby in Java).

Thomas E Enebo said that JRuby as yet lacks much socket support, so wouldn’t be able to run Rails as-is. He also thought about the possibility of changing Rails to run as a Java servlet.

In a different direction, Lyndon Samson used IKVM.NET to turn the JRuby jar into a .NET CLR executable. He could then run Ruby code under .NET. (It was like a Ruby interpreter written in .NET.)

Cloning into an object

Eric Mahurin asked how he could copy one object into another object (shallow copy). “It would be nice to handle the case where the objects have a different class, but I would at least like to know how to do it when the classes are the same.”

As an example, he wanted to be able to write

dest = Object.new # or String.new if necessary
source = "hello world" 
destid = dest.id

source.clone_into(dest)

dest             -> "hello world" 
dest.id==destid  -> true
dest.class       -> String 
George Ogata said that the evil.rb project defines an Object#become method, which does what is desired. It is modelled after the Smalltalk method of the same name.

Robert Klemme suggested simply copying the instance variables from the source object into the destination. He noted however that this wouldn’t work well for objects defined in C, such as String and Array, because these have state which is only visible from the C level.

Eric tried out Object#become, and found it did what he wanted. “It looks like it might be made standard in ruby at some point.” “Anybody know when/if become will be made standard?”

nobu replied, “When: time_t wrap arounds (where sizeof(time_t) == 8), perhaps. If: Matz.become(Evil) executed successfully.”

library for doing html escaping...

Sean T Allen was searching on RubyForge for a library to escape the HTML in a String. (e.g. turn “&” to “&amp;”.) He couldn’t find it, and it was driving him crazy!

Phlip said that this functionality is included with Ruby – it’s in the CGI library.

require 'cgi'
s = CGI::escapeHTML('foo&bar')
puts(s)

Performance of SyncEnumerator

Matt Mower profiled some of his code, and found that the following code was taking up a lot of time (particularly in calls to Kernel.callcc).

# Re-formatted from Matt's original code
def euclidean_distance(vector)
  Math.sqrt(
    SyncEnumerator.new(self, vector).collect { |i, j|
      (i-j) ** 2
    }.inject(0) { |s, v| s + v }
  )
end

“However I’m now wondering if the magic which makes SyncEnumerator work is of the expensive kind (I’m assuming this is where all the Kernel#cc calls are coming from as well).”

SyncEnumerator is used to take two (or more) “internal iterators” (iterators that use yield, for example Array#each) and iterate over both of them at the same time.

Ken Kunz gave a link to a RedHanded post Enumerate Side-by-side with SyncEnumerator. The comments replying to the post suggest the use of Enumerable#zip, which does a similar thing to SyncEnumerator but performs much better.

Matt’s code converted to use zip might look like

  def euclidean_distance(vector)
    sum = self.zip(vector) { |i, j|
      (i-j) ** 2
    }.inject(0) { |s, v| s + v }
    Math.sqrt(sum)
  end

The reason for the big difference is that SyncEnumerator uses continuations (which are implemented inefficiently in the current Ruby interpreter), while Enumerable#zip converts its arguments into Arrays. (Which is a problem when the argument is an infinite or large sequence.)

Matt himself re-implemented his method in a similar way to:
def euclidean_distance2(vector)
  sum = 0
  each_with_index { |x, i|
    y = vector[i]
    sum += (x-y) ** 2
  }
  Math.sqrt(sum)
end
He concluded with “It’s a pity about the slowness of continuations since we agree that SyncEnumerator provides a very neat solution. As you observed maybe Rite/YARV will improve the situation. We can but hope!”

Starting and stopping a child process in Windows

In a thread about dealing with processes on Windows, nobu posted some code which did pid = spawn("cmd.exe").

spawn is a new feature of the Ruby 1.9 development branch. It is a portable way of launching a program and getting a Process back that you can control.

Per-project RubyGem stats

Tom Copeland: “One nice thing about RubyForge is that you can see how many times your project has been downloaded. But downloads via RubyGems don’t get put in the RubyForge database, so they don’t show up in the charts. This is sad.”

He then gave a link that provides download stats for the top 500 RubyGems in the current month.

Lyle Johnson “Huh. What are these “Rake” and “Rails” gems that are getting so many downloads?” (“P.S. That was a joke, people.”)

RubyGems and RDoc

James Edward Gray II asked if you could “set RDoc options, like main and title, in a Gem specification?”

Assaph Mehr said that it was indeed possible, via spec.rdoc_options. He also gave a link to the GemspecReference page from the RubyGems wiki that explains this.

New Releases

Kwartz-ruby 2.0.0 released - Ruby on Rails support

kwatch announced Kwartz-ruby 2.0.0, a templating system for multiple programming languages (Ruby, PHP, Java). It now has Rails support.

Su Doku 0.0.2 (beta2) in Ruby

Dr Balwinder S Dheeman posted an update to his implementation of the Su Doku puzzle game, using an ANSI console UI.

RMagick 1.8.0

Tim Hunter released a new version of RMagick, the Ruby bindings for the ImageMagick and GraphicsMagick image processing libraries.

It now incorporates RVG (Ruby Vector Graphics), which was previously a separate library. “RVG is a library for drawing 2D graphics with an API based on the SVG specification.”

“RVG would be a good library to use if you’re writing an application that needs to programmatically generate drawings, such as a charting application, especially if you need to export your drawings in multiple resolutions (web, print, etc.) and multiple image formats.”

Arachno Ruby IDE 0.5.5 for Linux

Lothar Scholz declared ready the latest Linux version of the Arachno Ruby IDE.

“You can download a time unlimited trial version”.

Daniel Berger asked if there was any chance of a Solaris version (SPARC), but Lothar said “Sorry, no chance for sparc hardware support.”

One-Click Ruby Installer 182-15 for Windows

Curt Hibbs released the One-Click Ruby Installer for Windows based on Ruby 1.8.2 final.

“It mostly upgrades included extensions and applications to their most recent versions.” The fxri program was also added.

“fxri combines a nice interactive search interface to the Ruby documentation along with an interactive ruby session (irb)—all wrapped up in a nice GUI shell.”

sys-proctable 0.7.0

Daniel Berger, “After many moons”, announced sys-proctable 0.7.0, a Ruby library for getting information on processes.

The Win32 version has been completely revamped. There have also been changes to the other supported platforms (Linux, Solaris, FreeBSD).

foxGUIb 0.4 (for FXRuby 1.2.6)

Henon put out a development release of foxGUIb, an interactive builder for graphical interfaces that use the FOX toolkit. The major change is that it now works with fox12.

Classifier 1.2 with Bayesian and NEW LSI classification

Lucas Carlson, with the help of David Fayram, added LSI classification to his Classifier library.

HighLine 0.2.0

James Edward Gray II released a version of the solution he wrote for the HighLine Ruby Quiz.

“HighLine was designed to ease the tedious tasks of doing [line-oriented] console input”.