I have the scenario below
When (/^ I select two files/) do |arg1,arg2|
end
I don't want to repeat code when I select seven files. Is there a way I can loop through arg1,arg2. The same code should work when I pass 5 / 7 arguments.
When (/^ I select files/) do |arg1,arg2, arg3,arg4|
Loop through args
do what ever you want....
end
Yes your regex should read,
When(/^I select "2" files$/) do |num|
num.to_i
<whatever else>
end
Or use a table and pass the name of the file to select
| test.text |
| apples.doc|
Ets
Had you tried browswer.all('a').each ?
You can use xpath too broswer.xpath('//a'), or something like browser.xpath("//div[#id='divid'//a").
Related
I have a step that can be like this:
Then I 'eat' all food except
| Bread |
Then I 'drink' all food except
| Bread |
| Milk |
Then I 'eat' all food
I decided to put some of the arguments into the table, because otherwise it may be hard to read it.
Step definition in Ruby is:
Then(/^I '(eat|drink)' all food(?: except)?$/) do |action, exceptions|
exceptions = exceptions.raw.flatten.map(&:strip) unless exceptions.nil?
action == 'eat' ? method1(exceptions: exceptions) : method2(exceptions: exceptions)
It works fine, but not for the case when I don't pass the table argument ("Then I 'eat' all food").
Is it possible to make a table argument optional?
I'm not sure if it will work in cucumber, but as it's just a ruby block you can try to use param with splat. A single param will hold the whole parameter list then:
Then(/^I '(eat|drink)' all food(?: except)?$/) do |*params|
# params is an array
action = params[0]
exceptions = params[1] # may be nil
#...
end
More on splats
I have a set of numbers 123456789
I am writing a loop, so for every 3 numbers/characters it insert a comma, and then starts a new line.
What type of loop would I use for this? And how do I tell ruby for every 3 numbers? "123456.each_char.limit(3)"? I I know limit isnt correct but hopefully im getting the idea accross.
puts 123456789.to_s.gsub(/(.{3})/,"\\1,\n")
result :
123,
456,
789,
alternative loop way :
"123456789".each_char.with_index(1) do |item, index|
if index % 3 == 0
print item + ",\n"
else
print item
end
end
If the set of numbers is a string you can use Enumerable#each_slice to split up the characters into groups of 3 and then join them together before printing to the console:
[21] pry(main)> "123456789".chars.each_slice(3) { |a| p "#{a.join}," }
"123,"
"456,"
"789,"
I would like to re-open my script at the end of its execution. I tried with load but it didn't work. Is what I want to do possible? If yes, what should I try?
This is the structure of my script:
usr_choice = gets.chomp.to_i
case usr_choice
when 1
# Do something
when 2
# Do something else
else
puts "Choice not recognised"
end
Basically I would like for example to go back to the user input (usr_choice) after going through the case statement. Without a GoTo.
So you want a loop? Well, use loop:
loop do
usr_choice = gets.chomp.to_i
case usr_choice
when 1
puts 'one'
when 2
puts 'two'
else
break # exit the loop (not the case construct as in other languages)
end
end
Example:
$ ruby filename.rb
1
one
2
two
1
one
kthxbye
$
very new to Ruby, I've got the following situation. I have a file with values separated by new lines, they look like this:
18917
18927
18929
...
I want to prepend a folder path to all of them, then grab the first 2 characters and prepend that as well, then the value in the file and then append a '.jpg' at the end so they would end up looking like this:
path/to/foler/18/18917.jpg
So I've code this ruby code:
folder = "/path/to/folder"
lines = File.readlines("values.csv")
images = lines.collect.to_s.gsub("\n", ".jpg,")
images.split(',').collect { |dogtag | puts "bad dog: #{folder}/#{dogtag[0,2]}/#{dogtag}" }
Now, this almost works, the part that is not working is the grabbing of the first 2 characters. I also tried it with the method outside quotes (and without the #{} of course) but it just produces an empty result.
Could someone please point out my folly?
Eventually I want to delete those images but I'm guessing that substituting 'File.delete' for 'puts' above would do the trick?
As usual, thanks in advance for taking the time to look at this.
You don't seem to be understanding what collect does.
I would rewrite your snippet like this:
File.read("values.csv").each do |line|
puts "bad dog: /path/to/folder/#{line[0,2]}/#{line.chomp}.jpg"
end
-- Update for last comment: --
If you don't want to use an if statement to check if a file exists before deleting it, you have two option (AFAIK).
Use rescue:
File.read("values.csv").each do |line|
begin
File.delete "/path/to/folder/#{line[0,2]}/#{line.chomp}.jpg"
rescue Errno::ENOENT
next
end
end
Or extend the File class with a delete_if_exists method. You can just put this at the top of your script:
class File
def self.delete_if_exists(f)
if exists?(f)
delete(f)
end
end
end
With this, you can do:
File.read("values.csv").each do |line|
File.delete_if_exists "/path/to/folder/#{line[0,2]}/#{line.chomp}.jpg"
end
In C and many other languages, there is a continue keyword that, when used inside of a loop, jumps to the next iteration of the loop. Is there any equivalent of this continue keyword in Ruby?
Yes, it's called next.
for i in 0..5
if i < 2
next
end
puts "Value of local variable is #{i}"
end
This outputs the following:
Value of local variable is 2
Value of local variable is 3
Value of local variable is 4
Value of local variable is 5
=> 0..5
next
also, look at redo which redoes the current iteration.
Writing Ian Purton's answer in a slightly more idiomatic way:
(1..5).each do |x|
next if x < 2
puts x
end
Prints:
2
3
4
5
Inside for-loops and iterator methods like each and map the next keyword in ruby will have the effect of jumping to the next iteration of the loop (same as continue in C).
However what it actually does is just to return from the current block. So you can use it with any method that takes a block - even if it has nothing to do with iteration.
Ruby has two other loop/iteration control keywords: redo and retry.
Read more about them, and the difference between them, at Ruby QuickTips.
I think it is called next.
Use next, it will bypass that condition and rest of the code will work.
Below i have provided the Full script and out put
class TestBreak
puts " Enter the nmber"
no= gets.to_i
for i in 1..no
if(i==5)
next
else
puts i
end
end
end
obj=TestBreak.new()
Output:
Enter the nmber
10
1
2
3
4
6
7
8
9
10
Use may use next conditionally
before = 0
"0;1;2;3".split(";").each.with_index do |now, i|
next if i < 1
puts "before it was #{before}, now it is #{now}"
before = now
end
output:
before it was 0, now it is 1
before it was 1, now it is 2
before it was 2, now it is 3