2012-04-09 12 views
4

Rubyを習っていますが、理解できないバグがあります。私は文字列(行)の配列を取るパターンを含む特定の行まですべての行を削除するメソッドがあります。 次のような方法に見える:これは正常に動作し、結果の文字列(行)は、私が作成していたWebページ に正しく表示されRubyエラー:未定義メソッド `[] 'for 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 

これはうまくいきませんが、これはうまくいきません。生成されたWebページでは、コンテンツの代わりに、次のエラーメッセージが表示されます。液体エラー:未定義メソッド `[] 'for nil:NilClass

私はこのメッセージから分かりません。限り、私の理解として、私のコードを呼び出すいくつかのコードは、配列であるかのように非配列オブジェクトにアクセスしようとしました。しかし、私のメソッドの両方のバージョン は文字列の配列を返します(両方の変数の接尾辞と本文は文字列の配列に設定されています)。なぜ違いがあるのでしょうか?

残念ながら、Rubyについての私の知識が不足しているため、この問題をデバッグする方法についての手がかりはありません。

上記のコードで間違いがありますか?別の方法として、誰かが、 "undefined method [[] 'for nil:" NilClass "というエラーを引き起こす原因について何らかのヒントを持っていますか?

EDIT

追加情報。私は自分自身を書いていないコードを拡張しています( Octopress、ファイルプラグイン/ include_code.rbから来ています)。私は

code = linesToString(removeHeaderLines(stringToLines(file.read))) 

でライン

code = file.read 

を交換した

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 

2つの不足している方法は次のとおりです:元 レンダリングコードは次のようになります

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/) 

は(私が行ったように)、1が最後には '\ n' の各ラインを取得each_lineを使用して一方

["A", "B"] 

を与えます。 結果として

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 

そしてそれはうまくいきます。

+0

あなたが操作しているテキストの一部を追加することができればそれがあるのなら、人々はあなたを伝えることができます役立つだろうおそらく、あなたのメソッドを完全に書くためのよりよい方法です。 –

+0

ルビのバージョンは? – DanS

+0

テキストはCソースファイルです。各ソースファイルの先頭には、コメントにオプションのGNUライセンスがあります。このライセンスコメントは削除する必要があります。このコメントの最後の2行目には文字列 "www.gnu.org"が含まれています。だから私の計画はwww.gnu.orgまでのすべての先導的な行を削除してから空でない行(*、* /など)をすべて削除することです。先頭のコメントの終わりの後、実際のコードの開始前に少なくとも1つの空行があります。 – Giorgio

答えて

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 
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 = []

ようなもので、配列をinitalizeすることを怠ってきた、トンのため

ルックそれはあなたが呼んでいるファンクションが期待している可能性があります。指定されたstakダンプをスキャンし、コードの行が記述されるまで上から開始します。その行を調べて、あなたが逃したかもしれないものを見てください。

+0

@は変数名の前に何を意味していますか?それは配列に必要ですか? – Giorgio

+0

接頭辞 '@ 'の変数はインスタンス変数です。 –

関連する問題