【问题标题】:Why are the top-most if conditions ignored?如果条件被忽略,为什么最顶层?
【发布时间】:2019-03-14 20:37:31
【问题描述】:

我承认我对 Ruby 还是很陌生,所以我还不熟悉问题并且还在学习。

我已经用谷歌搜索了很多次这个问题,但一直没有找到确切的答案。大多数结果都在谈论“嵌套”if/else 语句。这不是我正在尝试的。我从 SO 那里找到了另一个答案,它谈到了根据条件映射数组,但感觉这会让我回到我已经遇到的同样问题。

如果有人感兴趣,请链接到关于合并嵌套数组的 SO 文章: Ruby: Merging nested array between each other depending on a condition

我的问题:

在 ruby​​ 中设计一个简单的 CLI 脚本时,使用 optparse 来控制基于条件的输出。我遇到了一个问题,我无法执行多个顺序 if 语句并将多个数组合并/合并到一个数组中以传递给另一个函数。

由于某种原因,只有最后一个 if 块 被兑现。最后一个之前的所有 if 块都返回 nil

谁能告诉我我做错了什么,并为我提供一些关于我的问题的相关文档。比如为什么会出现这样的问题?

希望有一个可行的解决方案可供学习,但参考资料也可以,因为我的目标是从这个问题中学习。

我的测试结果:

$ 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

下面是我的脚本:

#!/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

感谢 Max 和大家向我展示了我的错误。忘记在函数底部返回选中的。

【问题讨论】:

  • 请查看网站的帮助部分以了解Minimal Complete Verifiable Example 的概念。这是证明您的问题的最短示例吗?
  • 此代码的行为与您在使用部分中显示的不同。
  • 提示:你的 selected_servers 返回了一些东西,但不是你期望的。
  • @pjs -我很抱歉。我在我的代码中留下了一个未使用的条件块。删除它。将代码减少到仅受影响的函数。
  • @SergioTulentsev 抱歉。 (让每个人都开心很难。)添加回原来的 optsparse 代码。可以确认它是可复制粘贴运行的。 (下次学习)

标签: ruby conditional optparse


【解决方案1】:

selected_servers 中没有显式返回,因此它返回它运行的最后一个表达式的值,这通常是失败的unless。失败的 if/unless 返回 nil

【讨论】:

  • if 被伪装成unless 时,这不是有点误导吗?
  • @muistooshort:就我个人而言,unless 总是让我停下来重新阅读几次条件。真的是我想的那样吗?真的吗?被双重否定烧了太多次了:)
  • @SergioTulentsev 同样在这里,我必须在脑海中将unless cond 重写为if !cond 所以我不使用它(除了带有各种Rails 宏的unless: :method_name 表单,但即便如此我还是倾向于编写一个额外的方法,以便我可以使用 if: 代替)。这种特殊情况更加隐蔽,因为if 内部有一个后缀unless,并且整个表达式最终成为方法调用的值。
猜你喜欢
  • 1970-01-01
  • 2019-06-02
  • 2019-09-11
  • 1970-01-01
  • 2023-03-06
  • 1970-01-01
  • 1970-01-01
  • 2021-11-06
  • 2019-03-22
相关资源
最近更新 更多