tags:

views:

43

answers:

2

I want to iterate an array inside a Ruby heredoc.

<<-BLOCK
Feature: User logs in
  In order to post content
  As an user
  I want to log in

<< Here i want to iterate scenarios >>
BLOCK

"scenarios" is an array I want to loop. For each element I want to print out:

Scenario: #{scenario}
  Given
  When
  Then

So for example if "scenarios" contains:

scenarios[0] = "User successfully logs in"
scenarios[1] = "User failed to log in"

I want the heredoc string to be:

<<-BLOCK
Feature: #{feature}
  In order to #{in_order_to}
  As #{as}
  I want #{i_want}

Scenario: User successfully logs in
  Given
  When
  And

Scenarios: User failed to log in
  Given
  When
  And
BLOCK

How do I do iterate inside a Ruby heredoc?

+3  A: 

You can do it but I'm not sure it is the most readable approach:

s = <<-BLOCK
Feature: User logs in
  In order to post content
  As an user
  I want to log in

#{scenarios.map{|x|
<<-INNERBLOCK
Scenario: #{x}
  Given
  When
  Then
INNERBLOCK
}}

BLOCK
Mark Byers
Why does it defeats the purpose of heredocs? Isn't it ok to be able to have dynamic data inside heredocs?
never_had_a_name
Btw. that didn't work cause \n was interpreted as text and not new line.
never_had_a_name
Weird. I still got the \n. Here is what the script and file looks like: http://pastie.org/1150945
never_had_a_name
@ajsie: That looks right to me. Try using `puts` or `print` on an element of the list to see the real value of the string.
Mark Byers
+1  A: 

You could use ERB. It would be cleaner and not that much more code:

require 'erb'
s = ERB.new(<<-BLOCK).result(binding)
Feature: User logs in
  In order to post content
  As an user
  I want to log in

<% scenarios.map do |x| %>
  Scenario: <%= x %>
  Given
  When
  Then
<% end %>
BLOCK

The first line might look weird, so I'll break it down

s = ERB.new(<<-BLOCK).result(binding)

ERB.new creates a new erb template with the passed string as its content. <<-BLOCK is a heredoc that says take the heredoc value that follows and sub it into the expression. result(binding) Evaluates the template in the current context(binding being the context of the current evaluation).

From there you can easily extract your templates into files as they get bigger.

More about Ruby's heredocs by James Edward Gray II

BaroqueBobcat
this is a better solution, IMHO
rampion