[rspec-users] passing a hash in stories

Ben Mabey ben at benmabey.com
Fri Aug 8 13:43:06 EDT 2008

Jonathan Linowes wrote:
> Hi,
> Anyone have code you could share that lets you pass a hash in plain 
> text stories,
> for example
> Then I fill out form with name: Jon, email: jon at mail.com, age: 9
> passes in a hash { 'name' => 'Jon', 'emal' => 'jon at mail.com', 'age' => 
> '9' }
> _______________________________________________
> rspec-users mailing list
> rspec-users at rubyforge.org
> http://rubyforge.org/mailman/listinfo/rspec-users
You can do this, and I have done it in the past, but I wouldn't 
recommend it.  Their are a couple of reasons why I would discourage it.  
The first is that by just posting a hash to the form's URL (like you 
would do in a controller spec) you are not verifying the existence of 
the form fields and thereby skipping the view layer of the stack.  You 
can get around this by also checking the markup for the form fields like 
you would in a view spec.  However, doing this becomes very tedious.  A 
much better solution exists and that is webrat.  Webrat offers a very 
nice interface that ends up verifying the existence of the form fields 
and doing the post for you.  If you haven't looked into webrat then I 
would highly recommend it.[1]

The other disadvantage of what you are doing is that you might be 
placing too much information in your stories.  The danger of this is 
that you might end up with ugly stories with a lot of noise that end up 
drowning out the real 'signal' of the story.  Additionally, every time 
you add a field to the form you will have to change the story.  See my 
post about the different styles of writing styles to see an example of 
how you might rewrite it. [2]

That said, I don't know your exact situation and what you are trying to 
do may very well be the best approach to it.  So, the answer to your 
real question would be something like:

  # Pass the params as such: ISBN: '0967539854' and comment: 'I love 
this book' and rating: '4'
  # this matcher will post to the resourcese default create action
  When "$actor submits $a_or_an $resource with $attributes" do |actor, 
a_or_an, resource, attributes|
    post_via_redirect "/#{resource.downcase.pluralize}", 
{resource.downcase => attributes.to_hash_from_story}

class String
  # Coverts a string found in the steps into a hash.  Example:
  # ISBN: '0967539854' and comment: 'I love this book' and rating: '4'
  #   => {"rating"=>"4", "isbn"=>"0967539854", "comment"=>"I love this 
  def to_hash_from_story
    self.split(/, and |, /).inject({}){ |hash_so_far, key_value|
                                              key, value = 
key_value.split(":").map{ |v| v.strip.gsub(" ","_")}
hash_so_far.merge(key.downcase => value.gsub("'",""))

To reiterate, I really do not like the pattern above.  I started out 
doing stories like that ran into many problems with it.  In short I 
think step reuse is overrated.

I hope that helps,


More information about the rspec-users mailing list