if array.present?
puts "hello"
end
There is no else part to this.
How to write the above if condition using unless.
I'm asking this question because of this lint error:
Use a guard clause instead of wrapping the code inside a conditional expression
Regarding your comment:
I'm asking this question because of this lint error
Use a guard clause instead of wrapping the code inside a conditional expression
This means that instead of:
def foo(array)
if array.present?
puts "hello"
end
end
You are supposed to use:
def foo(array)
return unless array.present?
puts "hello"
end
See https://github.com/bbatsov/ruby-style-guide#no-nested-conditionals
If this is a Rails question (is it?), you can also use blank?:
def foo(array)
return if array.blank?
puts "hello"
end
There's no reason to.
Remember: unless is the inverse of if (or !if if you rather), and is only intended to make your code easier to read.
Using unless with your expression would be incredibly awkward, because you're now moving the actual body of work to an else statement...
unless array.present?
return
else
puts "hello"
end
...which doesn't make your code any easier to read if you had stuck with a negated if:
if !array.present?
return
else
puts "hello"
end
Don't use unless here. You lose readability in exchange for virtually nothing.
One-liner:
puts "hello" unless !array.present?
However, I would recommend:
puts "hello" if array.present?
unless array.present?
return
else
puts "hello"
end
OP requested one-liner modification:
Pseudocode:
something unless condition
Therefore:
puts "hello" unless !array.present?
Related
Ruby newbie here. I've written a case statement to check whether a string parameter ends with "?", and I don't understand the result. Here's my code:
class Bob
def self.hey(phrase)
case phrase
when phrase.chars.last == "?"
'Sure.'
else
'Whatever.'
end
end
end
When I call Bob.hey("Does this cryogenic chamber make me look fat?") I get back Whatever., despite "Does this cryogenic chamber make me look fat?".chars.last == "?" evaluating to true in IRB. I can't figure out what I'm missing. Any help would be appreciated.
There's two forms of the case statement, one where you specify case expr and another where you don't. In the first form the expr value is tested against all of the branches with ===. In the second form each branch is evaluated like an if would be.
This means there's two ways to fix this. Either drop the term from the case part:
def self.hey(phrase)
case
when phrase.chars.last == "?"
'Sure.'
else
'Whatever.'
end
end
Or switch the case to focus on the important part:
def self.hey(phrase)
case phrase.chars.last
when "?"
'Sure.'
else
'Whatever.'
end
end
Another way to do this is to use a regular expression:
def self.hey(phrase)
case phrase
when /\?\z/
'Sure.'
else
'Whatever.'
end
end
Where /\?\z/ means "question mark character at end of string.
If there are only two cases, an if/else is more than enough:
if phrase.chars.last == "?"
...
else
...
end
Note that you could use end_with? :
if phrase.end_with?('?')
...
I am new to Ruby.
I need to make this script work:
puts "Do you like cats?"
ask = gets
def ask(n)
if ask == yes
return "I do too"
end
if ask == no
return "Dogs are better"
end
end
puts "#{ask(n)}"
Error message is :
pracif.rb:15:in <main>': undefined local variable or methodn' for
main: Object (NameError)
Here's a script that would work for you :
puts "Do you like cats?"
answer = gets
def ask(n)
if n == 'yes'
return "I do too"
end
if n == 'no'
return "Dogs are better"
end
end
puts ask(answer.downcase.chomp)
Explaination
As the error said you were trying to pass in a variable n which was not defined
Secondly you have a method name ask same as variable name. I've renamed the variable to answer instead
Thirdly, enclose yes and no in quotes
And finally, since you are using gets a \n gets appended like yes\n so none of your conditions would match. So i've used chomp to remove \n. And also used downcase to make input case insensitive.
EDIT
As mentioned by #Jordan in the comments, there is no reason to use string interpolation for the puts statement. So it's enough to call the method directly.
There are a bunch of issues with your code. Try something more like:
def reply(response)
return 'I do too' if response == 'yes'
return 'Dogs are better' if response == 'no'
'Invalid response!'
end
puts 'Do you like cats?'
response = gets().chomp()
puts reply(response)
Pay attention to the variable names. If you keep them descriptive, it is easier to spot mistakes.
Your script has no n local variable defined that you are passing to your ask(n) method at the end.
Rename your ask variable that your script gets from user to answer for example and pass it to your ask method at the end like so:
Updated code to fix other problem I did not see in the first run.
puts "Do you like cats?"
answer = gets.chomp
def ask(n)
(n == 'yes') ? "I do too" : "Dogs are better"
end
puts "#{ask(answer)}"
I am new to programming and I don't understand what the difference is. I am coding in Ruby.
if should be obvious: execute a block of code if the condition is true.
unless is the opposite: execute a block of code if the condition is false.
http://www.codecademy.com/glossary/ruby/if-unless-elsif-and-else
unless is equal to if not
for example:
a= false
unless a
puts "hello"
end
=> hello
if not a
puts "hello"
end
=> hello
One of the goals of Ruby language is to become more closer to the real English. And keywords if and unless are really good examples of that. Look at this:
if animal.can_speak?
animal.say 'Woof!'
end
# moreover, it can be transformed in one-line, which looks pretty awesome:
animal.say 'Woof!' if animal.can_speak?
unless is an opposite of the if and instead of writing:
if not animal.can_speak?
puts "This animal can't speak"
end
we can use unless, that usually considered as more natural way:
unless animal.can_speak?
puts "This animal can't speak"
end
# it also has one-line approach:
puts "..." unless animal.can_speak?
This is going to sound weird, but I would love to do something like this:
case cool_hash
when cool_hash[:target] == "bullseye" then do_something_awesome
when cool_hash[:target] == "2 pointer" then do_something_less_awesome
when cool_hash[:crazy_option] == true then unleash_the_crazy_stuff
else raise "Hell"
end
Ideally, I wouldn't even need to reference the has again since it's what the case statement is about. If I only wanted to use one option then I would "case cool_hash[:that_option]", but I'd like to use any number of options. Also, I know case statements in Ruby only evaluate the first true conditional block, is there a way to override this to evaluate every block that's true unless there is a break?
You could also use a lambda:
case cool_hash
when -> (h) { h[:key] == 'something' }
puts 'something'
else
puts 'something else'
end
Your code is very close to being valid ruby code. Just remove the variable name on the first line, changing it to be:
case
However, there is no way to override the case statement to evaluate multiple blocks. I think what you want is to use if statements. Instead of a break, you use return to jump out of the method.
def do_stuff(cool_hash)
did_stuff = false
if cool_hash[:target] == "bullseye"
do_something_awesome
did_stuff = true
end
if cool_hash[:target] == "2 pointer"
do_something_less_awesome
return # for example
end
if cool_hash[:crazy_option] == true
unleash_the_crazy_stuff
did_stuff = true
end
raise "hell" unless did_stuff
end
I think, following is the better way to do the stuff you want.
def do_awesome_stuff(cool_hash)
case cool_hash[:target]
when "bullseye"
do_something_awesome
when "2 pointer"
do_something_less_awesome
else
if cool_hash[:crazy_option]
unleash_the_crazy_stuff
else
raise "Hell"
end
end
end
Even in case's else part you can use 'case cool_hash[:crazy_option]' instead of 'if' if there are more conditions. I prefer you to use 'if' in this case because there is only one condition.
in ruby 3.0 you can do the following with pattern matching
# assuming you have these methods, ruby 3 syntax
def do_something_awesome = "something awesome 😎"
def do_something_less_awesome = "something LESS awesome"
def unleash_the_crazy_stuff = "UNLEASH the crazy stuff 🤪"
you can do
def do_the_thing(cool_hash)
case cool_hash
in target: "bullseye" then do_something_awesome
in target: "2 pointer" then do_something_less_awesome
in crazy_option: true then unleash_the_crazy_stuff
else raise "Hell"
end
end
will return
do_the_thing(target: "bullseye")
=> "something awesome 😎"
do_the_thing(target: "2 pointer")
=> "something LESS awesome"
do_the_thing(crazy_option: true)
=> "UNLEASH the crazy stuff 🤪"
in ruby 2.7 it still works
# need to define the methods differently
def do_something_awesome; "something awesome 😎"; end
def do_something_less_awesome; "something LESS awesome"; end
def unleash_the_crazy_stuff; "UNLEASH the crazy stuff 🤪"; end
# and when calling the code above to do the switch statement
# you will get the following warning
warning: Pattern matching is experimental, and the behavior may change
in future versions of Ruby!
I'm not a native English speaker. I know it sounds stupid nonetheless. I write in Python & C. But I can't quite understand how unless works.
Is it healthy to think of it from a logical standpoint? Eg, consider the if keyword: if condition. If condition is true, the code runs. What's the logical explanation for unless?
Is there any other way to think of it?
unless x is equivalent to if !x
Ruby unless modifier:
Syntax: code unless conditional
Executes code if conditional is false.
Example:
$var = 1
print "1 -- Value is set\n" if $var
print "2 -- Value is set\n" unless $var
$var = false
print "3 -- Value is set\n" unless $var
This will produce following result:
1 -- Value is set
3 -- Value is set
The easiest way is: unless is an opposite of if. It works in the same places (I think) as if:
foo = nil
puts "This will not show" if foo
puts "But this will" unless foo
if foo then
puts "This will not show"
end
unless foo
puts "But this will"
end
It looks nicer in the code if you write unless foo instead of if !foo - but that is only my opinion. In the longer form, you can even use else, but please, do not.
Here is a set of rules to follow to make the code more readable.
The way i think of it is to say:
"The block of code is going to be executed, unless the condition is true"
unless <condition>
<code>
end
hungry = true
unless hungry
puts "I'm writing Ruby programs!"
else
puts "Time to eat!"
end
This is the easy way to understand