Rails 3 и Oracle: настройки NLS отклоняют десятичный разделитель - PullRequest
1 голос
/ 22 ноября 2010

Я работаю с Ruby on Rails 3.0 над базой данных oracle только для чтения (подключение через oracle_enhanced_adapter).

Столкнувшись с известной проблемой «n + 1 запросов», я попробовал метод include.
В отличие от описания в руководствах Rails, в производимом втором запросе требуемые идентификаторы перечислены не как целые числа, а как строковые представления значений с плавающей запятой. Исходные идентификаторы имеют тип NUMBER.

К сожалению, настройки NLS для баз данных предназначены для Германии, включая NLS_NUMERIC_CHARACTERS, который ожидает "," в качестве десятичного разделителя. Поэтому я всегда получаю ORA-01722 ошибку , как описано здесь .

Точнее:

@var.assoc.includes(:another_assoc).where("column_1 = ?", some_value)

выходы

ActiveRecord :: StatementInvalid: OCIError: ORA-01722: неверный номер: ВЫБЕРИТЕ «TABLE_A». * FROM «TABLE_A» ГДЕ («TABLE_A». «ID» IN («1715.0», «1716.0», «1717.0», '1718,0', '1719,0', '1720,0', '1721,0'))

(мне пришлось упростить код Rail выше, так как он содержал некоторые отвлекающие детали, такие как преобразования "строка в символ")

Как уже упоминалось, база данных доступна только для чтения, поэтому используется

alter session set nls_numeric_characters = '.,'

работал напрямую с базой данных. Но я не смог найти правильный способ изменить сессию рельсов.

Все, что я нашел, казалось, ссылалось на Rails 2 или использовала устаревшие функции.
Как я могу решить это для Rails 3.0?

В качестве альтернативы: Как я могу заставить Rails (или, возможно, oracle_enhanced_adapter) преобразовать все перечисленные идентификаторы в Fixnum?

Спасибо и всего наилучшего, Тим

1 Ответ

1 голос
/ 22 ноября 2010

У нас была та же проблема с Oracle, и мы решили ее, поместив следующий код в инициализатор (поместите его в config/initializers/something.rb):

BigDecimal.class_eval do
  alias :old_to_s :to_s

  def to_s(format='F')
    old_result = self.old_to_s(format)
    (old_result[-2..-1] == ".0" ? old_result[0..-3] : old_result)
  end
end

Это вызвано типом столбца, который выиспользовать в качестве первичного ключа.Если вы объявите его как NUMBER, он будет преобразован в BigDecimal.В качестве альтернативы вы можете объявить свои идентификаторы как NUMBER(10) или что-то подобное, что более очевидно будет отображаться в FixNum (чьи идентификаторы будут преобразованы правильно).

Надеюсь, это поможет.

...