Ruby错误:未定义的方法`[]'为nil:NilClass

时间:2012-04-09 14:11:50

标签: ruby

我正在学习Ruby,我有一个我无法理解的错误。我有一个方法,它采用一个字符串数组(行)并删除所有行到包含模式的某一行。 该方法如下所示:

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。

从这条消息中我无法理解。据我所知,一些调用我的代码的代码试图访问一个非数组对象,就像它是一个数组一样。但两个版本 我的方法返回一个字符串数组(后缀和body都被设置为一个字符串数组),那为什么会有区别呢?

所以,不幸的是,由于我对Ruby的知识匮乏,我不知道如何调试这个问题。

有人在上面的代码中看到任何错误吗?或者,是否有任何人提示任何可能导致错误的错误“未定义的方法`[]'为nil:NilClass”?

修改

其他信息。我正在扩展我自己没有编写的代码(它来自于 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

我希望这会有所帮助。

编辑2

感谢Hassan的提示(使用join方法)我发现了问题! 与join方法并行存在split方法。所以

"A\nB\n".split(/\n/)

给出

["A", "B"]

然而,通过使用each_line(就像我所做的那样),最后得到每行的'\ n'。 结果

suffix.drop_while {|line| (line != "")}

删除所有行。结果是一个空字符串,显然崩溃了库 我在用。感谢Hassan表达了更为惯用的解决方案。我现在有了 以下内容:

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

它工作正常。

2 个答案:

答案 0 :(得分:1)

当您尝试像数组(或哈希)一样使用nil时会发生该异常:

irb(main):001:0> nil[0]
NoMethodError: undefined method `[]' for nil:NilClass
        from (irb):1
        from /home/mslade/rubygems1.9/bin/irb:12:in `<main>'

或在未初始化时使用变量作为数组(或散列):

irb(main):005:0> @b[0]
NoMethodError: undefined method `[]' for nil:NilClass
        from (irb):5
        from /home/mslade/rubygems1.9/bin/irb:12:in `<main>'

通过类似@b = []

的内容,查找您忽略了数组初始化的位置

如果你实际上没有使用数组,那么你正在调用的函数可能需要一个。从顶部开始扫描给定的stak转储,直到它提到你的代码行。然后调查该行,看看你可能错过了什么。

答案 1 :(得分:0)

我不知道导致异常的原因,但您的代码可能是这样的:

def remove_header_lines(lines)
  pattern = /some pat/
  index = lines.index {|lines| lines =~ pattern}

  lines = lines.drop(index+1).drop_while {|lines| line != ""} unless index.nil?

  lines.join
end