marcamillion
marcamillion

Reputation: 33755

How do I convert boolean values to integers?

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

Answers (8)

Victor Cordeiro Costa
Victor Cordeiro Costa

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

Mikołaj Wawrzyniak
Mikołaj Wawrzyniak

Reputation: 69

It is not pure ruby solution but, You can use ActiveRecord::Type::Integer.new.cast(true)

Upvotes: 5

sawa
sawa

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

Darth Egregious
Darth Egregious

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

Andre Figueiredo
Andre Figueiredo

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

Jörg W Mittag
Jörg W Mittag

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

thebugfinder
thebugfinder

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

rudolph9
rudolph9

Reputation: 8119

inflection_point = (firm.inflection_point ? 1 : 0)

Upvotes: 76

Related Questions