{ |one, step, back| } 113 to 122 of 184 articles Syndicate: full/short

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.



comments

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.



comments

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.



comments

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?



comments

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.


comments

When Clocks Go Bad   11 Jun 04
[ print link all ]
Message ruby-talk:103140 on the ruby talk mailing list mentioned problems with the sleep command interacting in strange ways with setting the clock. That reminded me of this story.

Way back when, I used to work on a data acquisition system that used an IRIG clock reader to timestamp our data samples. An IRIG clock works by reading a signal that sends the time once every second. Between the second ticks, the clock reader would interpolate the time down to the millisecnod level. This allows you to have several clocks on different systems all synchronized to the same clock signal.

Our system had to take a sample every 20 milliseconds, so every cycle we would calculate the time of the next cycle. When the current data cycle was done, we would just wait until that next scheduled time arrived to start the next cycle.

An IRIG clock reader is an interesting device. Normally it works really well, but occasionally (especially if there is noise on the clock signal line) it will misread the time signal. One particular reader we were using tended to misread a couple of bits in the minutes data with the result that for one second, the clock reader would add 30 minutes to the real time. When the next clock signal arrived a second later, the reader would start reporting the correct time again.

Jumping ahead was no problem. Our software just used the reported time and continued to schedule data cycles. However, when the clock jumped backwards, the next data cycle was suddenly scheduled for 30 minutes in the future. The result was that our system mysteriously stopped dead for 30 minutes and then just as mysteriously restarted as if nothing happened.

Time is a strange concept in computer programs. It is difficult to know what the exact time is while executing. Consider the following lines of code …

   t = Time.now                      # Line 1
   puts "The Current Time is: #{t}"  # Line 2

One would think that line 2 will print the current time. And most of the time we would be correct. But suppose I pressed the suspend button on my laptop between line 1 and line 2. It might be hours (or days) before line 2 prints out its now "out-of-date" time message.

When you are dealing with times in the millisecond range, there are all kinds of things that will pause your program from one line to the next. Interrupts, page faults, and time slicing all interact in interesting ways to make the concept of "time" in a program something of a challenge.

It wasn’t hard to fix our cycle scheduler to be well behaved, even in the face of uncertain time. And I learned a new respect for time in the process.


comments

Ruby in five E's   31 May 04
[ print link all ]
I’ve been listening to David Heinemeier Hansson talk on the "Ruby on Rails" project (download the talk here). I really like his summary of Ruby slide which he calls "Ruby in five E’s".

I’ll reproduce his summary here:

  • Everything is an object
      5.times do print "hello world".capitalize end
    
  • Elegant blocks gives inline power
      db.select_all(sql).inject([]) do |objects, row|
        objects << instantiate(row)
      end
    
  • Exploring with reflection
  • Extending at runtime (even standard lib!)
  • Extensive standard library
    • XML, Test/Unit, Distributed Ruby, XML-RPC, WEBrick


comments

Starting with a Blank Slate   21 May 04
[ print link all ]
Here’s a quick Ruby tip. All Ruby classes ultimately inherit from the Object class. This means that every object gets about 40 methods from the Object class without doing anything extra.

Sometimes, however, you don’t want to start with all those methods. I’m thinking of proxy classes that use method_missing to forward messages to another object. Methods defined by Object (actually Kernel, but lets not worry about that) will not be forwarded because they are not missing in the proxy.

This is easy to fix. Create a BlankSlate class like this …

  class BlankSlate
    instance_methods.each { |m| undef_method m unless m =~ /^__/ }
  end

BlankSlate is a class with no instance methods except for __send__ and __id__.

Now we can create a proxy object by inheriting from BlankSlate

  class Proxy < BlankSlate
    def initialize(obj)
      @obj = obj
    end
    def method_missing(sym, *args, &block)
      puts "Sending #{sym}(#{args.join(',')}) to obj"
      @obj.__send__(sym, *args, &block)
    end
  end

Now, try this with the proxy object:

  n = Proxy.new(1)
  puts (n+5)
  puts "1.id = #{1.id}"
  puts "n.id = #{n.id}"
  puts "n.__id__ = #{n.__id__}"

Here’s the output:

  $ ruby blankslatedemo.rb
  Sending +(5) to obj
  6
  1.id = 3
  Sending id() to obj
  n.id = 3
  n.__id__ = 537806934


comments

Miller on Mock Objects   07 May 04
[ print link all ]
Charles Miller reminds us that there are two reasons for using mock objects.
  1. To create an environment where the object under test can live.
  2. To test that the object under test correctly modifies the environment.

Each use requires a slightly different API (#1 sytle APIs tend to be more flexible than style #2). I’ve used both styles of APIs in the past (and had been frustrated trying to use a style #2 API in a style #1 situation), but I hadn’t connected the differences with the reason for the differences before.


comments

RubyGems 0.3.0 Release   07 May 04
[ print link all ]
This is a bit late (but Hey! I’ve been busy). Chad Fowler has a good writeup on the new features in the latest RubyGems alpha release. We’ve put a lot of effort into this project and it is looking pretty good. This version is fairly feature complete, but we expect some do some tuning and adjustments. Check it out and provide some feedback.
comments

 

Formatted: 14-Oct-08 02:53
Feedback: jim@weirichhouse.org