When I use this code:
x = []
x << 1
if (x[0].inspect == 1)
puts "OLLAAA"
end
It outputs nothing, but it should because x[0].inspect is == to 1. But if I change == to != I get output "OLLAAA", or when if is changed to unless. Any ideas?
Fixnum#inspect is an alias for to_s - you need to compare against "1"
Why are you so sure x[0].inspect == 1? Object::inspect returns a string.
$ irb
2.0.0-p247 :001 > x = []
=> []
2.0.0-p247 :002 > x << 1
=> [1]
2.0.0-p247 :003 > x[0].inspect == 1
=> false
If you change == to !=, obviously you flip the logic, so it prints. The exact same thing is happening for if to unless.
Because of below :
x[0].inspect # => "1"
x[0].inspect gives string instance,which is not equal to Fixnum instance 1. Thus x[0].inspect == 1 evaluates to false,and you didn't get the output. Now when you use !=,hope you got the point why you did get the output.
Fixnum#inpect call actually does Fixnum#to_s. See below :
12.method(:inspect) # => #<Method: Fixnum#to_s>
as mentioned above, inspect return a string. You can solve your problem with
if (x[0].inspect.to_i == 1)
puts "Hey I am an integer :)"
end
Related
I receive a param and want it to be either a string like this :
"abc,efg"
or an Array like this
["abc","efg"]
In the first case I want to convert it into an Array, what would be the good way ?
Here is what I thought
if params[:ids] && params[:ids].is_a? Array
ids = params[:ids]
else if params[:ids]
ids = params[:ids].split(",")
I'd use a ternary for this to keep it simple and on one line:
ids = params[:ids].is_a?(String) ? params[:ids].split(',') : params[:ids]
I've reversed the order so you don't get an undefined method error if you try calling split on nil should params[:ids] be missing.
Array.wrap(params[:ids]).map{|x| x.split(',')}.flatten
Apologies for piling on. But I thought I would offer a slight tweak to the answer proposed by SickLickWill (which doesn't quite handle the Array case correctly):
ids = params[:id].split(',').flatten
This will handle the String case just fine:
:001 > params = {id: "abc,efg"}
:002 > ids = params[:id].split(',').flatten
=> ["abc", "efg"]
As well as the Array case:
:003 > params = {id: ["abc","efg"]}
:004 > ids = params[:id].split(',').flatten
=> ["abc", "efg"]
If there's any chance the id param will be nil, then this barfs:
:005 > params = {}
=> {}
:006 > ids = params[:id].split(',').flatten
NoMethodError: undefined method `split' for nil:NilClass
So, you could put in a conditional test:
:007 > ids = params[:id].split(',').flatten if params[:id]
=> nil
Or, use try:
:008 > ids = params[:id].try(:split, ',').try(:flatten)
=> nil
You miss end tag and you have wrong else if and you can delete the check of params[:ids] because if :ids key do not exist is_a? return NilClass
I think you can do this
ids = if params[:ids].is_a? Array
params[:ids]
elsif params[:ids]
params[:ids].split(",")
end
I think the shortest way would be to use .try. It saves you from writing out an if-then-else.
params_id = params[:id].try(:split, ',')
is there a shorter way to do this (considering a is already set to some value):
a = b if b.present?
I may have come across a way to do this before, but don't remember.
Just a = b if b.present? on its own is functionally equivalent to:
if b.present?
a = b
else
a = nil
end
so you could use Object#presence:
presence()
Returns the receiver if it's present otherwise returns nil. object.presence is equivalent to
object.present? ? object : nil
like this:
a = b.presence
If a already has a value and you're really saying:
a = something_interesting
a = b if b.present?
then you could say:
a = b.presence || something_interesting
if b is some complex expression that you want to evaluate just once, you could use
a = b.presence || a
you could do this
a = b if !b.nil?
or
a = b if b
or
a = b if b != nil
The thing about present? is it protects you against the trap of empty arrays, hashs, and other collections. So these will work if you are not concerned about an empty collection.
You can use ||= operator, but it depends on of what you want your code to do. This operator assigns the value of b to a if b is not nil.For example, if a = 5 and perform the following operation a ||= b value of b will be assigned to a only if b is not nil, but if a was not previously declared value of a will be nil for this code a ||= b.
EXAMPLES:
irb(main):001:0> b = nil
=> nil
irb(main):002:0> a ||= b
=> nil
irb(main):003:0> b = 5
=> 5
irb(main):004:0> a ||= b
=> 5
irb(main):005:0> a ||= nil
=> 5
||= operator is what you are looking for. It checks if the operand is nil or present before assigning a value. If present doesn't assign, if nil or undefined will assign the value.
[1] pry(main)> a
NameError: undefined local variable or method `a' for main:Object
from (pry):1:in `__pry__'
[2] pry(main)> a ||= 100
=> 100
[3] pry(main)> a = nil
=> nil
[4] pry(main)> a ||= 100
=> 100
[5] pry(main)> a ||= 200
=> 100
My understanding is that ruby returns the last statement evaluated in a function. What if the function ends with an if statement that evaluates to false
def thing(input)
item = input == "hi"
if item
[]
end
end
puts thing("hi").class #> Array
puts thing("not hi").class #> NilClass
I like this functionality (returning nil if the statement is false), but why isn't false returned (from the assignment to item)?
If your if statement doesn't result in any code being run, it returns nil, otherwise it returns the value of the code that was run. irb is a good tool to experiment with such stuff:
irb(main):001:0> i = if false then end
=> nil
irb(main):002:0> i = if true then end
=> nil
irb(main):007:0> i = if false then "a" end
=> nil
irb(main):008:0> i = if false then "a" else "b" end
=> "b"
The return value of an if expression is the value of the clause that was evaluated, not of the condition. In case no clause was evaluated (if without else), nil is returned:
irb(main):001:0> x = if false
irb(main):002:1> []
irb(main):003:1> end
=> nil
irb(main):004:0> x
=> nil
irb(main):005:0>
given this:
if (params[:to].to_s =~ (/^r\+.*#site.com$/)) == nil
How can I make site.com dynamic to: #{SITE_CONFIG['mail_host']}
I tried
if (params[:to].to_s =~ (/^r\+.*##{SITE_CONFIG['mail_host']}$/)) == nil
Which did not work.. ideas?
In ruby you can create the regexp from a string representation using Regexp.new:
if (params[:to].to_s =~ Regexp.new("^r\\+.*##{Regexp.quote(SITE_CONFIG['mail_host'])}$")) == nil
Define "not work", regexes can contain interpolated strings:
pry(main)> foo = "wat"
=> "wat"
pry(main)> "ohai wat kthxbai" =~ /#{foo}/
=> 5
pry(main)> foo = "nar"
=> "nar"
pry(main)> "ohai wat kthxbai" =~ /#{foo}/
=> nil
pry(main)> /#{foo}/
=> /nar/
I'm using something like this:
case referer
when (referer.include? "some_string")
redirect_link = edit_product_path
when (referer.include? "some_other_string")
redirect_link = other_product_path
end
Unfortunately, this returns nil even if the string some_string is present in the variable referer.
Here's what i tried in Ruby Console:
ruby-1.8.7-p334 :006 > jasdeep = "RAILS"
ruby-1.8.7-p334 :026 > case jasdeep
ruby-1.8.7-p334 :027?> when (jasdeep.include? "AI")
ruby-1.8.7-p334 :028?> puts "Hello"
ruby-1.8.7-p334 :029?> end
=> nil
Any inputs will be appreciated.
Try this
jasdeep = "RAILS"
case jasdeep
when /IL/
puts "Hello"
end
jasdeep = "RAILS"
case
when jasdeep.include?("AI")
puts "Hello"
end
That nil is the returned value from the puts statement, not from .include?. Try to run the following two statements separately from the console and observe the returned value:
jasdeep.include? "AI"
puts "hello"
case true
when referer.include? "some_string"
redirect_link = edit_product_path
when referer.include? "some_other_string"
redirect_link = other_product_path
end