Override BigDecimal to_s default in Ruby

2019-05-23 12:29发布

As I retrieve data from a database table an array is populated. Some of the fields are defined as decimal & money fields and within the array they are represented as BigDecimal.

I use these array values to populate a CSV file, but the problem is that all BigDecimal values are by default represented in Scientific format (which is the default behaviour of the BigDecimal to_s method). I can show the values by using to_s('F'), but how can I override the default?

3条回答
Viruses.
2楼-- · 2019-05-23 13:05

Ruby makes this easy. Behold:

class BigDecimal
  def to_s
    return "Whatever weird format you want"
  end
end

# Now BigDecimal#to_s will do something new, for all BigDecimal objects everywhere.

This technique is called monkey patching. As you might guess from the name, it's something you should use cautiously. This use seems reasonable to me, though.

查看更多
劳资没心,怎么记你
3楼-- · 2019-05-23 13:12
class BigDecimal
  alias old_to_s to_s

  def to_s( param = nil )
      self.old_to_s( param || 'F' )
   end
end
查看更多
爱情/是我丢掉的垃圾
4楼-- · 2019-05-23 13:31

This is built on @Farrel's answer, but without polluting the method namespace with a useless old_xyz method. Also, why not use default arguments directly?

class BigDecimal
  old_to_s = instance_method :to_s

  define_method :to_s do |param='F'|
    old_to_s.bind(self).(param)
  end
end

In Ruby 1.8, this gets slightly uglier:

class BigDecimal
  old_to_s = instance_method :to_s

  define_method :to_s do |param|
    old_to_s.bind(self).call(param || 'F')
  end
end

Or, if you don't like the warning you get with the above code:

class BigDecimal
  old_to_s = instance_method :to_s

  define_method :to_s do |*param|
    old_to_s.bind(self).call(param.first || 'F')
  end
end
查看更多
登录 后发表回答