Я изучаю Ruby, и у меня есть ошибка, которую я не могу понять. У меня есть метод, который принимает массив строк (строк) и удаляет все строки до определенной строки, содержащей шаблон. Метод выглядит следующим образом:Ошибка Ruby: неопределенный метод `[] 'для nil: NilClass
def removeHeaderLines(lines)
pattern = "..." # Some pattern.
# If the pattern is not there, do not drop any lines.
prefix = lines.take_while {|line| (not line.match(pattern))}
if prefix.length == lines.length then
return prefix
end
# The pattern is there: remove all line preceding it, as well as the line
# containing it.
suffix = (lines.drop_while {|line| (not line.match(pattern))}).drop(1)
return suffix
end
Это прекрасно работает, и получившиеся строки (строки) будут корректно отображаться на веб-странице Я генерирующего.
Кроме того, я хочу удалить все непустые строки, следуя шаблону. Я изменил метод следующим образом:
def removeHeaderLines(lines)
pattern = "..." # Some pattern.
# If the pattern is not there, do not drop any lines.
prefix = lines.take_while {|line| (not line.match(pattern))}
if prefix.length == lines.length then
return prefix
end
# The pattern is there: remove all line preceding it, as well as the line
# containing it.
suffix = (lines.drop_while {|line| (not line.match(pattern))}).drop(1)
# Remove leading non-empty lines.
# ADDING THIS INTRODUCES A BUG.
body = suffix.drop_while {|line| (line != "")}
return body
end
Очень удивительно (по крайней мере, для меня) это не работает. На сгенерированной веб-странице вместо содержимого я вижу сообщение об ошибке: Ошибка жидкости: неопределенный метод `[] 'для nil: NilClass.
Я не могу понять это сообщение. Насколько я понимаю, некоторый код, вызывающий мой код, пытался получить доступ к объекту без массива, как если бы он был массивом. Но обе версии моего метода возвращают массив строк (оба суффикса переменных и тела установлены в массив строк), так почему же должна быть разница?
Так, к сожалению, из-за моих скудных знаний о Ruby я не имею понятия, как отладить эту проблему.
Не видите ли кто-либо ошибку в приведенном выше коде? В качестве альтернативы, есть ли у кого-нибудь какие-либо намеки относительно того, что может вызвать ошибку «неопределенный метод» [] для nil: NilClass?
EDIT
Дополнительная информация. Я расширяю код, который я сам не написал (он исходит от Octopress, файлы plugins/include_code.rb). Оригинальный код рендеринга выглядит следующим образом:
def render(context)
code_dir = (context.registers[:site].config['code_dir'].sub(/^\//,'') || 'downloads/code')
code_path = (Pathname.new(context.registers[:site].source) + code_dir).expand_path
file = code_path + @file
if File.symlink?(code_path)
return "Code directory '#{code_path}' cannot be a symlink"
end
unless file.file?
return "File #{file} could not be found"
end
Dir.chdir(code_path) do
##################################
# I have replaced the line below #
##################################
code = file.read
@filetype = file.extname.sub('.','') if @filetype.nil?
title = @title ? "#{@title} (#{file.basename})" : file.basename
url = "/#{code_dir}/#{@file}"
source = "<figure class='code'><figcaption><span>#{title}</span> <a href='#{url}'>download</a></figcaption>\n"
source += " #{highlight(code, @filetype)}</figure>"
safe_wrap(source)
end
end
я заменил линию
code = file.read
с
code = linesToString(removeHeaderLines(stringToLines(file.read)))
, где два недостающих методы:
def stringToLines(string)
ar = Array.new
string.each_line {|line| ar.push(line)}
return ar
end
def linesToString(lines)
s = ""
lines.each {|line| s.concat(line)}
return s
end
Я надеюсь это поможет.
EDIT 2
Благодаря намеком Хасана (использовать метод присоединиться) Я нашел эту проблему! Параллельно методу соединения существует метод разделения. Так
"A\nB\n".split(/\n/)
дает
["A", "B"]
В то время как с помощью each_line (как я), один получает каждую строку с '\ п' в конце. Как следствие
suffix.drop_while {|line| (line != "")}
удаляет все строки. Результатом стала пустая строка, которая, по-видимому, сбой библиотеки , которую я использую. Благодаря Хасану для обозначения более идиоматического решения. У меня есть :
def removeHeaderLines(code)
lines = code.split(/\r?\n/)
pat = /.../ # Some pattern.
index = lines.index {|line| line =~ pat}
lines = lines.drop(index + 1).drop_while {|line| line != ""} unless index.nil?
lines.join "\n"
end
и он отлично работает.
Это поможет, если вы могли бы добавить некоторые из текста, который вы манипулируете, то люди могут сказать вам, если есть возможно, лучший способ написать свой метод в целом. –
Какая версия рубина? – DanS
Текст является исходным C-файлом. В начале каждого исходного файла в комментарии может быть добавлена лицензия GNU. Этот комментарий должен быть удален. Вторая строка этого комментария содержит строку «www.gnu.org». Поэтому мой план состоит в том, чтобы удалить все ведущие строки до www.gnu.org, а затем все непустые строки (например, * ..., * /). После окончания главного комментария есть, по крайней мере, одна пустая строка перед началом реального кода. – Giorgio