如何用Ruby编写包含多个条件的保护子句



在对这段代码运行Rubocop后,我得到

Use a guard clause instead of wrapping the code inside a conditional expression.

所以从我所读到的"Guard Clause"将在不满足条件的情况下跳出方法,所以我们不必浪费时间来检查额外的条件,如果我的理解不正确,请纠正我。

我的问题是,虽然我将如何使用多个条件的保护语句

def auth_creds
  if %w(test1 qa demo ci).include? ENV['ENV']
    { key: 'key1', secret: 'secret1' }
  elsif ENV['ENV'] == 'live'
    { key: 'key2', secret: 'secret2' }
  else
    fail 'Unable to set key/secret'
  end
end

谢谢

您的代码片段不是"保护子句"的有效示例。没什么好防备的。它只是选择数据。case/when链看起来更好,但if链也可以。

def auth_creds
  case ENV['ENV']
  when 'test1', 'qa', 'demo', 'ci'
    { key: 'key1', secret: 'secret1' }
  when 'live'
    { key: 'key2', secret: 'secret2' }
  else
    fail 'Unable to set key/secret'
  end
end

Guard子句(或者我称之为早期返回)在方法的整个主体被条件语句包装时使用。

def process_project
  if project
    # do stuff
  end
end

该方法不会做任何事情,除非有一个project。因此,如果我们减少这里的嵌套,它会使代码更具可读性。

def process_project
  return unless project
  # do stuff with project
end
同样,并非代码中的每个if都可以/应该转换为这种形式。

这完全取决于您的实际代码,但是对于给定的代码片段,您可以使用一个保护子句来确保有效的ENV['ENV']值:

VALID_ENVS = %w(test1 qa demo ci live)
def auth_creds
  fail 'invalid environment' unless VALID_ENVS.include? ENV['ENV']
  if ENV['ENV'] == 'live'
    { key: 'key2', secret: 'secret2' }
  else
    { key: 'key1', secret: 'secret1' }
  end
end

正如Sergio Tulentsev所指出的,将您的凭据存储在ENV中(而不是环境的名称)可能会更好:

def auth_creds
  { key: ENV.fetch('KEY'), secret: ENV.fetch('SECRET') }
end

fetch将引发一个KeyError,如果给定的键不在ENV中。

保护子句一般是这样的:

def do_something
  return 'x' if some_condition?
  # other code
end
所以你的代码可以重写为
def auth_creds
  return { key: 'key1', secret: 'secret1' } if %w(test1 qa demo ci).include? ENV['ENV']
  return { key: 'key2', secret: 'secret2' } if ENV['ENV'] == 'live'
  fail 'Unable to set key/secret'
end

然而,这是相当丑陋的,现在rubocop会抱怨行太长。因此,让我们重新定义代码以描述其意图:

def auth_creds
  return { key: 'key1', secret: 'secret1' } if test_env?
  return { key: 'key2', secret: 'secret2' } if live_env?
  fail 'Unable to set key/secret'
end
private # omit if `auth_creds` is also private
def test_env?
  %w(test1 qa demo ci).include? ENV['ENV']
end
def live_env?
  ENV['ENV'] == 'live'
end

附加点:%w(test1 qa demo ci)提取为常量!

双重加分:(感谢@Sergio Tulentsev)从代码中获取特定于环境的(可能是敏感的!!)凭据!如果使用Rails,将其放在secrets.yml中,否则使用许多伟大的宝石之一:

  • dotenv
  • 费加罗

关于Rubocop的一句话:对它的建议持保留态度。例如,您的代码并不是真正使用保护子句的情况,它只是根据条件返回数据。因此,您也可以尝试将代码重构为case表达式。

有时,Rubocop只是在说垃圾:-)(不是故意的,但是"测量"代码风格很难!)

相关内容

  • 没有找到相关文章

最新更新