{ |one, step, back| } 106 to 115 of 182 articles WikiSyndicate: full/short

Builder Objects   24 Aug 04
[ print link all ]

Builder Objects

Sometimes you get good ideas from other languages.
I’ve had fun with this little package over the past few days. The Groovy language was the big buzz at the No Fluff, Just Stuff conference (see NoFluff2004) a few weeks ago. So I’ve been looking at some groovy stuff recently (and I did a Groovy presentation at our local Java group), and I stumbled across the builder library that comes with Groovy. "What a cool idea" I thought and saw that it would be easy to implement in Ruby. So here is the result.

The basic idea is that you create a builder object and then send it messages. It responds to the messages by building up a data structure based on those messages.

Ack, it’s easy to see it in action than to describe it. For example, the following code …

  builder = Builder::XmlMarkup.new("", 2)
  puts builder.person {
    name("jim")
    phone("555-1234", "local"=>"yes")
    address("Cincinnati")
  }

will print …

  <person>
    <name>jim</name>
    <phone local="yes">555-1234</phone>
    <address>Cincinnati</address>
  </person>

So, an XML Markup object produces XML markup. Not very surprising until you think about the methods send to the builder. Where is the person method defined? Or the name method?

Actually, they are not defined anywhere. Instead we have defined a generic method_missing method and handles any undefined method and adds the name of the method to the XML markup we are building. In addition we use code blocks to capture the nested nature of the XML. The result is a very natural way to programmatically generate XML markup.

And it goes beyond just markup. If you use Bulder::XmlEvents instead of Builder::XmlMarkup, the same syntax will generate SAX-like events instead of markup. Or you can use a DOM builder to generate a DOM object tree (I haven’t implemented the DOM version, but it should be straightforward).

There are a couple of "gotchas" with this approach that you should be aware of …

  • Within the builder code blocks, any method call with an implicit object target needs to be sent to our builder. To achieve this, the code blocks are evaluated with instance_eval which changes the value of self to be the builder. This is OK until you want to call a method in the calling object. Since self is no longer the calling object, you have to explicitly provide the caller. Builders make this easy by setting the +@self+ instance variable to the caller.
  • What happens when you need an XML tag that has the same name as an existing method name (e.g. id )? The builder objects handle this by inheriting from BlankSlate. In addition, all the implementation methods in a builder begin with an underscore, which makes them unlikely candidates for XML tags.

Because Builder objects lack the normal methods that most objects have makes working with them rather interesting. Consider the following irb session where we create a builder object and let irb try to display it (by sending it an inspect message):

    >> x = Builder::XmlMarkup.new
    => <inspect/>
    >> x
    => <inspect/><inspect/>
    >> x.to_s
    => "<inspect/><inspect/><to_s/>"
    >> x.methods
    => "<inspect/><inspect/><to_s/><methods/>"
    >> x + 5
    => "<inspect/><inspect/><to_s/><methods/><+>5</+>"
    >> x
    => <inspect/><inspect/><to_s/><methods/><+>5</+><inspect/>

Every time we send a message to the builder it records the name of the message. In a way, the builder has become a trace object, recording all the messages send to it. Weird.

Finally, consider this last example. Suppose we have a method that uses a builder to generate an RSS feed. Here is the method in part ..

  def generate_rss(builder, a_title, a_link, items)
    builder.rss("version" => "0.91") {
      channel {
        title a_title
        link  a_link
        # ... code missing ...
        items.each do |it|
          item {
           title it.title
           link  it.link
           description it.description
          }
        end
      }
    }
  end

Now a single method (generate_rss) can generate XML markup text, a DOM tree or a series of SAX events, all depending on what kind of builder object you pass to the function. That’s slightly cool.

As I mentioned, I got this idea from the Groovy language. Groovy has some other builders as well. For example there is an Ant task builder that integrates with ant. It is a very flexible technique that really shows off the power of a dynamic language.

Note: You can find the Builder object code in the RubyGem builder-0.1.1.gem available on the RubyGem server on RubyForge.


RSS Feed for GemWatch Available   21 Aug 04
[ print link all ]
I’ve setup a simple RSS feed for newly released gems. The same file that builds the GemWatch HTML file now also builds an RSS 2.0 file. You can find the feed at http://onestepback.org/gemwatch.rss.

This is the first hand-built RSS feed I’ve put together, so let me know if I’ve screwed something up.

By the way, the idea from the feed came from the Dave's Article at the Pragmatic Automation web site


No Fluff, Just Stuff Conference 2004   09 Aug 04
[ print link all ]
I just got back from the Southern Ohio Java Symposium, a.k.a. the No Fluff, Just Stuff conference in Cincinnati. Wow, what a great weekend. I blogged in detail about the conference last year (NoFluffJustStuffFriday), so I’m not going to go into detail about each session. Jay Zimmerman takes this conference all over the states and targets a lot of cities that might not otherwise have a lot of opportunities for technical conferences. If No Fluff, Just Stuff comes around to your city, grab your team and attend. It will be worth your time.

A couple of themes emerged from the conference. Aspect Oriented Programming may finally be coming of age. I first heard of AOP about 4 years ago. This year, there seemed to be more substance behind the buzz. We shall see.

Another theme was the the strong belief among the speakers that although Groovy is still very much in its infancy, it has a strong possibility become very significant in the next few years. If you haven’t heard of Groovy, it is a dynamic scripting language built on top of the JVM. Unlike other JVM languages such as Jython and JRuby, Groovy is designed to work closely with Java and especially the Java libraries. A brief look at Groovy reveals a lot of similarities with Ruby. I’ll be looking at Groovy in more detail.

I’ve got a couple ideas for blog entries inspired by the conference and I’ll post them here in time.

RubyConf.new(2004) is Taking Registrations   08 Aug 04
[ print link all ]
The 2004 International Ruby Conference is now open for registration. Not only that, but the first 50 people who register for the conference will receive a free copy of the second edition of the Programming Ruby book (a.k.a. the PickAxe book) by Thomas and Hunt. See the announcement here.

The program agenda is looking pretty good. I’m talking about RubyGems this year (what else!). I’m especially excited to see that David Heinemeier Hansson will be there and he will be talking about Ruby on Rails which has been getting a lot of air time recently.

The Conference is relatively inexpensive (only $200 for the conference fees) and it’s a great time to meet a lot of Rubyists all at once. The conference is in the Washington DC area (Chantilly, VA), so it is accessible to a large portion of the east coast.

If you are at all interested in Ruby, I urge to to come and meet with us! You can register here.

Update!

It has just been announced that Brad Cox, the inventor of Objective-C will be giving the Keynote speech at the conference.


Helen is Famous   05 Aug 04
[ print link all ]
I came home the other day and my wife announces that she is now famous and that her picture can be found on the internet.

It turns out that she is featured on the local school district's web site where she is a library aide. The picture was taken during one of the school’s book promotions. (Helen is the one dressed up as the Cat-in-the-Hat.)

Here’s the picture …

Reading: Pragmatic Project Automation   30 Jul 04
[ print link all ]
I’m currenly reading Mike Clark’s "Pragmatic Project Automation". I purchased it last week after reading the online PDF of chapter 3 where Mike goes through the steps of setting up CruiseControl. Just using that chapter allowed me to setup CruiseControl for our current project at work. I figured if one chapter was that helpful, getting the whole book is a must.

I really like the book. I’m a big believer in automating all that I can, that is part of the motivation behind the creation of Rake. Mike provides a lot of great ideas and I can’t wait to try them out. (BTW, Rake gets a footnote mention on page 40, Woo Hoo!).

The book is targeted at the mainstream Java audience, so it talks a lot about ant and Cruise Control. Ruby and non-Java scripting languages are mentioned only in passing, but this is reasonable given the size and scope of the book. Mike says that he wants to encourage non-Java scripting and that the www.pragmaticautomation.com website will feature Ruby whenever he can.

And true to his word, today he posted a stakeout script that runs his unit tests whenever a file changes. Check it out.

Oh, and check out the book too.


Braces Vs Do/End   30 Jul 04
[ print link all ]
The big remaining question on Ruby coding style is: When should you used { } for blocks, and when should you use do/end?

Blocks in Ruby may be written with brace delimeters or do/end delimiters. There is a subtle difference in precedence between the two versions, but for most work the two are identical.

So which way do you go?

Some folk use { } for one-liners and do/end for multi-liners. Others stick exclusively to either { } or do/end. I tried all of the above, but was never really satisified with any of the guidelines.

Here is the guideline I use now:

  • Use { } for blocks that return values
  • Use do / end for blocks that are executed for side effects

This has the advantage of using the choice of block delimiter to convey a little extra information. Here’s some examples.

  # block used only for side effect
  list.each do |item| puts item end

  # Block used to return test value
  list.find { |item| item > 10 }

  # Block value used to build new value
  list.collect { |item| "-r" + item  }

Of course, if precedenence makes a difference, use the type of block that makes sense. This is just a guideline after all.

But I have found the distinction to be useful.


50+ Gems Available   09 Jul 04
[ print link all ]
More than 50 packages have been released as a RubyGem at this point. I’ve added a Gem Watch sidebar to my blog so you can watch as the new gems become available.

If you are considering releasing your Ruby project as a gem, you might want to see this (or this if you are using Rake).

Anyone want to make a guess when we will hit 100 gems?


RubyGems 0.7.0 has been Released   09 Jul 04
[ print link all ]
Updates to this site have been rather sporatic recently. Part of the reason is RubyGems version 0.7.0. I’ve been heavily involved with this version for the past few weeks and I’m happy to say it is available now in the expected locations (e.g. RubyForge).

The biggest change to RubyGems is the command structure. We now follow a cvs-like command structure where gem is the main command and install, build, etc are subcommands. For example, it install the latest version of rake, use the following command:

  gem install rake

Options are now defind on individual subcommands and the whole structure is much easier to learn and understand. In addition, the help system knows about individual commands and all the options for each command.

As you can guess, I’m quite excited about the latest version. I hope you download it and give it a tryout.

BTW, if you use Rake to build RubyGems, you will want to grab the latest version (rake-0.4.2) that supports rubygems-0.7.0.


Rake Version 0.4.0 is Out   20 Jun 04
[ print link all ]
This version has some minor changes and bug fixes. Fixes include a better way of determining file time stamps that doesn’t give problems on Windows machines.

The biggest change is that FileList are now "load on demand". When you define a file list, e.g.

   PKGFILES = FileList['**/*.rb', 'test/*']
   PKGFILES.exclude(/^temp/)

The file list just records the include and exclude patterns. Later, when you do …

  PKGFILES.each { |filename| ... }

the file list will actually go out and read the file system to find the matching files. The thought is that searching the file system is a rather expensive operation and if you never actually use the file list, then it is wasted time. By building the file list only when it is needed will make rake startup time a bit faster.

If you are having trouble starting with rake, I wrote up a QuickStartExample showing off some of the features of rake.

What is Rake?

Rake is a make-like utility written entirely in Ruby. It allows to you specify build target and actions, with the action being standard Ruby code.

Download

You can get Rake from rubyforge. If you have rubygems installed, then all you need to do is …

  gem -i rake

If you have a very recent version of rubygems (i.e. from CVS), then the —gen-rdoc option finally produces a decent rendition of the Rake documentation locally.

 

Formatted: 30-Aug-08 05:24
Feedback: jim@weirichhouse.org