如何在Ruby中编写具有多个条件的保护子句?

时间:2015-09-09 07:34:37

标签: ruby guard-clause

针对此代码运行Rubocop后,我正在

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

所以从我所看到的情况来看,如果条件不满足,“守卫条款”将会退出该方法,所以我们不必浪费时间通过额外的条件,如果我的理解不正确,请纠正我

我的问题是,我将如何使用具有多个条件的保护声明

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

由于

3 个答案:

答案 0 :(得分:8)

您的代码段不是“防护条款”的有效示例。没有什么可以防范的。它只是选择数据。它看起来更好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都可以/应该转换为此形式。只有在合适的地方。

答案 1 :(得分:3)

这完全取决于您的实际代码,但使用给定的代码段,您可以使用guard子句来确保有效的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

作为noted by Sergio Tulentsev,将您的凭据存储在ENV(而不是env的名称)可能会更好:

def auth_creds
  { key: ENV.fetch('KEY'), secret: ENV.fetch('SECRET') }
end
如果在fetch中找不到给定的密钥,则

KeyError会引发ENV

答案 2 :(得分:1)

守卫条款通常如下:

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中,否则请使用众多伟大的宝石之一:

关于Rubocop的一句话:用一粒盐来接受它的建议。例如,您的代码实际上不是保护条款的情况,它只是根据条件返回数据。因此,您也可以尝试将代码重构为case expression

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