I just started learning ruby, but there's something I noticed.
In JavaScript the else block isn't really needed. So you can do something like
if (condition){
// do something
return
}
//do something else
return
instead of
if (condition){
// do something
return
} else {
//do something else
return
}
is this possible in Ruby ?
Yes, it is possible to use if without else in Ruby.
Here are some examples
class Demo
def example1
if condition
do_something
end
continue
end
def example2
do_something if condition # as modifier
continue
end
def example3
do_something unless condition # syntactic sugar for if !(condition)
continue
end
end
For a full tutorial please have a look here.
Please keep in mind, that example1 is (sometimes) concidered a bad coding style by the Ruby Style Guide.
Related
I see two styles of writing the same thing:
def find_nest(animal)
return unless animal.bird?
GPS.find_nest(animal.do_crazy_stuff)
end
vs
def find_nest(animal)
if animal.bird?
GPS.find_nest(animal.do_crazy_stuff)
end
end
Which one is more correct/preferable/following-best-practises? Or it does not matter?
As per Ruby style guide,
Prefer a guard clause when you can assert invalid data. A guard clause
is a conditional statement at the top of a function that bails out as
soon as it can.
# bad
def compute_thing(thing)
if thing[:foo]
update_with_bar(thing)
if thing[:foo][:bar]
partial_compute(thing)
else
re_compute(thing)
end
end
end
# good
def compute_thing(thing)
return unless thing[:foo]
update_with_bar(thing[:foo])
return re_compute(thing) unless thing[:foo][:bar]
partial_compute(thing)
end
It is obviously a matter of personal preference. But I prefer the early return. Not only does it make code "flatter" and easier to read, it also scales well with the number of checks. For example:
def create_terms_of_service_notification
return if Rails.env.test?
return if current_user.accepted_tos?
# imagine 5 more checks here.
# Now imagine them as a mess of nested ifs.
# create the notification
end
This :}
def find_nest(animal)
GPS.find_nest(animal.do_crazy_stuff) if animal.bird?
end
is there a way to shorten this line on Ruby?
if (res = bla_permission_invalid).is_a? String then return res end
on
def something # many things that like this
if (res = bla_permission_invalid).is_a? String then return res end
# do something else
return true
end
when the content of bla_permission_invalid are something like
def bla_permission_invalid
return invalid_address_report_func if invalid_address?
return permission_error_report_func if #user.not_one_of? [ :group1, :group2 ]
return nil
end
invalid_adress_report_func and permission_error_report_func returns string
If possible values are String and NilClass, then the code can be simplified to this:
def something
res = bla_permission_invalid()
return res if res # strings are truthy, so they'll be returned but nil will proceed
# do something else
true
end
def something
bla_permission_invalid || (
# do something else
true)
end
For fun, one could rewrite your something method like this:
def something
true.tap do
bla_permission_invalid.tap { |res| return res if res.is_a? String }
# do something else (thx Sergio)
end
end
But more importantly, Mark Thomas deserves credit for his observation, that the problem at hand should be solved by using custom exceptions.
Error code approach is good in languages that don't have exceptions. Ruby has them.
Mark Thomas already noted in his comment that it looks like you're trying to handle errors on your own using some kind of string identifier. You could use exceptions instead:
class AddressError < StandardError; end
class PermissionError < StandardError; end
def something
bla_permission_invalid
# do something
true
end
def bla_permission_invalid
raise AddressError if invalid_address?
raise PermissionError if #user.not_one_of? [ :group1, :group2 ]
end
In the above code something calls bla_permission_invalid, performs its work and returns true. If an exception is raised in bla_permission_invalid, it automatically propagates up the call stack, you don't have to explicitly return it from something.
To handle the exception:
begin
something
rescue AddressError
# handle address error
rescue PermissionError
# handle permission error
end
is there a way to pass a code block as a ruby if condition?
I have a list of regular expressions and I want to check if a message matches any of them and then do something accordingly or else do something different.
Here is an example snippet for how I think it should be written:
msg_values.each do |msg|
if (SKIP_MSG_ARRAY.each { |regular_exp| return true if msg.match(regular_exp)})
# do something
else
# do something else
end
end
is it possible? or else what is the best way of writing something like this?
Use Enumerable#any?. See the reference docs: http://ruby-doc.org/core-2.0/Enumerable.html. This method (as well as Enumerable#all?) will return true or false.
Example:
msg_values.each do |msg|
if (SKIP_MSG_ARRAY.any? { |regular_exp| msg.match(regular_exp)})
# do something
else
# do something else
end
end
I've always been searching for something like Python's while / else struct in Ruby to improve my code.
That means that the loop is executed and if the condition in the loop hasn't been true any time, then it returns the value in the else statement.
In ruby, I can do like this :
if #items.empty?
"Empty"
else
#items.each do |item|
item
end
end
So is there a way to improve this ?
Thank you in advance.
Remember that the iterator block returns what you put into it, which can be tested for further use.
if arr.each do |item|
item.some_action(some_arg)
end.empty?
else_condition_here
end
Hm, you could write it as a ternary:
#items.empty? ? 'Empty' : #items.each { |item| item }
You may want to do something more useful in your block though, since each is executed for its side effects and returns the original receiver.
Update as per your comment: I guess the closest you could get is something like
unless #items.empty?
#items.each { |item| p item }
else
'Empty'
end
Since we are in Ruby, let's have fun. Ruby has powerful case construct, which could be used such as this:
case items
when -:empty? then "Empty"
else items.each { |member|
# do something with each collection member
}
end
But to make the above code work, we have to modify the native class Symbol first. Modification of native classes is Ruby specialty. This needs to be done only once, typically in a library (gem), and it helps you ever after. In this case, the modification will be:
class Symbol
def -#
Object.new
.define_singleton_method :=== do |o| o.send self end
end
end
This code overloads the unary minus (-) operator of Symbol class in such way, that saying -:sym returns a new empty object monkey patched with :=== method, that is used behind the scenes by the case statement.
A more or less functional way:
empty_action = { true => proc{ "Empty"},
false => proc{ |arr| arr.each { |item| item }} }
empty_action[#items.empty?][#items]
I have a background from languages which use {} to say that these are "block of statements" but i am learning ruby and really confused how it being done there.
So lets say in C i have
if ( condition )
{
statement1;
statement2;
}
else if (condition)
{
statement1;
statement2;
// nested if
if (condition)
{
dosomethinghere;
}
}
else
{
statement1;
statement2;
}
How i can put this code in ruby? and also mention how to understand synomenous of "{}" in ruby, thanks.
Well, to answer your first question:
if ( condition )
statement1
statement2
elsif (condition)
statement1
statement2
// nested if
if (condition)
dosomethinghere
end
else
statement1
statement2
end
The syntax rule for if statement is:
if expr [then]
expr...
[elsif expr [then]
expr...]...
[else
expr...]
end
Where everything between [] is optional
However, and in other direction, you can also create and pass code blocks, check this post to read more about this topic.
The ruby syntax for if is:
if condition
body
else
alternativa body
end
Or
if condition then body else alternative body end
It's the same for while loops except with do instead of then.
{ and } are used to pass anonymous functions (confusingly called "blocks" in ruby) as arguments to methods.
I'd suggest getting a decent book and sitting down and reading the first few chapters this should cover everything you asked here and a lot more. I'd suggest http://oreilly.com/catalog/9780596529864 although if you're trying to get something done really quick http://www.troubleshooters.com/codecorn/ruby/basictutorial.htm is quite a good brief intro to get you started.
in Ruby, the opening brace is implied after an if. to close the block, you use an end instead of a close brace. the only other difference is you use elsif (condition) instead of else if (condition).
If you're thinking "how do I create a new variable scope in Ruby"? ie:
{
var myvar = 1;
}
myvar = 2; // compile error because myvar isn't in this scope!
I'm not really sure how you would do that.
try running the following:
def example(x,y)
puts "X:#{x},Y:#{y}"
if ( x == 0 ) then
puts "Its true"
elsif (x == 1)
puts "Its not true"
puts "it certainly isn't"
if (y == 0) then
puts "i'm the nested if"
end
else
puts "i made it to the default case"
puts "freedom"
end
puts
end
example(0,0)
example(1,0)
example(1,1)
example(2,2)
If you want a scope you can define your own scope method:
def scope
yield
end
# use like this
scope {
x = 5
puts x #=> 5
}
x #=> undefined local variable
EDIT: for a better approach to 'scopes' in Ruby 1.9 see: http://banisterfiend.wordpress.com/2010/01/07/controlling-object-scope-in-ruby-1-9/