What is the Difference Between a Proc and a Lambda in Ruby?

Posted by ben on May 11, 2010

The concepts of a Proc and a lambda in Ruby are subtly different and this post aims to try and explain the differences.

Procs and Lambdas

Firstly why do we need Procs and lambdas? In order to answer this you need to understand what a block is in Ruby.

Understanding what a block is?

A block is simply a piece of code, which is usually attached to a method, Proc or lambda. It is important to note that this block of code is NOT an object (yet…), it is code that is defined either within braces {} or within a do end container.

The code in a block is just logic that hasn’t been wrapped into an object yet. When this block is passed to a method and that method has a yield statement then Ruby will wrap that block into a special type of object. That type of object is a Proc object. Once the block becomes a Proc Ruby can use it and the block code ‘comes alive’.

Therefore we need a Proc object in order to handle blocks. The next question is how does a lambda fit in.

A lambda is a type of Proc object, it is almost completely identical to a Proc apart from two differences. This little code snippet shows that a Proc and a lambda are derived from the same superclass, Proc.

  def what_are_lambdas_and_procs
    puts "--- #{__method__} ---"
    lam = lambda { puts 'lam variable assigned a lambda' }
    lam.call
    puts "lam is a class of: #{lam.class.name}"
    puts "lam method count: #{lam.methods.size}"
    puts
    prc = Proc.new { puts 'prc variable assigned a Proc' }
    prc.call
    puts "prc is a class of: #{prc.class.name}"
    puts "prc method count: #{prc.methods.size}"
    ""
  end

This will output:

  --- what_are_lambdas_and_procs ---
  lam variable assigned a lambda
  lam is a class of: Proc
  lam method count: 55

  prc variable assigned a Proc
  prc is a class of: Proc
  prc method count: 55

So what are the subtle differences between Proc and lambda?

As mentioned there are two differences, and these differences are :

  1. in how a Proc/lambda assigns arguments, and
  2. in what happens, when a Proc/lambda calls return within a caller method.

Proc, lambda argument assignment

When a lambda is called with more or less than the required number of arguments Ruby will throw an ArgumentError.

However when a Proc is called with more arguments, no error is thrown and the extra values are simply thrown away. When it is called with less arguments these parameters are simply assigned a value of nil.

These two code snippets demonstrate this:

  def lambda_args
    puts "--- #{__method__} ---"
    lam = lambda { |a, b| puts "lambda with 2 arguments a:#{a}, b:#{b}" }
    lam.call( "first", "second")
    puts "lambda called with three arguments..."
    begin
      lam.call("first", "second", "third")
    rescue
      puts "   ArgumentError: wrong number of arguments (3 for 2)"
    end
    puts "lambda called with no arguments..."
    begin
      lam.call()
    rescue
      puts "   ArgumentError: wrong number of arguments (0 for 2)"
    end
  end

  def proc_args
    puts "--- #{__method__} ---"
    prc = Proc.new { |a, b| puts "Proc with 2 arguments a:#{(a.nil?) ? "nil" : a }, b:#{(b.nil?) ? "nil" : b }" }
    prc.call( "first", "second")
    puts "Proc called with three arguments..."
    prc.call("first", "second", "third")
    puts "Proc called with no arguments..."
    prc.call()
  end

This will output:

  --- lambda_args ---
  lambda with 2 arguments a:first, b:second
  lambda called with three arguments...
     ArgumentError: wrong number of arguments (3 for 2)
  lambda called with no arguments...
     ArgumentError: wrong number of arguments (0 for 2)

  --- proc_args ---
  Proc with 2 arguments a:first, b:second
  Proc called with three arguments...
  Proc with 2 arguments a:first, b:second
  Proc called with no arguments...
  Proc with 2 arguments a:nil, b:nil

Proc and lambda return behaviour

When a lambda returns a value and this lambda is called within a method then method will simply continue it’s execution until it itself returns a value.

However when a Proc returns a value and this Proc is called within a method this containing method will be exited WITHOUT any further execution. This is slightly surprising behaviour, and consequently a Proc should be handled with care.

These two code snippets demonstrate this behaviour:

  def lam_return
    puts "--- #{__method__} ---"
    puts "simple function that calls a lambda and then returns it's own string."
    my_lam = lambda { return 'Lambda has returned' }
    my_lam.call 
    return 'lam_return method string returned'
  end

  def proc_return
    puts "--- #{__method__} ---"
    puts "simple function that calls a Proc, \nBUT instead of returning it's own string returns the Proc's string."
    my_proc = Proc.new { return 'Proc string returned' }
    my_proc.call # this function returns and finishes here
    return 'proc_return method string returned' # the return is never called
  end

This will output the following:

  --- lam_return ---
  simple function that calls a lambda and then returns it's own string.
  lam_return method string returned

  --- proc_return ---
  simple function that calls a Proc, 
  BUT instead of returning it's own string returns the Proc's string.
  Proc string returned

Proc return work around

There is however a very simple work around to avoid a Proc from returning out of it’s caller method. Simply removed the return statement, because Ruby always returns the last line this last line will be returned automatically.

  def proc_return_work_around
    puts "--- #{__method__} ---"
    puts "simple function that calls a Proc, \nhowever the method string still returns."
    my_proc = Proc.new { 'Proc string returned' }
    my_proc.call # this function returns and finishes here
    return "#{__method__} method string returned" # the return is never called
  end

This will output:

  --- proc_return_work_around ---
  simple function that calls a Proc, 
  however the method string still returns.
  proc_return_work_around method string returned

Conclusion

As you have seen there are only two small differences between a Proc and a lambda but these differences have quite surprising behaviours. Therefore following the Ruby principle of “…least surprise”, it is best practice to use lambdas over Procs unless you absolutely need the Proc behaviour.

For more information please see this article: http://en.wikibooks.org/wiki/Ruby_Programming/Syntax/Method_Calls

Create Sinatra Partials The Rails Way 1

Posted by ben on September 25, 2009

This is just a quick post. I’ve been playing around with the Sinatra micro web framework, and have to say that it is excellent. It really is the perfect tool for rapidly creating small and useful Ruby micro-sites.

Being small and lightweight it doesn’t have many of the features of larger frameworks like Ruby on Rails. One of the features I’ve begun to need is the handling of Rails like partials.

Notably I need to pass both local variables and collections to the partial code and have the partials rendered accordingly. I started implementing my own version, and then came across a nice little Github project: Sinatra-Helpers by sbfaulkner.

Anyway here is the code he uses for Sinatra partials:

def haml_partial(name, options = {})
  item_name = name.to_sym
  counter_name = "#{name}_counter".to_sym
  if collection = options.delete(:collection)
    collection.enum_for(:each_with_index).collect do |item,index|
      haml_partial name, options.merge(:locals => {item_name => item, counter_name => index+1})
    end.join
  elsif object = options.delete(:object)
    haml_partial name, options.merge(:locals => {item_name => object, counter_name => nil})
  else
    haml "_#{name}".to_sym, options.merge(:layout => false)
  end
end

You can use his project or if you just need this feature just pop this code into your Sinatra helpers file application_helper.rb:

helpers do

  def partial(name, options = {})
    item_name = name.to_sym
    counter_name = "#{name}_counter".to_sym
    if collection = options.delete(:collection)
      collection.enum_for(:each_with_index).collect do |item, index|
        partial(name, options.merge(:locals => { item_name => item, counter_name => index + 1 }))
      end.join

    elsif object = options.delete(:object)
      partial name, options.merge(:locals => {item_name => object, counter_name => nil})
    else
      haml "_#{name}".to_sym, options.merge(:layout => false)
    end
  end
end

Now you can call the partial from a your page e.g. index.haml

= partial("mypartial", :locals => {:var1 => "value 1", :var2 => "value 2 and so on"})

Create a partial in the same directory as the calling page. Note that this code doesn’t like filenames truncated with a ‘-’, so avoid this if possible. Also like in Rails your partials should start with an underscore. e.g. _mypartial.haml

To access the variable from this partial simply call the local variable name in your code:

%h2 
  This is var1:
  = var1

%p 
  And this is var2:
  = var2

Handling collections, again, is similar to the way Rails handles partial collections. From your page call the partial with a collection such as:

= partial("listitem", :collection => ["item 1", "item 2 and so on"])

Now in the _listitem.haml partial code simply provide the partial name as a variable or the partialname with _counter for the increment number e.g.

%li
  = listitem
  is the 
  = listitem_counter
  in this array

Anyway all pretty basic stuff but I hope it helps the casual Sinatra surfer.

Goodluck.

SproutCore and Web Applications

Posted by ben on August 18, 2008

It’s been a wee while since my last article, which has largely been due to my summer holiday. Anyway I’ve been reading up and experimenting with the SproutCore JavaScript framework.

Its excellent but I wanted to explain why companies and developers should consider using it. So I’ve written an article on my business partner’s web site http://rapidappsgroup.com/content/desktop-web-applications-using-sproutcore/.

Please check it out as it tries to answer a lot of the general questions about web applications and JavaScript frameworks.

BE…

An Almost Fix for Creating RubyGems on Windows 5

Posted by ben on June 25, 2008

Introduction

I wrote this article originally so that I could write command-line apps using Ruby, as I got further and further down the line I realised that what I really wanted to do was create a command-line app using RubyGems. I use both Windows and an Apple Mac and I quickly found myself having problems trying to create RubyGems on Windows.

In this article I try to explain my thought process and the problems I encountered. Unfortunately I had to employ a manual process when trying to package up my project into a tar file, as there isn’t a simple way to do this in Windows (let me know if you have a solution), however everything else seems to work.

What’s a RubyGem?

One of the joys of Ruby is the RubyGems packaging system. It is essentially a tool written in Ruby, for packaging up source code for deployment.

The RubyGems site describes it as follows:

RubyGems is the premier ruby packaging system. It provides:

  • A standard format for destributing Ruby programs and libraries.
  • An easy to use tool for managing the installation of gem packages.
  • A gem server utility for serving gems from any machine where RubyGems is installed.

Why should I create a RubyGem?

Maybe a better question should be when should I package my code up into a RubyGem. Obviously there are no hard and fast rules but if you are going to share your code libraries with others or even with other applications of yours, you should think about using a gem.

Now you might think that you don’t want to make all your code public on RubyForge, and there are very good reason not to publish every gem, so you don’t have to. RubyGems comes with its own local gem server so you can create your own gem library and share it amoung your other Ruby applications.

This is really quite useful, you get the power of RubyGems without the commitment and maintenance work of making your code OpenSource. Plus at any point in time you can then make it OpenSource, and live off the joy of the Ruby community :) .

The reason I wrote this article is because I wanted to create a simple command-line application using Ruby. I went through a number of steps before realising that the best way was to use RubyGems.

I started by creating my own command-line structure and then found this great article by Todd Werth. He has a single Ruby file that you just replace various sections and viola you have a very simple command-line app. But it wasn’t quite what I wanted. I didn’t want to have to type:

./my_super_app 'some params'

I wanted to type:

my_super_app 'some params'

I also wanted the structure of the application to follow a standard structure and I didn’t want to put ‘.’ into my path, for security reasons. Dr Nic came to the rescue with a couple of excellent articles describing how to create gems using newgem and specifically command-line apps as gems.

Installing newgem on Windows

To install newgem on Windows use the RubyGems install method.

gem install newgem

This will install the gem and its dependencies. However one of its dependencies is the Hoe gem, and there is a slight issue using it on Windows.

What is hoe?

Hoe is a compliment to rake, it was created by Ryan Davis and provides rake tasks for testing, packaging, and releasing RubyGems. Geoffrey Grosenbach has a nice tutorial for using hoe and also describes how to create a project structure using the sow task.

Hoe uses a .hoerc file for configuration, and this file should reside in the user’s home directory, something like:

C:\Documents and Settings\MyUserName

An example .hoerc file should look like the one below. Please note that this is a YAML file and if you copy it from here remember to follow the indentation convention:

---
publish_on_announce: false
exclude: !ruby/regexp/tmp$|CVS|\.svn|_darcs|\.git|log$|local/.*\.rb$|Makefile|.*\.o$|.*\.bundle$|.*\.so$|.*\.dll$/ 
str: ""
"@taguri": tag:ruby.yaml.org,2002:regexp/tmp$|CVS|\.svn|_darcs|\.git|log$|local/.*\.rb$|Makefile|.*\.o$|.*\.bundle$|.*\.so$|.*\.dll$/
blogs:
- user: user
  url: url
  extra_headers:
    mt_convert_breaks: markdown
  blog_id: blog_id
  password: password

On Unix systems there is a shortcut to the user’s home directory which is ‘~’ and on Windows this isn’t a shortcut. Windows however does have an environment variable HOMEPATH which will point to the user’s home directory. The problem is that the Hoe gem code uses ‘~’ in its hoe.rb file and this causes problems for Windows users.

Patching the hoe.rb file

OK, be brave, lets tweak the hoe.rb file so that it will work on the Windows platform. The Hoe gem hoe.rb file can be found in the following directory (assuming you installed Ruby to the standard location):

C:\ruby\lib\ruby\gems\1.8\gems\hoe-1.6.0\lib

To make it work for Windows PCs you will need to modify this file with the following changes.

Locate the define_tasks method:

def define_tasks # :nodoc:
  def with_config # :nodoc:
    rc = File.expand_path("~/.hoerc")
    exists = File.exist? rc
    config = exists ? YAML.load_file(rc) : {}
    yield(config, rc)
  end

And add a new method above it such as this, and modify the line rc = File.expand_path(“~/.hoerc”) as below:

def get_home_dir
  home_file_path = "~/"
  home_file_path = "#{ENV['HOMEPATH']}\\" if WINDOZE
  home_file_path
end

def define_tasks # :nodoc:
 def with_config # :nodoc:
   rc = File.expand_path(get_home_dir + '.hoerc')
   exists = File.exist? rc
   config = exists ? YAML.load_file(rc) : {}
   yield(config, rc)
 end

Finally you will need to locate and change the task :config_hoe so that it reads:

"signing_key_file" => "#{get_home_dir}.gem/gem-private_key.pem",
"signing_cert_file" => "#{get_home_dir}.gem/gem-public_cert.pem",

If all has gone correctly save this file and you are now ready to create a RubyGem.

Creating a basic RubyGem

Using the newgem RubyGem enter the following command at the command prompt:

newgem my_app -b greetings -T rspec -W

This will create a my_app subdirectory, with a command-line command app called greetings located in the bin directory. It will use the testing framework RSpec and finally will not generate the RubyForge web site code. This is assuming you don’t want to relese your code as OpenSource. The output will be something like this:

     create
     create  config
     create  doc
     create  lib
     create  script
     ... blah ...
     create  script/console
     create  script/console.cmd
     create  Manifest.txt
     readme  readme
Important
=========

* Open config/hoe.rb
* Update missing details (gem description, dependent gems, etc.)

If you want to add RSpec Stories to this project there is a useful command-line generator to do this. First navigate into the root of you new project app directory, in this case my_app. Now execute the generate script:

ruby script/generate install_rspec_stories

You should then get the following output:

  create  stories/steps
  create  stories/steps/my_app_steps.rb
  create  stories/sell_my_app.story
  create  stories/all.rb

Modify your greetings command so that it does something. Do this by editing the file located here:

my_app/bin/greetings

Open up this file and at the very end, add some code such as this, and save the file:

# do stuff
puts 'Greetings the world is my oyster!'

Packaging caveat

As mentioned in the begining of this article I couldn’t use rake to tar this project up for deployment to RubyForge. The reason is that rake makes a Unix platform dependent call to tar the package using a Ruby task file packagetask.rb located:

C:\ruby\lib\ruby\gems\1.8\gems\rake-0.8.1\lib\rake 

This means that on Windows you will have to manually tar this file.

However you can still create the gem using the rake task, and a gem file my_app-0.0.1.gem, will appear in the pkg directory:

rake gem

This new RubyGem can now be installed by using the gem install commands:

gem install pkg/my_app-0.0.1.gem

You should get the following output:

For more information on my_app, see http://my_app.rubyforge.org

NOTE: Change this information in PostInstall.txt
You can also delete it if you don't want it.


Successfully installed my_app, version 0.0.1
Installing ri documentation for my_app-0.0.1...
Installing RDoc documentation for my_app-0.0.1...

Finally you should now be able to execute your command-line command in the command prompt, simply by typing:

greetings

I hope this is useful and helps with your understanding of how RubyGems work, specifically on Windows, also please jot down some comments if you have any ideas or suggestions.

Links

Here is a list of useful RubyGems links:

Understanding RSpec Stories – a Tutorial 15

Posted by ben on June 10, 2008

When I initially started writing this RSpec guide I had planned to cover both traditional RSpec Specs and the new Stories feature, however the guide quickly became to big so I decided to focus purely on RSpec Ruby Stories, as opposed to RSpec Rails Stories.

Why Unit Testing?

Every pragmatic programmer tells us that we should be writing unit tests, but are they really that important? Well unfortunately they are. Unit test ensure that we write good quality code mitigating the number of bugs we introduce into a software system. However more than that, they help us think about the problem from different perspectives which leads to further insights and gradually makes the domain problems more manageable.

Unit testing is especially important when the language you use is interpreted. With compiled languages like C and C++ for example, the compiler picks up on compile time errors, however with interpreted languages like Ruby, Perl and Python there is no compiler and bugs can easily be introduced which won’t be uncovered until the interpreter executes that branch of the code.

Traditionally tests have been written using a Unit Test framework like JUnit, NUnit or RUnit. However it is easy to spending a lot of time writing tests that test every unit of code in your software system, what RSPec does is to provide a subtle shift of focus from Unit testing to Behaviour testing or Behaviour Driven Development (BDD). By focusing on the behaviour of the system it helps clarify in our minds what the system should actually be doing. It also means that our energy is directed at more ‘useful’ tests. Useful tests, cover what the system should be doing and build in enough redundancy so that it should be easy to refactor our code without having to re-write every test.

What is RSpec? Give me some background.

RSpec is a Behavioural Driven Development (BDD) tool, originally created by Dave Astels and Steven Baker.

However David Chelimsky is really the gatekeeper of the RSpec project, and because it is an OpenSource project you can find the code on the GitHub RSpec Repository. If you would like to use Git to ‘check out’ a copy of the source code see my article: Installing Git on Apple OSX

RSpec is really two projects merged into one. The RSpec project pages describes these merged projects as:

  • a Story Framework for describing behaviour at the application level
  • a Spec Framework for describing behaviour at the object level

Dan North created rbehave which is the Story framework and he describes it as:

rbehave is a framework for defining and executing application requirements. Using the vocabulary of behaviour-driven development, you define a feature in terms of a Story with Scenarios that describe how the feature behaves. Using a minimum of syntax (a few “quotes” mostly), this becomes an executable and self-describing requirements document.

The Spec framework was created by David Chelimsky, and is orientated at testing the behaviour of objects in your system.

By encompassing two frameworks RSpec equips a programmer with a thorough set of testing tools, allowing you to think about your software problem from a number of perspectives.

What is an RSpec Story?

Dan North has a good article about what a Story actually is, but here is a quick summary. A Story describes the functionality of a specific software feature, and it describes it in a way that is easy to understand from the point of view of a client. In fact a story should be thought of as a conversation between a client and a programmer over some feature of the software.
As this story unfolds the programmer guides the client by prompting different Scenarios and using specific words Given, When and Then, to capture the essence of the systems behaviour.

A typical story template will take this structure but does not necessarily have to:

Title (one line describing the story)

Narrative:
As a [role]
I want [feature]
So that [benefit]

Acceptance Criteria: (presented as Scenarios)

Scenario 1: Title
Given [context]
  And [some more context]...
When  [event]
Then  [outcome]
  And [another outcome]...

Scenario 2: ...

The key points to a story are:

  • Title – this should describe an activity or action
  • Narrative – should include a role, feature and a benefit. “As a [role] I want [feature] so that [benefit]“
  • Scenario – describes what is different in the story. NB you can have a number of different scenarios.
  • Scenario: Given/Events/Outcomes – Given [some context], When [I do something], Then [this happens]. It is important to use the Given, When, Then language.
  • Givens should define all of, and no more than, the required context
  • Event should describe the feature

RSpec actually has four implementations of a Story, which given the sporadic documentation can lead to much confusion. Essentially from an RSpec point of view a Story consists of three parts:

  • the Story
  • Steps that the Story undertakes
  • Components to be tested, described by the Story

Installing RSpec on Apple OSX

The quickest and easiest way to install RSpec is to use Ruby gems. In the Apple Terminal.app command prompt enter the following command, and install RSpec as root:

sudo gem install -r rspec

It should be noted that according to how you have setup your Mac, you may need to use sudo to install this gem. If all goes well you should get output such as this:

Bulk updating Gem source index for: http://gems.rubyforge.org/
Successfully installed rspec-1.1.4
1 gem installed
Installing ri documentation for rspec-1.1.4...
Installing RDoc documentation for rspec-1.1.4...

Finally if you are an Apple user and are using TextMate you might want to read my article on how to install the TextMate RSpec bundle.

How to Create an RSpec Story

The simplest type of RSpec Story consists of a single file that contains both the Story and the executable Steps, all you need to do is require the library or class you wish to test.
For example if we wish to use RSpec to test an Account object you would create your library file such as account.rb:

class Account
  attr_accessor :balance

  def initialize(amount)
    @balance = amount
  end

  def transfer_to(account, amount)
    @balance = @balance - amount.to_f
    account.balance = account.balance.to_f + amount.to_f
  end
end

Now create your RSpec Story and save this file as account_story.rb with the following content. Note that on Apple OSX systems you seem to have to require the rubygems library:

require 'rubygems'
require 'spec'
require 'spec/story'
require 'account'

Story "transfer to cash account",
%(As a savings account holder
  I want to transfer money from my savings account
  So that I can get cash easily from an ATM) do

  Scenario "savings account is in credit" do
    Given "my savings account balance is", 100 do |balance|
      @savings_account = Account.new(balance)
    end
    And "my cash account balance is", 10 do |balance|
      @cash_account = Account.new(balance)
    end
    When "I transfer", 20 do |amount|
      @savings_account.transfer_to(@cash_account, amount)
    end
    Then "my savings account balance should be", 80 do |expected_amount|
      @savings_account.balance.should == expected_amount
    end
    And "my cash account balance should be", 30 do |expected_amount|
      @cash_account.balance.should == expected_amount
    end
  end

  Scenario "savings account is overdrawn" do
    Given "my savings account balance is", -20
    And "my cash account balance is", 10
    When "I transfer", 20
    Then "my savings account balance should be", -40
    And "my cash account balance should be", 30
  end
end

Note that although you did not explicitly define the code in the Steps of the second Scenario the RSpec framework uses the Given, When, Then methods defined in the first Scenario. In fact if you look at the Story and think of it as a plain old Ruby code file you gradually understand what is happening. The file defines a number of methods Story, Scenario, Given, When and Then, note that when RSpec analyses this Story file it parses the two Scenarios and is able to match the Given, When, Then methods with the other Scenario.

RSpec Plain Text Stories

This previous example gives us the basic understanding of how a Story works and is structured, but what about the RSpec plain text stories, how do I create one and how are they structured?

The goal of a Plain Text Story is to extract the Steps into a separate file and write the Story in such a way that it looks just like plain text with no Ruby code. In fact it is possible to name the Story file such that it does not even have the .rb file extension.

However by extracting the Steps from the Story we will require a helper file to bind the Story to the Steps. Therefore a plain text Story file will consist of four parts:

  • the Story
  • Steps that the Story undertakes
  • Components to be tested, described by the Story
  • Helper file to bind the Story to the Steps

There isn’t any hard and fast rules about how you should structure the file system with respect to Stories and Steps, however best practice seems to describe a stories directory and a steps subdirectory.

stories +
        + steps

Story files are created without the .rb file extension and are placed in the stories directory and consequently a Step file is created with the same name as the Story file, but with _step.rb extension. Helper files can be put in the stories directory, and should have the same name as the story file but this time with the .rb file extension.

Create a Story file with the following file name, bank

This is a story about an transferring money between bank accounts. 
Note that the text up here above the Story: declaration won't be 
processed, so you can write whatever you wish!

Story: transfer to cash account
  As a savings account holder
  I want to transfer money from my savings account
  So that I can get cash easily from an ATM

  Scenario: savings account is in credit
    Given my savings account balance is '100'
    And my cash account balance is '10'
    When I transfer '20'
    Then my savings account balance should be '80'

  Scenario: savings account is overdrawn
    Given my savings account balance is '-20'
    And my cash account balance is '10'
    When I transfer '20'
    Then my savings account balance should be '-40'

Now create a steps file with the following name and place it in the steps directory, bank_steps.rb

require 'rubygems'
require 'spec/story'
require 'spec/story/extensions/main'
require File.join(File.dirname(__FILE__), "../account")

steps_for(:bank) do
  Given("my savings account balance is '$savings'") do |savings|
    @savings_account ||= Account.new(savings)
  end
end

steps_for(:bank) do
  Given("my cash account balance is '$cash'") do |cash|
    @cash_account ||= Account.new(cash)
  end
end

steps_for(:bank) do
  When("I transfer '$amount'")  do |amount|
     @savings_account.transfer_to(@cash_account, amount)
  end
end

steps_for(:bank) do
  Then("my savings account balance should be '$expected_amount'") do |expected_amount| 
     @savings_account.balance.should == expected_amount.to_f
  end
end

The helper file by default is given the same name as the Story file but this time with the .rb extension. Here is an example of such a file, called bank.rb.

#!/usr/bin/env ruby
require 'rubygems'
require 'spec'
require 'spec/story/runner'
require 'account'

# require all the steps files so that we can link the story to them
Dir[File.join(File.dirname(__FILE__), "steps/*.rb")].each do |file|
  require file
end

# execute the steps in the steps file
with_steps_for :bank do
  run File.expand_path(__FILE__).gsub(".rb","")
end

Now to run this story all you have to do is from the Apple Terminal.app navigate to the stories directory and execute the following Ruby command:

ruby bank.rb

If all is successful you should see the following output:

requiring files ./steps/addition_steps.rb
requiring files ./steps/bank_steps.rb
Running 2 scenarios

Story: transfer to cash account

  As a savings account holder
  I want to transfer money from my savings account
  So that I can get cash easily from an ATM

  Scenario: savings account is in credit

    Given my savings account balance is '100'
    And my cash account balance is '10'

    When I transfer '20'

    Then my savings account balance should be '80'

  Scenario: savings account is overdrawn

    Given my savings account balance is '-20'
    And my cash account balance is '10'

    When I transfer '20'

    Then my savings account balance should be '-40'

2 scenarios: 2 succeeded, 0 failed, 0 pending

I hope this gives you a good introduction and a basis for understanding how RSpec Stories work. Finally here are a list of links which may help you further:

Installing Sqlite3 on Windows for Rails 48

Posted by ben on June 04, 2008

The Windows version of Ruby on Rails does not ship with the Sqlite3 database, even though the database.yaml configuration file is preconfigured to use Sqlite.

This is a how to guide on how to install Sqlite3 on your Windows PC. This article assumes that you already have Ruby and Ruby on Rails installed on your PC.

First you will need to download two files from the Sqlite web site http://www.sqlite.org/download.html:

    sqlite-3_5_9.zip (214.32 KiB)
    A command-line program for accessing and modifing SQLite databases. 
    See the documentation for additional information.

    sqlitedll-3_5_9.zip (213.17 KiB)
    This is a DLL of the SQLite library without the TCL bindings. 
    The only external dependency is MSVCRT.DLL.

The first file is the Sqlite command line program used for modifing the Sqlite database. You may or may not use this.

The second file is the Windows DLL library file and Ruby uses this when Rails makes Sqlite database calls.

When both these ZIP files have been extracted you should have the following files:

  • sqlite3.exe
  • sqlite3.def
  • sqlite3.dll

Copy these file to the bin directory of your Ruby installation, if you followed the default Ruby installation it will be located here:

    C:\ruby\bin

Now that you have the Sqlite3 files installed you need to tell Ruby how to use them. To do this you need to download the Ruby bindings for Sqlite3.
Fortunately this is easy to do, using Ruby gems. Simply at the command prompt type the following command:

    gem install sqlite3-ruby

You will now need to tell Gems which version you need as you will be presented with the following output:

    Bulk updating Gem source index for: http://gems.rubyforge.org
    Select which gem to install for your platform (i386-mswin32)
     1. sqlite3-ruby 1.2.2 (mswin32)
     2. sqlite3-ruby 1.2.2 (ruby)
     3. sqlite3-ruby 1.2.1 (mswin32)
     4. sqlite3-ruby 1.2.1 (ruby)
     5. Skip this gem
     6. Cancel installation
    >_

Please select option 1, sqlite3-ruby 1.2.2 (mswin32). All being successful you will get some output like this:

    Successfully installed sqlite3-ruby-1.2.2-mswin32
    Installing ri documentation for sqlite3-ruby-1.2.2-mswin32...
    Installing RDoc documentation for sqlite3-ruby-1.2.2-mswin32...

If you are using Rails 2+ you should be able to run the following rake tasks from your Rails application directory. For example say you created a Rails application located here: C:\MyApp you should be able to execute:

    C:\MyApp>rake db:create
    or
    C:\MyApp>rake db:migrate

Hope this is useful.

Installing the Latest RSpec TextMate Bundle 14

Posted by ben on June 04, 2008

If you are using TextMate on your Apple Mac you may wish to download the RSpec TextMate Bundle and install it. The TextMate bundle can be found in the RSpec Git repository. In your Terminal.app enter the following commands. Please note that you will need Git installed on your Apple Mac in order to do this, please see my article Installing Git on Apple OSX on how to do this:

cd /Applications/TextMate.app/Contents/SharedSupport/Bundles
git clone git://github.com/dchelimsky/rspec-tmbundle.git RSpec.tmbundle

You should get output like this in your Terminal window:

Initialized empty Git repository in /Applications/TextMate.app/Contents/SharedSupport/Bundles/RSpec.tmbundle/.git/
remote: Counting objects: 46199, done.
remote: Compressing objects: 100% (10514/10514), done.
Indexing 46199 objects...
remote: Total 46199 (delta 33049), reused 46199 (delta 33049)
 100% (46199/46199) done
Resolving 33049 deltas...
 100% (33049/33049) done

Now you will need to reload your TextMate Bundle Editor for this new bundle to be applied. In TextMate select the following menu items and button:

  Bundles > Bundle Editor > Reload Bundles

If you ever need to get a more uptodate version of the RSpec.tmbundle then simply navigate to your TextMate Bundle directory and use Git to pull the latest version down to your machine. Don’t forget to reload your bundles once this has been done. To pull the latest version from the Git hub use this command:

git pull

For older instructions on how to do this see Robby on Rails – RSpec Bundle for TextMate

Installing Git on Apple OSX 3

Posted by ben on June 03, 2008

Git is a version control system like CVS and Subversion. It was created by Linus Torvalds and used for Linux. It has recently been adopted by the Ruby community and many of the new Ruby and Ruby on Rails projects now use it. One of the reason’s for it’s popularity amongst the Ruby community is because of github. In there own words:

GitHub is the easiest (and prettiest) way to participate in that collaboration: fork projects, send pull requests, monitor development, all with ease.

How to quickly setup Git on Apple OSX

The simplest way to install Git on Apple OSX (for Intel Mac) is to use this pre-packaged installer: http://metastatic.org/text/Concern/2007/08/18/git-package-for-mac-os-x/, however if you have a PowerPC Mac or wish to use an alternative installation method, try the information on this site: http://bc.tech.coop/blog/070827.html

Launch the installer, and accept the license agreements. Once the installer has completed open up OSX Terminal.app (cmd + space, then type terminal), and type git at the command prompt, if all has been successful you should see something like this:

usage: git [--version] [--exec-path[=GIT_EXEC_PATH]] [-p|--paginate|--no-pager] [--bare] [--git-dir=GIT_DIR] [--work-tree=GIT_WORK_TREE] [--help] COMMAND [ARGS]

The most commonly used git commands are:
   add           Add file contents to the index
   apply         Apply a patch on a git index file and a working tree
   archive       Create an archive of files from a named tree
   bisect        Find the change that introduced a bug by binary search
   branch        List, create, or delete branches
   checkout      Checkout and switch to a branch

...  continued with more commands ...

Configuring Git

One of the interesting things about Git is that it can be configured from the command line. Therefore the first thing to do is setup your user details so that when you add changes it uses your details. This web site has some very good instructions on how to get up and running using Git very quickly http://git.or.cz/course/svn.html.

To configure your Git user details enter the following at the command prompt:

git config --global user.name "Your Name Comes Here"
git config --global user.email you@yourdomain.example.com

Clone / Checkout the RSpec Git Repository

Now you should be able to clone (Subversion calls this checkout) a repository so that you can view the source code. To do this enter the following command at the command prompt. I intend to checkout the RSpec repository from github:

git clone git://github.com/dchelimsky/rspec.git

All being well you should see output in your Terminal like this:

Initialized empty Git repository in /Users/myname/my_repositories/rspec/.git/
remote: Counting objects: 46810, done.
Compressing objects: 100% (10646/10646), done.)   
Indexing 46810 objects...
remote: Total 46810 (delta 33521), reused 46810 (delta 33521)
 100% (46810/46810) done
Resolving 33521 deltas...
 100% (33521/33521) done

Now you should have all the source code in your new repository.