I will admit that I'm still new to Ruby so I'm not yet familiar with the gotcha's and am still learning.
I've googled the issue many times but haven't been able to find an exact answer. Most results talk about "nested" if/else statements. Which isn't what I'm attempting. I found another answer from SO that talked about mapping the arrays based on conditions, but feel like that would bring me back to the same issues I'm already having.
Link to SO article regarding merging nested arrays if anyone is interested: Ruby: Merging nested array between each other depending on a condition
My Question:
While designing a simple CLI script in ruby using optparse to control the output based on conditionals. I came across an issue where I am unable to do multiple sequential if statements and concat/merge multiple arrays into one to be passed to another function.
For some reason only the last if block is being honoured. All if blocks before the last one return nil.
Can anyone tell me what I'm doing wrong and provide me with some relevant documentation regarding my issue. Such as why such an issue occurs?
Would love a working solution to learn from, but reference material would work as well since my goal is to learn from this issue.
Results of my tests:
$ ruby servers.rb
#=> ["server1", "server2", "server3"]
$ ruby servers.rb -m
#=> nil
$ ruby servers.rb -h
#=> nil
$ ruby servers.rb -s server6
#=> ["server6"]
$ ruby servers.rb -m -h
#=> nil
Below is my script:
#!/usr/bin/env ruby
require 'optparse'
@servers = {
'primary' => %w[server1 server2 server3],
'inhouse' => %w[server4 server5],
'mlm' => %w[server6]
}
@options = {
inhouse: false,
server: [],
mlm: false
}
# Parse options passed to medusabackup.rb
optparse = OptionParser.new do |opts|
opts.on('-h', '--inhouse', 'Limit results to inhouse results') do
@options[:inhouse] = true
end
opts.on('-m', '--mlm', 'Include mlm results') do
@options[:mlm] = true
end
opts.on('-s', '--server=SERVER', 'Limit results to SERVER') do |f|
@options[:server] << f
end
opts.on_tail('--help', 'Display this screen') { puts opts, exit }
end
begin
optparse.parse!
rescue OptionParser::InvalidOption, OptionParser::MissingArgument
puts $ERROR_INFO.to_s
puts optparse
exit
end
def selected_servers
# Setup Selected variable as an array
selected = []
# If @options[:server] array is not empty and @options[:server]
# add @options[:server] servers to [selected] array
if @options[:server].empty?
# If @options[:mlm] is true add @server['mlm'] servers to [selected] array
selected.concat @servers['mlm'] if @options[:mlm]
# If @options[:inhouse] is true add @server['inhouse'] servers to [selected] array
selected.concat @servers['inhouse'] if @options[:inhouse]
# If @options[:mlm], @options[:inhouse] is true add @server['mlm'] servers to [selected] array
selected.concat @servers['primary'] unless @options[:mlm] || @options[:inhouse]
else
selected.concat @options[:server]
end
end
puts selected_servers.inspect
Thanks to Max and everyone for showing me my blunder. Forgot to return selected at the bottom of the function.
There's no explicit return in selected_servers
, so it's returning the value of the last expression it runs, which is usually a failing unless
. A failing if/unless returns nil
.