6

What's the best approach for ignoring some lines when reading/parsing a file (using Ruby)?

I'm trying to parse just the Scenarios from a Cucumber .feature file and would like to skip lines that doesn't start with the words Scenario/Given/When/Then/And/But.

The code below works but it's ridiculous, so I'm looking for a smart solution :)

File.open(file).each_line do |line|
  line.chomp!
  next if line.empty? 
  next if line.include? "#"
  next if line.include? "Feature" 
  next if line.include? "In order" 
  next if line.include? "As a" 
  next if line.include? "I want"
orde
  • 5,233
  • 6
  • 31
  • 33
user2253130
  • 589
  • 2
  • 5
  • 14
  • You might want to look at using a custom Cucumber formatter: https://github.com/cucumber/cucumber/wiki/Custom-Formatters – Andy Waite Apr 15 '13 at 18:03

5 Answers5

6

You could do it like this:

a = ["#","Feature","In order","As a","I want"]   
File.open(file).each_line do |line|
  line.chomp!
  next if line.empty? || a.any? { |a| line =~ /#{a}/ }
end
fmendez
  • 7,250
  • 5
  • 36
  • 35
5

The start_with? method accepts multiple arguments:

File.open(file).each_line do |line|
  next unless line.start_with? 'Scenario', 'Given', 'When', 'Then', 'And', 'But'
  # do something with line.
end
steenslag
  • 79,051
  • 16
  • 138
  • 171
  • @squiguy did I misunderstood this? "skip lines that doesn't start with the words Scenario/Given/When/Then/And/But." – steenslag Apr 14 '13 at 00:03
  • I guess he is contradicting himself then. Looks different from what is in his script. – squiguy Apr 14 '13 at 00:33
  • You're right steenslag: skip lines that doesn't start with the words Scenario/Given/When/Then. In the example I just shown the solution that I found to ignore the header of my .feature file. Anyway, thanks for your input. – user2253130 Apr 14 '13 at 16:57
1

Use a Regular Expression for Compactness

You can replace most of your current loop with a single regular expression that uses alternation. You might also want to use String#chomp! as part of your conditional expression. For example:

File.open(file).each do |line|
  next if line.chomp! =~ /^$|#|Feature|In order|As a|I want/
  # something else
end

This reduces your block by six lines of code. Whether or not you find this alternative easier to read, it is certainly shorter and a bit more idiomatic. Your mileage may vary.

Todd A. Jacobs
  • 81,402
  • 15
  • 141
  • 199
  • You might also find `next unless line.strip! =~ /^\s*(Scenario|Given|When|Then|And|But)/` a more reliable construct, but the expression in my original answer is closer to what you say already works for you. – Todd A. Jacobs Apr 14 '13 at 05:53
0

That's not that much help, but well, you might use array intersection for less code.

words = ["#", "Feature", "In order", "As a", "I want"]

File.open(file).each_line do |line|
  line.chomp!
  next if line.empty? || !(line.split & words).empty?
konole
  • 766
  • 4
  • 8
0

Use the abstract method refctoring method! You could employ what ever technique ,clever or not-so-clever ,in the abstracted method.

File.open(file).each_line do |line|
         line.chomp!
         next if ignore(line)
end

def ignore line
#do whatever you like here, clever or straightforward. 
#All the techniques others has posted could be applied here
end
pierrotlefou
  • 39,805
  • 37
  • 135
  • 175