konung
konung

Reputation: 7038

Outputing value of TrueClass / FalseClass to integer or string/

I'm trying to figure out if there is an easy way to do the following short of adding to_i method to TrueClass/FalseClass.

Here is a dilemma: I have a boolean field in my rails app - that is obviously stored as Tinyint in mysql. However - I need to generate xml based of the data in mysql and send it to customer - there SOAP service requires the field in question to have 0 or 1 as the value of this field. So at the time of the xml generation I need to convert my False to 0 and my True to 1 ( which is how they are stored in the DB). Since True & False lack to_i method I could write some if statement that generate either 1 or 0 depending on true/false state. However I have about 10 of these indicators and creating and if/else for each is not very DRY. So what you recommend I do?

Or I could add a to_i method to the True / False class. But I'm not sure where should I scope it in my rails app? Just inside this particular model or somewhere else?

Upvotes: 6

Views: 5672

Answers (5)

Darth Egregious
Darth Egregious

Reputation: 20086

You can use:

5 - bool.to_s.length

This will always work because true.to_s is "true" and false.to_s is "false", and "true".length is 4, while "false".length is 5.

Upvotes: 0

Joshua Pinter
Joshua Pinter

Reputation: 47471

Extend TrueClass and FalseClass with humanize and to_i.

This comes up in most of my projects so I use an initializer (if you're using Rails) that adds these two helpful methods to each class, like so:

config/initializers/true_and_false.rb

class TrueClass
  def humanize
    'Yes'
  end

  def to_i
    1
  end
end

class FalseClass
  def humanize
    'No'
  end

  def to_i
    0
  end
end

Then it makes rendering true very easy for both "human consumption" and "machine consumption":

> true.humanize     #=> Yes
> true.to_i         #=> 1

> false.humanize    #=> No
> false.to_i        #=> 0

Upvotes: 5

Matijs van Zuijlen
Matijs van Zuijlen

Reputation: 468

Update: This 'solution' is dangerous and should not be used!

You can also try:

value.object_id / 2

I'm not sure how well this works across implementations.

To get rid of the duplication of having to repeat this 10 times, I would still recommend creating a method:

def boolean_to_i value
  value.object_id / 2
end

No real need to monkey-patch, though.

Upvotes: 2

mipadi
mipadi

Reputation: 410592

You could create a file such as lib/boolean_ints.rb and monkey-patch a to_i method to TrueClass and FalseClass, as you suggested. Then, in the models or controllers in which you need to use the to_i method, you could just put

require 'boolean_ints'

at the top, and they'd be available for use.

Upvotes: 5

Mark Rushakoff
Mark Rushakoff

Reputation: 258148

You could just monkeypatch the TrueClass and FalseClass in your app, near that particular model: any implementation of to_i on true and false are likely to be the same.

irb(main):004:0> true.to_i
NoMethodError: undefined method `to_i' for true:TrueClass
        from (irb):4
irb(main):005:0> class TrueClass
irb(main):006:1>  def to_i
irb(main):007:2>   1
irb(main):008:2>  end
irb(main):009:1> end
=> nil
irb(main):010:0>
irb(main):011:0* true.to_i
=> 1

But to avoid monkeypatching, is there any reason you couldn't just use the ternary operator? If that's still not DRY enough for you, wrap it up in a method.

irb(main):012:0> true ? 1 : 0
=> 1
irb(main):013:0> false ? 1 : 0
=> 0

Of course, that works with non-boolean variables as well:

irb(main):019:0* 1234 ? 1 : 0
=> 1
irb(main):020:0> nil ? 1 : 0
=> 0

Upvotes: 3

Related Questions