newBike
newBike

Reputation: 15022

How to open String class to rewrite to_s method

I want to rewrite the to_s method so that I can print the money in number_to_currency format. How do I do it? Is there any way to print all Integer or Float variables in number_to_currency format without calling number_to_currency method?

I ran this code in the console:

require 'pry'
require 'action_view'
include ActionView::Helpers


class String
  def to_s(x)
    number_to_currency(x)
  end
end

sum = 0
0.upto(one_fifth-1) do |line_no|
  sum += lo_to_hi[line_no].last
end
ap("bottom #{one_fifth} sum:#{sum}, average #{sum/one_fifth}")

and got this exception: in `to_s': wrong number of arguments (0 for 1) (ArgumentError).

Upvotes: 0

Views: 274

Answers (3)

D.Fux
D.Fux

Reputation: 376

First, the to_s method has no argument. And it's dangerous to call other methods in to_s when you don't know if that method also calls the to_s. (It seems that the number_to_currency calls the number's to_s indeed) After several attempts, this trick may work for your float and fixnum numbers:

class Float
  include ActionView::Helpers::NumberHelper
  alias :old_to_s :to_s
  def to_s
    return old_to_s if caller[0].match(':number_to_rounded')
    number_to_currency(self.old_to_s)
  end
end

class Fixnum
  include ActionView::Helpers::NumberHelper
  alias :old_to_s :to_s
  def to_s
    return old_to_s if caller[0].match(':number_to_rounded')
    number_to_currency(self.old_to_s)
  end
end

Note that in this trick, the method uses match(':number_to_rounded') to detect the caller and avoid recursive call. If any of your methods has the name like "number_to_rounded" and calls to_s on your number, it will also get the original number.

Upvotes: 1

Saurabh
Saurabh

Reputation: 73659

As, you want to print all int and float variables in number_to_currency, you have to overwrite to_s function in Fixnum/Integer and Float class, something like following:

As pointed out by Stefan, Integer and Float have a common parent class: Numeric, you can just do:

class Numeric
  def to_s(x)
    number_to_currency(x)
  end
end

Upvotes: 0

Felipe
Felipe

Reputation: 11897

I don't think to_s should have an argument (because the definition in the parent class (probablyObject) doesn't.). You can either use to_s as it is (no arguments) or create a new method which takes an argument but isn't called to_s

In other words, if you want to override a method you have to keep the exact same method signature (that is, its name and the number of arguments it takes).

What if you try:

class String
    def to_s_currency(x)
        number_to_currency(x)
    end
end

Upvotes: 1

Related Questions