Reputation: 33755
I have a boolean value to check if it is true, then set a local variable. How do I refactor this so it is more Ruby-ish?
if firm.inflection_point
inflection_point = 1
else
inflection_point = 0
end
Upvotes: 41
Views: 43301
Reputation: 2184
I just noticed a lot of people proposed to Monkey Patch the ruby classes and implement the .to_i
method on them in order to solve this problem.
I need to gently inform that the act of Monkey Patching the TrueClass
and FalseClass
can be dangerous to your system
A good approach is to use the Ruby Refinements in order to make a much safer monkey patching. This approach restrict the changes on the monkey patched classes to the scope of your class.
lib/refinements/boolean_refinements.rb
module BooleanRefinements
refine FalseClass do
def to_i
0
end
end
refine TrueClass do
def to_i
1
end
end
end
/your_class.rb
require 'refinements/boolean_refinements'
class MyClass
using BooleanRefinements
# Here you can use true.to_i and false.to_i as you wish
end
Upvotes: 5
Reputation: 69
It is not pure ruby solution but, You can use ActiveRecord::Type::Integer.new.cast(true)
Upvotes: 5
Reputation: 168081
If you just have that at one point, then rudolph9's answer is good, but if you are having a similar kind of logic all over the place, then maybe it might make sense with general use in mind to monkey patch:
class FalseClass; def to_i; 0 end end
class TrueClass; def to_i; 1 end end
inflection_point = firm.inflection_point.to_i
Within Ruby, you should keep all of your logic dealing with truth values rather than 0
and 1
, but I guess you are dealing with some inputs or outputs from/to some external system that deals with 0
and 1
. Then, doing like this will make sense.
Upvotes: 25
Reputation: 20086
Here's another method:
5 - bool.to_s.length
This takes advantage of the fact that 'true'
has four characters, while 'false'
has 5.
Upvotes: 3
Reputation: 13425
Another alternative is use of short-circuit operators:
inflection_point && 1 || 0
irb(main):001:0> true && 1 || 0
=> 1
irb(main):002:0> false && 1 || 0
=> 0
Upvotes: 32
Reputation: 369428
In Ruby, if
is an expression. There's no need to assign to a variable inside the then
and else
branches, just return the value you want and assign the variable to the result of the if expression
:
inflection_point = if firm.inflection_point
1
else
0
end
In simple cases like this, it's more readable to write the entire expression on a single line:
inflection_point = if firm.inflection_point then 1 else 0 end
You can also use the conditional operator, which I personally find to be much less readable:
inflection_point = firm.inflection_point ? 1 : 0
Upvotes: 8
Reputation: 334
What you need is a conditional operation that is known as Ternary Operator It's used in almost every language and it uses the symbols ? and :
inflection_point = firm.inflection_point ? 1 : 0
basically means, if the first condition evaluates to true (firm.inflection_point), return the value after "?" (1) otherwise, return the value after ":" (0)
Upvotes: 5