Suppose we have n constants like:
FOO = 'foo' BAR = 'bar' ...
I need to check in the block if they exists and are non empty.
%w(FOO BAR FOOBAR).each {|i|开发者_如何转开发 # this doesn't work fail "#{i} is missing or empty" if (! defined?(i) || i.empty?) }
This is the best way, in my opinion:
[:FOO, :BAR, :FOOBAR].each do |i|
raise "constant #{i} not defined" unless Object.const_defined?(i)
puts "constant #{i} exists and has value #{Object.const_get(i)}"
end
EDIT:
Things are a bit more complicated if you want to look up constants in a scope sensitive way (i.e not just top-level constants):
def const_receiver
is_a?(Module) ? self : class << self; self; end
end
[:FOO, :BAR, :FOOBAR].each do |i|
raise "constant #{i} not defined" unless const_receiver.const_defined?(i)
puts "constant #{i} exists and has value #{const_receiver.const_get(i)}"
end
In your original code, i
is a string, so it won't be empty.
I assume you're checking whether the constant with the name of i
is empty, right? This is not a pipe.
%w(FOO BAR FOOBAR).each do |const_name|
raise "#{const_name} is missing or empty" if (! eval("defined?#{const_name}") || eval(const_name).empty?)
end
Notes:
- I've renamed
i
toconst_name
- Ruby tends to use
raise
rather thanfail
- You've got a fair bit of logic in one line. I'd be tempted to break it into two lines, one checking if the constant exists, and one checking if the string the constant refers to is empty. Better yet, make it into a method.
- Multi-line blocks tend to use
do ... end
rather than{ ... }
(that's more for single lines. I think there's a SO question comparing the two, however - it's worth looking up because the two forms aren't totally identical)
Out of curiosity, which programming language were you using before using Ruby? Was it Perl?
BAR = 'bar'
%w(FOO BAR FOOBAR).each {|i|
begin
eval(i)
rescue NameError=>e
puts e
end
}
精彩评论