1. Install the new DLR
First up install .Net Framework 4.0 (I have Beta1) - this has the new Dynamic Language Runtime (DLR) that makes things like IronRuby and IronPython possible.
2. Get the latest IronRuby release
Next we need to get IronRuby as a zip. Extract it to say d:\ironruby-0.9.0 Add the path to the bin folder to your PATH environment variable to avoiding lengthy paths. Drop to a command shell, type 'ir' to invoke the interactive IronRuby console. Type something simple to test if it works. It should.
>>>puts "Hello IronRuby"
3. Dragons ahead. Use diversion
But I hit a snag with this version of IronRuby, which had A BUG.
- So I had to get the latest (8 Sep 2009 master to be precise) version of the source from the github repository to overcome that. You can download it as a zip or use git as you prefer. I got the zip
ironruby-ironruby-90cdda82fd60f4b7e6d7d940501c586d55954466.zip (Could have used a shorter name) - Extract it to say d:\ir-src
I hit a few path-too-long errors during extraction. Just keep skipping them. I think it's because of the rather large alphanumeric string which is the name of the top-level folder. - Once extracted, navigate to D:\ir-src\ironruby-ironruby-90cdda82fd60f4b7e6d7d940501c586d55954466\Merlin\Main\Languages\Ruby
and open Ruby.sln in VS2008 (I have Dev Edition of VSTS.. Although it should build in VS Express Editions as per the docs - I couldn't get the solution to open in it.)
Build Solution. At the end of it you should find the built binaries in
D:\ir-src\ironruby-ironruby-90cdda82fd60f4b7e6d7d940501c586d55954466\Merlin\Main\bin\Debug - Rename that directory with the huge name to something like "ir".
- Copy all built binaries and overwrite the ones from the 0.9.0 release's bin folder i.e. D:\ironruby-0.9.0\bin.
- Open ir.exe.config in the same folder and update the Library paths element to the proper paths to folders within your ir-src folder. 'Handle with extreme care' or you'll lose hours chasing error messages. It should read
Path#1 - D:\ir-src\ir\Merlin\Main\Languages\ (NOT D:\ir-src\ir\Merlin\External.LCA_RESTRICTED\Languages)
Path#2 & #3 - D:\ir-src\ir\Merlin\External.LCA_RESTRICTED
My xml looks like<set language="Ruby" option="LibraryPaths"
value="D:\ir-src\ir\Merlin\Main\Languages\Ruby\libs\;D:\ir-src\ir\Merlin\External.LCA_RESTRICTED
\Languages\Ruby\redist-libs\ruby\site_ruby\1.8\;D:\ir-src\ir\Merlin\External.LCA_RESTRICTED\Lang
uages\Ruby\redist-libs\ruby\1.8\" />
4. Wrapper script ICucumber
Lastly we need a wrapper script to invoke cucumber with Ironruby. Create a file called icucumber.bat under your Ruby bin folder i.e. D:\Ruby\bin\icucumber.bat with the following text.
REM Update with appropriate values for GEM_PATH, Ruby bin and the path to ir.exe
@ECHO OFF
REM This is to tell IronRuby where to find gems.
SET GEM_PATH=d:\ruby\lib\ruby\gems\1.8
"D:\ironruby-0.9.0\bin\ir.exe" -D -X:ExceptionDetail "d:\ruby\bin\cucumber" %*
5. Back to our example from the previous two posts.
The .feature file stays unchanged.
Delete c:\cukes\dot_net_features\support\BowlingGame.rb ; since we're going to implement the same in C# this time around as
c:\cukes\dot_net_features\support\BowlingGame.cs
namespace CukesDemo
{
public class BowlingGame
{
public void roll(int pins_knocked_down)
{
Score += pins_knocked_down;
}
public int Score
{
get; set;
}
public bool Over
{
get { return false; }
}
}
}
Also create a small batch file to compile it to a DLL (Assumes csharp compiler is on the PATH).
c:\cukes\dot_net_features\support\Compile.bat
IF EXIST bin GOTO COMPILE
MKDIR bin
:COMPILE
csc /t:library /out:bin/BowlingGame.dll bowling_game.cs
Finally back to our step definitions to check the glue. Four changes needed - explained in comments.
cukes\dot_net_features\step_definitions\bowling_game_steps.rb
# CHANGE 1 : Add bin folder to load-path
$:.unshift(File.dirname(__FILE__) + '/../support/bin')
# CHANGE 2 : Get BowlingGame.dll
require 'BowlingGame'
Given /^I am starting a new game$/ do
# CHANGE 3 : Use Namespace::ClassName.new
@game = CukesDemo::BowlingGame.new
end
When /^I roll (\d+) gutter balls$/ do |count|
count.to_i.times{
@game.roll(0)
}
end
Then /^the score should be (\d+)$/ do |expected_score|
@game.score.should == expected_score.to_i
end
Then /^the game should be over$/ do
# CHANGE 4 : be_over passes even if Over returns false. Don't know what is the equiv of over?
in .Net
#~ @game.should be_over == true
@game.over.should == true
end
When /^my rolls are (.*)$/ do |rolls|
rolls.split(' ').each{|roll|
@game.roll(roll.to_i)
}
end
Now for the grand finale, run Cucumber to verify our .Net DLL via IronRuby !!!
HTH