Переопределить BigDecimal to_s по умолчанию в Ruby

Когда я извлекаю данные из таблицы базы данных, массив заполняется. Некоторые поля определены как десятичные и денежные поля, а в массиве они представлены как BigDecimal.

Я использую эти значения массива для заполнения CSV-файла, но проблема в том, что все значения BigDecimal по умолчанию представлены в научном формате (что является поведением по умолчанию метода BigDecimal to_s). Я могу показать значения, используя to_s('F'), но как я могу переопределить значение по умолчанию?


person Skoppensboer    schedule 25.02.2010    source источник


Ответы (3)


Это основано на ответе @Farrel, но без загрязнения пространства имен метода бесполезным методом old_xyz. Кроме того, почему бы не использовать аргументы по умолчанию напрямую?

class BigDecimal
  old_to_s = instance_method :to_s

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

В Ruby 1.8 это становится немного уродливее:

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

Или, если вам не нравится предупреждение, которое вы получаете с приведенным выше кодом:

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
person Jörg W Mittag    schedule 26.02.2010
comment
Пробовал этот код, но получил синтаксическую ошибку, неожиданное '=', ожидая tCOLON2 или '[' или '.' в строке define_method - person Skoppensboer; 12.03.2010
comment
@Skoppensboer: необязательные параметры с аргументами по умолчанию для блоков — это функция Ruby 1.9. Как и синтаксис block.(foo). В Ruby 1.8 вам нужно использовать другое решение для предоставления аргумента по умолчанию, и вам нужно использовать метод call. - person Jörg W Mittag; 12.03.2010
comment
Спасибо, Йорг, думал, что это может быть так, но, ребята, я пытаюсь помочь, все еще на 1.8.7. - person Skoppensboer; 15.03.2010

Руби делает это легко. Вот:

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.

Этот метод называется исправлением обезьяны. Как вы могли догадаться из названия, это то, что вы должны использовать с осторожностью. Однако такое использование кажется мне разумным.

person David Seiler    schedule 25.02.2010

person    schedule
comment
Великолепно! Спасибо, Фаррел и Дэвид, я знал, что это возможно, просто не знал, как это сделать. - person Skoppensboer; 26.02.2010
comment
Пожалуйста, не делайте этого. Он излишне загрязняет пространство имен BigDecimal совершенно бесполезным методом old_to_s. - person Jörg W Mittag; 26.02.2010