SameShirtEveryDay.com

Personal blog of the one called Alex Gorbatchev, from Toronto, Canada.
follow me on Twitter

Quick 3rdRail overview in screenshots

Posted on September 17th, 2007 by Alex Gorbatchev. In Rails, Ruby. No comments yet...

Code insight for a local class?

Here’s a quick 3rdRail overview in screenshots (flickr required).

CodeGear releases 3rdRail, a Ruby and Rails IDE

Posted on September 17th, 2007 by Alex Gorbatchev. In Rails, Ruby. 3 comments!

Code insight for a local class?

CodeGear released 3rdRail this morning. A few highlights:

  • Full Rails project support.
  • Rails specific refactoring, ie renaming a method in a controller will update all references as well as link_to and rename the associated view file.
  • Console with command completion.
  • Integrated Gecko browser with request monitor, DOM source, CSS and JavaScript

You can watch a screen cast here and download a trial for Windows, Unix and OSX here.

Here’s a quick 3rdRail overview in screenshots (flickr required).

Distributed RDoc and a DRb tip

Posted on September 16th, 2007 by Alex Gorbatchev. In Ruby. No comments yet...

First distributed Ruby attempts

Noobkit is powered at its core by RDoc. Obviously it’s not real time, far from it. In fact, full refresh of Noobkit’s database which includes 26 Gems together with Rails and Ruby Core takes about 25 minutes on a single Core 2 Duo 2.4Ghz with 4GB ram box.

About 20 minutes of that time is taken by RDoc parsing the source code. This is what I’m currently working on making better. I have used this article as a starting point and wrote a client/server script on top of customized RDoc.

The end result is having 4 threads running across 2 boxes each parsing a separate source file fed to it by the server.

This being the first time I’ve worked with DRb or Ruby threads in general, one thing that kept annoying me was inability to break with Ctrl+C when using DRb.thread.join. I’ve devised a simple waiting loop instead:

def wait_for_it(&block)
  return if block.nil?
  loop do
    sleep(0.1)
    break unless yield
  end
end

# ...do DRb magic...

# This will stall the current thread until DRb thread is finished.
wait_for_it {  DRb.thread.alive? }

The same function can also be used to insure that all workers have finished their job before doing something else:

# When a worked is done, it's added back to the queue
wait_for_it { @available_workers.size != $workers.size }

Improve your RSpec with simple custom matchers

Posted on September 15th, 2007 by Alex Gorbatchev. In Ruby, Testing. No comments yet...

RSpec is great:

it "should be its own root" do
  @node.root.should == @node
end

it "should add a child" do
  @node.children.size.should == 0

  child = @klass.new

  @node.add_child(child)
  @node.children.size.should == 1

  child.parent.should == @node
  child.root.should == @node
end

Looks beautiful. However, look at line #2. What would the output be if that test fails? The message would be something like this: "expected #{@target.inspect} to the same as #{@expected.inspect}".

Inspecting an object like a tree node could result in multiple pages worth of data and the output basically becomes unreadable if there’s an array of objects.

This problem could easily be fixed with a custom expectation matcher.

module BeTheSameAsMatcher
  class BeTheSameAs
    def initialize(expected)
      @expected = expected
    end

    def matches?(target)
      @target = target
      @target.eql?(@expected)
    end

    def failure_message
      "expected <#{to_string(@target)}> to " +
      "the same as <#{to_string(@expected)}>"
    end

    def negative_failure_message
      "expected <#{to_string(@target)}> not to " +
      "be the same as <#{to_string(@expected)}>"
    end

    # Returns string representation of an object.
    def to_string(value)
      # indicate a nil
      if value.nil?
        'nil'
      end

      # join arrays
      if value.class == Array
        return value.join(", ")
      end

      # otherwise return to_s() instead of inspect()
      return value.to_s
    end
  end

  # Actual matcher that is exposed.
  def be_the_same_as(expected)
    BeTheSameAs.new(expected)
  end
end

As you can see, methods failure_message and negative_failure_message define our error messages. Instead of default inspect call, I’m using a custom to_string method which will either return a join for an Array or to_s for any other object.

To make this available in all of your specs, the module needs to be added in your `spec_helper.rb` like so:

require 'spec/be_the_same_as'

Spec::Runner.configure do |config|
  config.include(BeTheSameAsMatcher)
end

After this, we can change our line #2 from the original script to this:

it "should be its own root" do
  @node.root.should be_the_same_as(@node)
end

Learning Ruby: A little trick to overriding parameterless constructors

Posted on September 14th, 2007 by Alex Gorbatchev. In Ruby. 2 comments!

After almost 8 months of working with Ruby, it still offers something new every day. Here’s a tricky part about overriding a constructor without any arguments:

class A
  def initialize
    @foo = 123
  end
end

class B < A
  def initialize(special_argument)
    # This call will result in "wrong number of arguments (1 for 0)"
    # exception because Ruby automatically passes all arguments.
    super
    # ... the same as ...
    super(*args)

    # Special case of calling super class' constructor without
    # argument - you MUST include parentheses to indicate
    # that you aren't passing any arguments.
    super()
  end
end

Obviously, I would’ve known that if I read the manual, but it would be too easy.

home
Subscribe to this blog Follow me on Twitter My bookmarks on Delicious My photography on Flickr