3

对这段代码运行 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

谢谢

4

3 回答 3

8

您的代码段不是“保护条款”的有效示例。没什么好防备的。它只是选择数据。它看起来会更好,case/whenif链条也很好。

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

当方法的整个主体都包含在条件中时,使用保护子句(或者我称之为提前返回)。

def process_project
  if project
    # do stuff
  end
end

除非有project. 因此,如果我们减少这里的嵌套,它会使代码更具可读性。

def process_project
  return unless project

  # do stuff with project
end

同样,并非if您的代码中的每个都可以/应该转换为这种形式。只在合适的地方。

于 2015-09-09T07:47:44.003 回答
3

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

fetchKeyError如果在 中找不到给定的键,将引发 a ENV

于 2015-09-09T08:12:21.737 回答
2

保护子句通常是这样的:

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,请将其放入 a 中secrets.yml,否则请为此使用许多出色的 gem 之一:


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

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

于 2015-09-09T07:54:55.580 回答