Why is
if name.eql? 'Name1' || name.eql? 'Name2'
# doSomething
end
not allowed in Ruby? What is the good practice to do this in Ruby?
What is the good practice to do this in ruby?
Parenthesizing method calls to avoid silly ambiguities.
if name.eql?('Name1') || name.eql?('Name2')
You can use a case-expression:
case name
when 'Name1', 'Name2'
# do something
when 'Name3'
# do something else
else
# if all else fails
end
ruby gives us the option to omit parenthesis and delegate the responsibility to the interpreter. what you've done is confuse the ruby interpreter because your lack of parentheses is ambiguous. Ie, ruby can't figure out what you're trying to do
this can be viewed a number of ways if we specify each parens
if(name.eql?('Name1') || name.eql?('Name2'))
if(name.eql?('Name1' || name.eql?('Name2'))
if(name.eql?('Name1')) || name.eql?('Name2')
a good practice is to specify parens when it starts to become ambiguous. Here that would mean putting them on the method arguements
if name.eql?('Name1') || name.eql?('Name2')
Related
This question already has answers here:
Difference between "and" and && in Ruby?
(8 answers)
Closed 6 years ago.
In the code below, if I replace the and in the any? statement with &&, it throws an error unexpected tIDENTIFIER, expecting '}'.
def ArrayAddition(arr)
i = 2
until i == arr.length
combinations = arr.permutation(i).to_a
return true if combinations.any?{|array| array.inject(&:+) == arr.max and !array.include? arr.max}
i+=1
end
false
end
What is going on here? Does Ruby handle these operators differently?
The operators and and && have different precedence, and are not equivalent. As such, the Ruby Style Guide advises against using and and or operators: The and and or keywords are banned. It's just not worth it. Always use && and || instead.
Due to the difference in precedence, the other operators in the expression have higher or lower comparative precedence. In this case, the argument for the Array#include? call end up binding to the wrong expression.
You can solve this by adding parentheses around the argument to the Array#include? call.
Yes. and has lower precedence than && (and almost everything else). This expression:
foo and bar baz
...is parsed like this:
foo and (bar baz)
...so Ruby knows foo is a method name (because it can't be anything else). On the other hand, this expression:
foo && bar baz
...is parsed like this:
(foo && bar) baz
...which just doesn't make sense and you get a syntax error.
Generally speaking you should use && unless you specifically want and's lower precedence, so in this case the easiest fix to the syntax error is to use parentheses around the method argument:
foo && bar(baz)
...and so:
array.inject(&:+) == arr.max && !array.include?(arr.max)
As a bonus, this is more readable as well.
For a better readability i normally prefer writing multiline-conditions in if-statements as follows:
if
something == nice and
anotherthing == bad
then
do_something
and_so_on
end
I am currently facing while-loops (at a point where i can't avoid them) and have to use multiple conditions. I tried the following and got a corresponding syntax error, unexpected keyword_do_block (SyntaxError):
while
something == nice and
anotherthing == bad
do
do_something
and_so_on
end
It turned out that the optional do-keyword can't stand alone in the next line, in opposite to the then-keyword. This is how it works -- after putting the do at the end of the preceding line:
while
something == nice and
anotherthing == bad do
do_something
and_so_on
end
For my comprehension of readability, this is probably not as readable as the corresponding if-statement, which "enforces" a newline and accentuates the indentation (again).
Did i miss an alternative syntax and/or is it probably a flaw in Ruby's syntax-design (shouldn't it be possible to put the do into the next line)?
You can use begin end while syntax, Your conditions will be at the end of the statement but as the if statement:
begin
do_something
and_so_on
end while
something == nice and
anotherthing == bad
BUT in this case it will execute once before checking the condition
You can kind of reverse it and it will work:
while
something == nice and
anotherthing == bad
begin
do_something
and_so_on
end
end
Good luck!
Hi all new to ruby is this if statement valid syntax?
if (verify_login_id = Login.where(params[:email_address], "active" =>1).select('id')# => [#<Login id: 767>]
verify_admin_id = Admin.where("login_id" => verify_login_id.first.id).exists? #=> true)
puts "trueee"
else
raise(ActiveRecord::RecordNotFound.new("Authorization is required to access this endpoint!"))
end
Although setting variable values within an if statement is syntactically valid, it is very problematic.
It can be mistakenly read as a comparison rather than assignment, and in many cases it is a result of someone trying to make a comparison and confusing the equals predicate == with the assignment operator =. That's why a lot of IDEs today mark such code as a warning and a probable error.
In your code it also seems quite unneeded... Break it into two more readable lines:
verified_login = Login.where(params[:email_address], "active" =>1).select('id').first # => [#<Login id: 767>]
if verified_login && Admin.where("login_id" => verified_login.id).exists? #=> true
puts "trueee"
else
raise(ActiveRecord::RecordNotFound.new("Authorization is required to access this endpoint!"))
end
Some more observations - your assignment to verify_login_id is not an id, but a Login object, and your assignment to verify_admin_id is not an id either - but a boolean (and you are not using it anyway). This might seem besides the point - but it adds up to an unreadable and an unmaintainable code.
No it is not a valid code. In the second line, it contains an invalid #-comment that has removed a single ) from the code. (exact snip is #=>true) and should be ) #=>true)
I've removed the comments from the code, added the missing parenthesis and the parser seems to accept it. I couldn't run it of course. So, try this one, it might work:
if (verify_login_id = Login.where(params[:email_address], "active" =>1).select('id')
verify_admin_id = Admin.where("login_id" => verify_login_id.first.id).exists?)
puts "trueee"
else
raise(ActiveRecord::RecordNotFound.new("Authorization is required to access this endpoint!"))
end
Regarding multiline condition in the if - yes, it is possible. Sometimes directly, sometimes with a small trick. Try this:
if (1+2 >=
3)
puts "as"
end
It works (at least on Ruby 1.9.3). However, this will not:
if (1+2
>=
3)
puts "as"
end
This is because of some internal specific of how Ruby interpreter/compiler is designed. In the last example, to make it work, you need to inform Ruby that the line has not ended. The following example works:
if (1+2 \
>=
3)
puts "as"
end
Note the \ added at the end of problematic line
What's the difference between these two Ruby if statements when we put a then at the end of the if statement?
if(val == "hi") then
something.meth("hello")
else
something.meth("right")
end
and
if(val == "hi")
something.meth("hello")
else
something.meth("right")
end
then is a delimiter to help Ruby identify the condition and the true-part of the expression.
if condition then true-part else false-part end
then is optional unless you want to write an if expression in one line. For an if-else-end spanning multiple lines the newline acts as a delimiter to split the conditional from the true-part
# can't use newline as delimiter, need keywords
puts if (val == 1) then '1' else 'Not 1' end
# can use newline as delimiter
puts if (val == 1)
'1'
else
'Not 1'
end
Here's a quick tip that is not directly related to your question: in Ruby, there is no such thing as an if statement. In fact, in Ruby, there are no statements at all. Everything is an expression. An if expression returns the value of the last expression that was evaluated in the branch that was taken.
So, there is no need to write
if condition
foo(something)
else
foo(something_else)
end
This would better be written as
foo(
if condition
something
else
something_else
end
)
Or as a one-liner
foo(if condition then something else something_else end)
In your example:
something.meth(if val == 'hi' then 'hello' else 'right' end)
Note: Ruby also has a ternary operator (condition ? then_branch : else_branch) but that is completely unnecessary and should be avoided. The only reason why the ternary operator is needed in languages like C is because in C if is a statement and thus cannot return a value. You need the ternary operator, because it is an expression and is the only way to return a value from a conditional. But in Ruby, if is already an expression, so there is really no need for a ternary operator.
The then is only required if you want to write the if expression on one line:
if val == "hi" then something.meth("hello")
else something.meth("right")
end
That brackets in your example are not significant, you can skip them in either case.
See the Pickaxe Book for details.
The only time that I like to use then on a multi-line if/else (yes, I know it's not required) is when there are multiple conditions for the if, like so:
if some_thing? ||
(some_other_thing? && this_thing_too?) ||
or_even_this_thing_right_here?
then
some_record.do_something_awesome!
end
I find it to be much more readable than either of these (completely valid) options:
if some_thing? || (some_other_thing? && this_thing_too?) || or_even_this_thing_right_here?
some_record.do_something_awesome!
end
# or
if some_thing? ||
(some_other_thing? && this_thing_too?) ||
or_even_this_thing_right_here?
some_record.do_something_awesome!
end
Because it provides a visual delineation between the condition(s) of the if and the block to execute if the condition(s) evaluates to true.
There's no difference at all.
And, just FYI, your code can be optimized to
something.meth( val == 'hi' ? 'hello' : 'right' )
This question already has answers here:
Difference between "and" and && in Ruby?
(8 answers)
Closed 3 years ago.
What's the difference between the or and || operators in Ruby? Or is it just preference?
It's a matter of operator precedence.
|| has a higher precedence than or.
So, in between the two you have other operators including ternary (? :) and assignment (=) so which one you choose can affect the outcome of statements.
Here's a ruby operator precedence table.
See this question for another example using and/&&.
Also, be aware of some nasty things that could happen:
a = false || true #=> true
a #=> true
a = false or true #=> true
a #=> false
Both of the previous two statements evaluate to true, but the second sets a to false since = precedence is lower than || but higher than or.
As the others have already explained, the only difference is the precedence. However, I would like to point out that there are actually two differences between the two:
and, or and not have much lower precedence than &&, || and !
and and or have the same precedence, while && has higher precedence than ||
In general, it is good style to avoid the use of and, or and not and use &&, || and ! instead. (The Rails core developers, for example, reject patches which use the keyword forms instead of the operator forms.)
The reason why they exist at all, is not for boolean formulae but for control flow. They made their way into Ruby via Perl's well-known do_this or do_that idiom, where do_this returns false or nil if there is an error and only then is do_that executed instead. (Analogous, there is also the do_this and then_do_that idiom.)
Examples:
download_file_via_fast_connection or download_via_slow_connection
download_latest_currency_rates and store_them_in_the_cache
Sometimes, this can make control flow a little bit more fluent than using if or unless.
It's easy to see why in this case the operators have the "wrong" (i.e. identical) precedence: they never show up together in the same expression anyway. And when they do show up together, you generally want them to be evaluated simply left-to-right.
and/or are for control flow.
Ruby will not allow this as valid syntax:
false || raise "Error"
However this is valid:
false or raise "Error"
You can make the first work, with () but using or is the correct method.
false || (raise "Error")
puts false or true --> prints: false
puts false || true --> prints: true
The way I use these operators:
||, && are for boolean logic. or, and are for control flow. E.g.
do_smth if may_be || may_be -- we evaluate the condition here
do_smth or do_smth_else -- we define the workflow, which is equivalent to
do_smth_else unless do_smth
to give a simple example:
> puts "a" && "b"
b
> puts 'a' and 'b'
a
A well-known idiom in Rails is render and return. It's a shortcut for saying return if render, while render && return won't work. See "Avoiding Double Render Errors" in the Rails documentation for more information.
or is NOT the same as ||. Use only || operator instead of the or operator.
Here are some reasons. The:
or operator has a lower precedence than ||.
or has a lower precedence than the = assignment operator.
and and or have the same precedence, while && has a higher precedence than ||.
Both or and || evaluate to true if either operand is true. They evaluate their second operand only if the first is false.
As with and, the only difference between or and || is their precedence.
Just to make life interesting, and and or have the same precedence, while && has a higher precedence than ||.
Just to add to mopoke's answer, it's also a matter of semantics. or is considered to be a good practice because it reads much better than ||.