Rails 3.0/3.2: Вызывается id для nil, который по ошибке будет 4 - если вы действительно хотите идентификатор nil, используйте object_id

Я слежу за учебным пособием Кевина Скоглунда Ruby on Rails 3 Essential Training, который был написан для rails 3.0, хотя в настоящее время я использую 3.2. Он использует следующий метод в page_controller с параметром before_filter для отображения только страниц, принадлежащих родительскому объекту.

В учебнике явно используется .find_by_id, потому что если результат равен нулю, он "не вернет ошибку". Однако я получаю "Called id for no", который по ошибке был бы 4, если вам действительно нужен идентификатор id nil, используйте object_id "при попытке просмотреть страницу, где @subject был установлен на nil.

def find_subject
  if params[:subject_id]
    @subject = Subject.find_by_id(params[:subject_id])
  end
end

Фактический код, вызывающий ошибку:

def list
  @pages = Page.order("pages.position ASC").where(:subject_id => @subject.id)
end

Это что-то, что изменилось с 3.0? Если да, то каков был бы правильный способ реализовать эту функциональность в 3.2?

Ответ 1

Сообщение:

"Вызывается id для nil, что по ошибке будет 4 - если вы действительно хотите идентификатор nil, используйте object_id"

Это стандартное сообщение в Rails, в котором говорится, что вы пытались вызвать .id по значению nil.

Итак, если @subject равно nil, то это нормально, подходящее поведение для получения этого сообщения, если вы пытаетесь вызвать @subject.id.

Я бы рекомендовал, чтобы в файле вида учитывалось, что @subject может быть nil и адресовать его в том, как вы представляете информацию. Посмотрите на код и подумайте, что вы должны представлять в представлении там, если @subject есть nil.

Ответ 2

Не имея кода, с которым вы работаете, я могу ошибаться. Но если вы используете

params[:id]

Для быстрой проверки просто поставьте это перед оператором if:

puts ">>> #{params[:subject_id]}"

Если он дает вам идентификатор, я ошибаюсь...

Ответ 3

Код, который вы вставили, скорее всего, не приведет к ошибке. По вашему мнению, вы, вероятно, показываете @subject.id, который выдает эту ошибку. Вы должны получить трассировку стека, которая дает точную строку, в которой проблема включена.