Ruby: Most concise way to use an ENV variable if it exists, otherwise use default value
In Ruby, I am trying to write a line that uses a variable if it has been set, otherwise default to some value:
myvar = # 开发者_如何学Pythonassign it to ENV['MY_VAR'], otherwise assign it to 'foobar'
I could write this code like this:
if ENV['MY_VAR'].is_set? #whatever the function is to check if has been set
myvar = ENV['MY_VAR']
else
myvar = 'foobar'
end
But this is rather verbose, and I'm trying to write it in the most concise way possible. How can I do this?
myvar = ENV['MY_VAR'] || 'foobar'
N.B. This is slightly incorrect (if the hash can contain the value nil
) but since ENV
contains just strings it is probably good enough.
The most reliable way for a general Hash is to ask if it has the key:
myvar = h.has_key?('MY_VAR') ? h['MY_VAR'] : 'default'
If you don't care about nil
or false
values (i.e. you want to treat them the same as "not there"), then undur_gongor's approach is good (this should also be fine when h
is ENV
):
myvar = h['MY_VAR'] || 'foobar'
And if you want to allow nil
to be in your Hash but pretend it isn't there (i.e. a nil
value is the same as "not there") while allowing a false
in your Hash:
myvar = h['MY_VAR'].nil? ? 'foobar' : h['MY_VAR']
In the end it really depends on your precise intent and you should choose the approach that matches your intent. The choice between if/else/end
and ? :
is, of course, a matter of taste and "concise" doesn't mean "least number of characters" so feel free to use a ternary or if
block as desired.
hash.fetch(key) { default_value }
Will return the value if it exists, and return default_value
if the key doesn't exist.
This works best for me:
ENV.fetch('VAR_NAME',"5445")
myvar = ENV.fetch('MY_VAR') { 'foobar' }
'foobar'
being the default if ENV['MY_VAR']
is unset.
Although it's not relevant in the specific example you gave since you're really asking about hash keys, not variables, Ruby does give a way to check variable definition. Use the defined?
keyword (it's not a method, but a keyword since it needs special handling by the interpreter), like so:
a = 1
defined? a
#=> "local-variable"
@a = 2
defined? @a
#=> "instance-variable"
@@a = 3
defined? @@a
#=> "class-variable"
defined? blahblahblah
#=> nil
Hence you could do:
var = defined?(var) ? var : "default value here"
As far as I know, that's the only way other than an ugly begin
/rescue
/end
block to define a variable in the way that you ask without risking a NameError. As I said, this doesn't apply to hashes since:
hash = {?a => 2, ?b => 3}
defined? hash[?c]
#=> "method"
i.e. you're checking that the method []
is defined rather than the key/value pair you're using it to access.
Another possible alternative, which will work even if ENV['MY_VAR'] turnsout to be a false value
myvar = ENV['MY_VAR'].presence || 'foobar'
The Demand gem which I wrote allows this to be extremely concise and DRY:
myvar = demand(ENV['MY_VAR'], 'foobar')
This will use ENV['MY_VAR']
only if it is present. That is, it will discard it just if it's nil, empty or a whitespace-only string, giving the default instead.
If a valid value for ENV['MY_VAR']
is falsy (such as false
), or an invalid value is truthy (such as ""
), then solutions like using ||
would not work.
I am new guy to Ruby, post the answer I found at 2021, maybe useful for someone.
check if env key exists:
include?(name) → true or false
has_key?(name) → true or false
member?(name) → true or false
key?(name) → true or false
get env with default value:
ENV.fetch(name, :default_val)
ref: https://docs.ruby-lang.org/en/master/ENV.html
myvar = ENV['MY_VAR'].is_set? ? ENV['MY_VAR'] : 'foobar'
This way you keep the .is_set? method.
精彩评论