在对这段代码运行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只是在说垃圾:-)(不是故意的,但是"测量"代码风格很难!)