Невозможно преобразовать ноль в строку - отредактировано для повторения всех неудачных попыток - PullRequest
2 голосов
/ 22 сентября 2009

В некотором месте моего кода я ожидаю, что current_part иногда будет nil, и я хочу запустить некоторый код (внутри блока if), когда это не так.

Используя script/server --debugger, я установил, что current_part на самом деле nil в тот момент, когда возникают следующие ошибки.

Все следующие версии генерируют ошибку can't convert nil into String во второй строке:

#

  def map_concepts_to_part(part, current_part)
     if current_part
        part.concepts.map { |concept| content_tag(:li, "stuff...")}.join
      end
  end

#

  def map_concepts_to_part(part, current_part)
     if test_if_exists(current_part)
        part.concepts.map { |concept| content_tag(:li, "stuff...")}.join
      end
  end

  def test_if_exists(test_subject)
    test_subject rescue nil
  end

#

  def map_concepts_to_part(part, current_part)
     if test_if_complete(current_part)
        part.concepts.map { |concept| content_tag(:li, "stuff...")}.join
      end
  end

  def test_if_complete(test_subject)
    test_subject.id rescue nil
  end

#

  def test_if_complete(part, current_part)
     unless current_part.to_s == ""
        part.concepts.map { |concept| content_tag(:li, "stuff...")}.join
      end
  end

#

  def test_if_complete(part, current_part)
     unless current_part.nil?
        part.concepts.map { |concept| content_tag(:li, "stuff...")}.join
      end
  end

#

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

part.concepts.map { |concept| content_tag(:li, "Concept: “" + concept.title + "”", :class => "one_concept") + content_tag(:li, "Attached images (" + concept.images.size.to_s + ")", :class => "all_images") + content_tag(:li, "Attached docs (XX)", :class => "all_docs")}.join

Ответы [ 5 ]

5 голосов
/ 22 сентября 2009

Тест current_part.to_s == "" возвращает true в моей системе ruby, когда current_part равно nil. В отличие от некоторых других языков, вы можете сказать nil.to_s и nil.nil? и заставить их работать. Я думаю, что есть что-то еще, что вызывает проблему. Можете ли вы показать больше кода?

(мои тесты были в ruby ​​1.8.6)

Редактировать: Если посмотреть вокруг, то, как правило, вызывает вышеуказанную ошибку, это выражение, такое как "text" + nil, а не nil.to_s. У вас есть что-нибудь подобное?

3 голосов
/ 24 сентября 2009

Проблема в вашей усеченной строке, где concept.title встречает плюс.

Когда вы делаете

"Foo" + some_obj.some_attr

и some_attr в объекте равен nil, Ruby не будет автоматически передавать его в строку. Это может случиться часто (!), Поскольку Rails приводит значение NULL в БД к нулю. Обходные пути - строковая оценка:

"Foo #{some_obj.attr_that_can_be_nil}"

замена шаблона (автоматически обрезает ноль)

"Foo %s" % some_obj.attr_that_can_be_nil

или объединение массива (то же самое)

["Foo ", some_obj.attr_that_can_be_nil].join

Причина, по которой вы не смогли найти ее, заключается в том, что ваша "усеченная строка" заслуживает того, чтобы ее собственные 5-6 строк были развернуты должным образом, так что вам будет гораздо легче обнаружить проблему.

В отношении sidenote вам не нужно & ldquo; и друзья - просто наберите его буквально, так как Rails в любом случае сейчас является UTF-8. Более того, при передаче содержимого в теговые помощники вы можете преобразовать это в & ldquo; что совсем не то, что вы хотите (если помощники избегают сущностей - я не помню, если они делают, но Строитель, конечно, делает).

0 голосов
/ 22 сентября 2009

Это локальная переменная в некоторой части? если это так, то даже выполнение current_part.nil? вызовет ошибку, если переменная не передана в частичное.

Чтобы преодолеть это, сделайте:

counter_part = defined?(counter_part) ? : counter_part : nil

Кстати: Обычно Ruby ищет оператор присваивания, чтобы определить, является ли что-то переменная - если имя не было присвоено, то Ruby предполагает, что имя является вызовом метода, поэтому выполнение следующего оператора вызовет ошибку, если x не было инициализировано:

irb(main):001:0> puts "yes nil" if x.nil?
#=>NameError: undefined local variable or method `x' for main:Object
0 голосов
/ 22 сентября 2009

Тобиас прав. Вы не можете получить доступ к любому члену объекта, если он равен нулю (так как он не существует). Вы должны проверить значение nil перед выполнением какой-либо операции или перед доступом к любому члену переменной или функции.

В cpp это как:

if (! Current_part) { выполнить операцию }

` Это очень распространенное NPE (исключение нулевого указателя) почти во всех языках программирования.

0 голосов
/ 22 сентября 2009

Если объект имеет значение nil, то вы не можете использовать ни один из его членов, потому что сам объект не существует. Таким образом, сравнение должно быть объекта и nil, а не члена объекта и nil.

Это похоже на исключение нулевого указателя.

Вы должны использовать что-то вроде

x = get_some_object if x.nil?

для инициализации переменной x, если она не инициализирована.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...