Checking if a variable is defined? - ruby

How can I check whether a variable is defined in Ruby? Is there an isset-type method available?

Use the defined? keyword (documentation). It will return a String with the kind of the item, or nil if it doesn’t exist.
>> a = 1
=> 1
>> defined? a
=> "local-variable"
>> defined? b
=> nil
>> defined? nil
=> "nil"
>> defined? String
=> "constant"
>> defined? 1
=> "expression"
As skalee commented: "It is worth noting that variable which is set to nil is initialized."
>> n = nil
>> defined? n
=> "local-variable"

This is useful if you want to do nothing if it does exist but create it if it doesn't exist.
def get_var
#var ||= SomeClass.new()
end
This only creates the new instance once. After that it just keeps returning the var.

The correct syntax for the above statement is:
if (defined?(var)).nil? # will now return true or false
print "var is not defined\n".color(:red)
else
print "var is defined\n".color(:green)
end
substituting (var) with your variable. This syntax will return a true/false value for evaluation in the if statement.

defined?(your_var) will work. Depending on what you're doing you can also do something like your_var.nil?

Try "unless" instead of "if"
a = "apple"
# Note that b is not declared
c = nil
unless defined? a
puts "a is not defined"
end
unless defined? b
puts "b is not defined"
end
unless defined? c
puts "c is not defined"
end

WARNING Re: A Common Ruby Pattern
the defined? method is the answer. See the accepted answer above.
But watch out... consider this common ruby pattern:
def method1
#x ||= method2
end
def method2
nil
end
method2 always returns nil.
The first time you call method1, the #x variable is not set - therefore method2 will be run. and
method2 will set #x to nil.
But what happens the second time you call method1?
Remember #x has already been set to nil. But method2 will still be run again!! If method2 is a costly undertaking this might not be something that you want.
Let the defined? method come to the rescue:
def method1
return #x if defined? #x
#x = method2
end
As with most things, the devil is in the implementation details.

Use defined? YourVariable
Keep it simple silly .. ;)

Here is some code, nothing rocket science but it works well enough
require 'rubygems'
require 'rainbow'
if defined?(var).nil? # .nil? is optional but might make for clearer intent.
print "var is not defined\n".color(:red)
else
print "car is defined\n".color(:green)
end
Clearly, the colouring code is not necessary, just a nice visualation in this toy example.

You can try:
unless defined?(var)
#ruby code goes here
end
=> true
Because it returns a boolean.

As many other examples show you don't actually need a boolean from a method to make logical choices in ruby. It would be a poor form to coerce everything to a boolean unless you actually need a boolean.
But if you absolutely need a boolean. Use !! (bang bang) or "falsy falsy reveals the truth".
› irb
>> a = nil
=> nil
>> defined?(a)
=> "local-variable"
>> defined?(b)
=> nil
>> !!defined?(a)
=> true
>> !!defined?(b)
=> false
Why it doesn't usually pay to coerce:
>> (!!defined?(a) ? "var is defined".colorize(:green) : "var is not defined".colorize(:red)) == (defined?(a) ? "var is defined".colorize(:green) : "var is not defined".colorize(:red))
=> true
Here's an example where it matters because it relies on the implicit coercion of the boolean value to its string representation.
>> puts "var is defined? #{!!defined?(a)} vs #{defined?(a)}"
var is defined? true vs local-variable
=> nil

It should be mentioned that using defined to check if a specific field is set in a hash might behave unexpected:
var = {}
if defined? var['unknown']
puts 'this is unexpected'
end
# will output "this is unexpected"
The syntax is correct here, but defined? var['unknown'] will be evaluated to the string "method", so the if block will be executed
edit: The correct notation for checking if a key exists in a hash would be:
if var.key?('unknown')

Please note the distinction between "defined" and "assigned".
$ ruby -e 'def f; if 1>2; x=99; end;p x, defined? x; end;f'
nil
"local-variable"
x is defined even though it is never assigned!

defined? is great, but if you are in a Rails environment you can also use try, especially in cases where you want to check a dynamic variable name:
foo = 1
my_foo = "foo"
my_bar = "bar"
try(:foo) # => 1
try(:bar) # => nil
try(my_foo) # => 1
try(my_bar) # => nil

Also, you can check if it's defined while in a string via interpolation, if you code:
puts "Is array1 defined and what type is it? #{defined?(#array1)}"
The system will tell you the type if it is defined.
If it is not defined it will just return a warning saying the variable is not initialized.
Hope this helps! :)

Leaving an incredibly simple example in case it helps.
When variable doesn't exist:
if defined? a then "hi" end
# => nil
When variable does exist:
a = 2
if defined? a then "hi" end
# => "hi"

Related

Ruby code to check for Integer [duplicate]

I need a function, is_an_integer, where
"12".is_an_integer? returns true.
"blah".is_an_integer? returns false.
How can I do this in Ruby? I would write a regex but I'm assuming there is a helper for this that I am not aware of.
Well, here's the easy way:
class String
def is_integer?
self.to_i.to_s == self
end
end
>> "12".is_integer?
=> true
>> "blah".is_integer?
=> false
I don't agree with the solutions that provoke an exception to convert the string - exceptions are not control flow, and you might as well do it the right way. That said, my solution above doesn't deal with non-base-10 integers. So here's the way to do with without resorting to exceptions:
class String
def integer?
[ # In descending order of likeliness:
/^[-+]?[1-9]([0-9]*)?$/, # decimal
/^0[0-7]+$/, # octal
/^0x[0-9A-Fa-f]+$/, # hexadecimal
/^0b[01]+$/ # binary
].each do |match_pattern|
return true if self =~ match_pattern
end
return false
end
end
You can use regular expressions. Here is the function with #janm's suggestions.
class String
def is_i?
!!(self =~ /\A[-+]?[0-9]+\z/)
end
end
An edited version according to comment from #wich:
class String
def is_i?
/\A[-+]?\d+\z/ === self
end
end
In case you only need to check positive numbers
if !/\A\d+\z/.match(string_to_check)
#Is not a positive number
else
#Is all good ..continue
end
You can use Integer(str) and see if it raises:
def is_num?(str)
!!Integer(str)
rescue ArgumentError, TypeError
false
end
It should be pointed out that while this does return true for "01", it does not for "09", simply because 09 would not be a valid integer literal. If that's not the behaviour you want, you can add 10 as a second argument to Integer, so the number is always interpreted as base 10.
Ruby 2.6.0 enables casting to an integer without raising an exception, and will return nil if the cast fails. And since nil mostly behaves like false in Ruby, you can easily check for an integer like so:
if Integer(my_var, exception: false)
# do something if my_var can be cast to an integer
end
"12".match(/^(\d)+$/) # true
"1.2".match(/^(\d)+$/) # false
"dfs2".match(/^(\d)+$/) # false
"13422".match(/^(\d)+$/) # true
You can do a one liner:
str = ...
int = Integer(str) rescue nil
if int
int.times {|i| p i}
end
or even
int = Integer(str) rescue false
Depending on what you are trying to do you can also directly use a begin end block with rescue clause:
begin
str = ...
i = Integer(str)
i.times do |j|
puts j
end
rescue ArgumentError
puts "Not an int, doing something else"
end
class String
def integer?
Integer(self)
return true
rescue ArgumentError
return false
end
end
It isn't prefixed with is_. I find that silly on questionmark methods, I like "04".integer? a lot better than "foo".is_integer?.
It uses the sensible solution by sepp2k, which passes for "01" and such.
Object oriented, yay.
The Best and Simple way is using Float
val = Float "234" rescue nil
Float "234" rescue nil #=> 234.0
Float "abc" rescue nil #=> nil
Float "234abc" rescue nil #=> nil
Float nil rescue nil #=> nil
Float "" rescue nil #=> nil
Integer is also good but it will return 0 for Integer nil
I prefer:
config/initializers/string.rb
class String
def number?
Integer(self).is_a?(Integer)
rescue ArgumentError, TypeError
false
end
end
and then:
[218] pry(main)> "123123123".number?
=> true
[220] pry(main)> "123 123 123".gsub(/ /, '').number?
=> true
[222] pry(main)> "123 123 123".number?
=> false
or check phone number:
"+34 123 456 789 2".gsub(/ /, '').number?
A much simpler way could be
/(\D+)/.match('1221').nil? #=> true
/(\D+)/.match('1a221').nil? #=> false
/(\D+)/.match('01221').nil? #=> true
Personally I like the exception approach although I would make it a little more terse:
class String
def integer?(str)
!!Integer(str) rescue false
end
end
However, as others have already stated, this doesn't work with Octal strings.
This might not be suitable for all cases simplely using:
"12".to_i => 12
"blah".to_i => 0
might also do for some.
If it's a number and not 0 it will return a number. If it returns 0 it's either a string or 0.
def isint(str)
return !!(str =~ /^[-+]?[1-9]([0-9]*)?$/)
end
Here's my solution:
# /initializers/string.rb
class String
IntegerRegex = /^(\d)+$/
def integer?
!!self.match(IntegerRegex)
end
end
# any_model_or_controller.rb
'12345'.integer? # true
'asd34'.integer? # false
And here's how it works:
/^(\d)+$/is regex expression for finding digits in any string. You can test your regex expressions and results at http://rubular.com/.
We save it in a constant IntegerRegex to avoid unnecessary memory allocation everytime we use it in the method.
integer? is an interrogative method which should return true or false.
match is a method on string which matches the occurrences as per the given regex expression in argument and return the matched values or nil.
!! converts the result of match method into equivalent boolean.
And declaring the method in existing String class is monkey patching, which doesn't change anything in existing String functionalities, but just adds another method named integer? on any String object.
Ruby 2.4 has Regexp#match?: (with a ?)
def integer?(str)
/\A[+-]?\d+\z/.match? str
end
For older Ruby versions, there's Regexp#===. And although direct use of the case equality operator should generally be avoided, it looks very clean here:
def integer?(str)
/\A[+-]?\d+\z/ === str
end
integer? "123" # true
integer? "-123" # true
integer? "+123" # true
integer? "a123" # false
integer? "123b" # false
integer? "1\n2" # false
Expanding on #rado's answer above one could also use a ternary statement to force the return of true or false booleans without the use of double bangs. Granted, the double logical negation version is more terse, but probably harder to read for newcomers (like me).
class String
def is_i?
self =~ /\A[-+]?[0-9]+\z/ ? true : false
end
end
For more generalised cases (including numbers with decimal point),
you can try the following method:
def number?(obj)
obj = obj.to_s unless obj.is_a? String
/\A[+-]?\d+(\.[\d]+)?\z/.match(obj)
end
You can test this method in an irb session:
(irb)
>> number?(7)
=> #<MatchData "7" 1:nil>
>> !!number?(7)
=> true
>> number?(-Math::PI)
=> #<MatchData "-3.141592653589793" 1:".141592653589793">
>> !!number?(-Math::PI)
=> true
>> number?('hello world')
=> nil
>> !!number?('hello world')
=> false
For a detailed explanation of the regex involved here, check out this blog article :)
One liner in string.rb
def is_integer?; true if Integer(self) rescue false end
I'm not sure if this was around when this question is asked but
for anyone that stumbles across this post, the simplest way is:
var = "12"
var.is_a?(Integer) # returns false
var.is_a?(String) # returns true
var = 12
var.is_a?(Integer) # returns true
var.is_a?(String) # returns false
.is_a? will work with any object.

Best way to test if a variable is nil or false implicitly

I was hoping someone could help me with identifying the most idiomatic way to test if a variable is nil or false implicitly for the sake of readability.
Here is my explicit example:
if somevar.nil? # explicitly checking for nil.
puts "Its nil."
end
Is it better to write:
if !somevar # implicit
puts "Var is nil or false."
end
I really like this way:
if not somevar # implicit
puts "Var is nil or false"
end
From what I am reading, testing for nil explicitly should be avoided to some extent as its generally not needed. Most examples suggest to take action only if a variable exists. However, I want to perform an action when a variable does not exist.
Main inspiration for ditching nil came from: ruby_idioms
def truthiness(value)
if value
"truthy"
else
"falsy"
end
end
puts "nil:", truthiness(nil) # falsy
puts "false:", truthiness(false) # falsy
puts "true:", truthiness(true) # truthy
puts "[]:", truthiness([]) # truthy
puts "{}:", truthiness({}) # truthy
puts "0:", truthiness(0) # truthy
I know you know Python, so I can say that:
In Python, None, False, and empty containers such as [], {}, and even 0 are all falsy.
In Ruby, nil and false are falsy, whereas most other things are truthy, even [], {}, and 0.
I think the most idiomatic way in ruby for testing whether something is false or nil is using unless:
unless somevar
puts "Var is nil or false."
end
From the ruby style guide
Favor unless over if for negative conditions (or control flow
||).
# bad
do_something if !some_condition
# bad
do_something if not some_condition
# good
do_something unless some_condition
# another good option
some_condition || do_something
You can use defined? keyword :
defined? expression tests whether or not expression refers to anything recognizable (literal object, local variable that has been initialized, method name visible from the current scope, etc.). The return value is nil if the expression cannot be resolved. Otherwise, the return value provides information about the expression.
unless defined?(var)
#your code
end
Quick PRY to test, what the defined? returns when a variable is defined and when not :-
arup#linux-wzza:~/Ruby> pry
[1] pry(main)> defined?(x)
=> nil
[2] pry(main)> x = nil
=> nil
[3] pry(main)> defined? x
=> "local-variable"
[4] pry(main)>

Ruby testing for definition of a variable

I know there are other questions similar such as:
Ruby: how to check if variable exists within a hash definition
Checking if a variable is defined?
But the answers aren't fully satisfactory.
I have:
ruby-1.9.2-p290 :001 > a=Hash.new
=> {}
ruby-1.9.2-p290 :002 > a['one']="hello"
=> "hello"
ruby-1.9.2-p290 :006 > defined?(a['one']['some']).nil?
=> false
ruby-1.9.2-p290 :007 > a['one']['some'].nil?
=> true
It seems like:
if a['one']['some'].nil?
a['one']['some']=Array.new
end
would be sufficient. Is this correct? Would this be correct for any data type? Is defined? needed in this case?
thx
You seem to be confusing two concepts. One is if a variable is defined, and another is if a Hash key is defined. Since a hash is, at some point, a variable, then it must be defined.
defined?(a)
# => nil
a = { }
# => {}
defined?(a)
# => "local-variable"
a.key?('one')
# => false
a['one'] = 'hello'
# => 'hello'
a.key?('one')
# => true
Something can be a key and nil at the same time, this is valid. There is no concept of defined or undefined for a Hash. It is all about if the key exists or not.
The only reason to test with .nil? is to distinguish between the two possible non-true values: nil and false. If you will never be using false in that context, then calling .nil? is unnecessarily verbose. In other words, if (x.nil?) is equivalent to if (x) provided x will never be literally false.
What you probably want to employ is the ||= pattern that will assign something if the existing value is nil or false:
# Assign an array to this Hash key if nothing is stored there
a['one']['hello'] ||= [ ]
Update: Edited according to remarks by Bruce.
I had to dig a number of pages deep into Google, but I eventually found this useful bit from the Ruby 1.9 spec:
"In all cases the test [defined?] is conducted without evaluating the operand."
So what's happening is that it looks at:
a['one']['some']
and says "that is sending the "operator []" message to the 'a' object - that is a method call!" and the result of defined? on that is "method".
Then when you check against nil?, the string "method" clearly isn't nil.
In addition to #tadmans answer, what you actually did in your example was to check, if the string "some" is included in the string "hello" which is stored in your hash at the position "one".
a = {}
a['one'] = 'hello'
a['one']['some'] # searches the string "some" in the hash at key "one"
A more simple example:
b = 'hello'
b['he'] # => 'he'
b['ha'] # => nil
That's why the defined? method did not return nil, as you expected, but "method".

What value assumes an uninitialized variable using Ruby on Rails?

I am using Ruby on Rails 3 and I have this situation:
In a controller I have
# first statement
if a == true
flag = true
end
# second statement
if flag == true
// code1
else
// code2
end
If a is false, what happens in the if statement without having initialized the flag variable? That is, is the flag variable "always"/"in any case" set to NOT TRUE?
Is it a safe approach?
You can try this sort of thing out in irb:
>> if false
>> foo = "bar"
>> end
=> nil
>> foo
=> nil
So you can see that even though the if condition is false, the foo variable is introduced (it is nil, which will be treated the same as false in your if, so you are safe). I suspect that this is because if statements don't introduce a new scope. See:
>> if true
>> bar = "baz"
>> end
=> "baz"
>> bar
=> "baz"
One final thought: If A is really just a boolean, you could set flag = A and avoid the if altogether.
An unassigned variable is equal to nil but constants work a little differently. With a variable anything other than nil or false will evaluate to true. With a constant you need to use definded?(CONSTANT) so your code would look like this:
# first statement
flag = A if defined?(A)
# second statement
if flag
puts "Code 1"
else
puts "Code 2"
end
# Or if you don't need the flag variable
if defined?(A) && A
puts "Code 1"
else
puts "Code 2"
end
Output:
Code 2
Code 2

In Ruby why won't `foo = true unless defined?(foo)` make the assignment?

What's going on here? What is the subtle difference between the two forms of "unless"?
> irb(main):001:0> foo = true unless defined?(foo)
=> nil
irb(main):002:0> unless defined?(fooo) ; fooo = false ; end
=> false
thx
Apparently, ruby creates local variable at parse time setting them to nilso it is defined and this is done whether the code is executed or not.
When the code is evaluated at your first line, it doesn't execute the assignment part since foo is set to nil. In the second line, because fooo has not been parsed yet, defined?returns nil letting the code inside the block execute and assign fooo.
As an example you can try this:
if false
foo = 43
end
defined? foo
=> "local-variable"
This is taken from a forum post at ruby-forum.
Let's start with something simpler:
# z is not yet defined
irb(main):001:0> defined?(z)
=> nil
# Even though the assignment won't execute,
# the mere presence of the assignment statement
# causes z to come to life.
irb(main):002:0> z = 123 if false
=> nil
irb(main):003:0> defined?(z)
=> "local-variable"
irb(main):004:0> z
=> nil
Now we can figure out your first example.
foo = true unless defined?(foo)
Is foo defined? Before we press ENTER in irb, no. However, the presence of the assignment statement causes foo to come to life. That means the assignment statement won't be executed, leaving foo in existence but having nil as its value. And what is the last expression evaluated in the irb line? It is unless defined?(foo), which evaluates to nil.
For more info on how assignments (even those that do not get executed) cause variables to exist, see this discussion of Variable/Method Ambiguity.
In your second example, there is nothing mysterious at all: fooo is not defined, so the code in the block executes, setting fooo to false. That assignment is the last expression evaluated, so false is the return value of our block.
irb(main)> foo = true unless defined?(Integer)
=> nil
irb(main)> foo = true unless defined?(thisIsUndefined)
=> true
Your first block is returning nil because the way it's written leaves 2 options:
foo is not defined --> assign true
foo is defined --> do nothing
Here, foo must be defined when the line is evaluated. Thus, nothing happens and nil is returned.
irb(main)> unless defined?(Integer) ; fooo = false ; end
=> nil
irb(main)> unless defined?(thisIsUndefined) ; fooo = false ; end
=> false
Your second block operates the same way your first one does. If fooo is not defined, the block is entered and fooo is set to false. The result of the last line of the block is the return value of the block, thus the false you are seeing. If fooo does exist, then the block is skipped over and nothing happens, therefore there is nothing to return, therefore the nil.
Based on your code, I would say that foo was defined when this code was run and fooo was not (test code shown was generated in Ruby 1.8.6). If you did not define either of these before running this code, then you may have something called foo that is defined by default (do defined?(foo) by itself to check). Try using a different name and see if you get the same results.
Edit:
irb(main)> defined?(bar)
=> nil
irb(main)> bar = true unless defined?(bar)
=> nil
irb(main)> defined?(bar)
=> "local-variable"
Apparently, defined?() is returning true since it has already seen bar (at the beginning of the line), even though you are still in the process of defining it.
in the first instance you call foo into existence in the assignment statement. Maybe this will clarify:
bar = if true
puts bar.class
else
puts "not reached"
end
NilClass
=> nil
baz = if true
puts baz.class
42
else
puts "not reached"
end
NilClass
=> 42
August, all look fine in 1.8.7:
$ irb
irb(main):001:0> unless defined?(fooo); fooo = true; end
=> true
irb(main):002:0> fooo
=> true
irb(main):003:0> `ruby --version`
=> "ruby 1.8.7 (2008-06-20 patchlevel 22) [i486-linux]\n"
Well.. One form is a block and one form isn't. The second part, the block, returns the last statement evaluated. The first one.. Hrm.. I don't know exactly what it's doing.
In Ruby 1.8.7:
foo = true unless defined?(foo)
p foo # => nil
unless defined?(fooo); fooo = true; end
p foo # => nil
I don't have an explanation for the behaviour you are seeing.

Resources