2016-11-05 3 views
1

instance_eval文字列の値を補間したい。引数alias_nameは、nilまたは文字列になることがあります。構文エラー、予期しない|| in instance_eval string

def create_document(klass, alias_name) 
    klass.instance_eval <<-EOS 
     def alias_name 
     #{alias_name} || name 
     end 
    EOS 
end 

しかし、これは実際に私の構文エラーを与えている:

Uncaught exception: (eval):2: syntax error, unexpected || 
     || name 
     ^

私はこのコードをよく見ている、それがnilであると、私は以下に示すように、文字列を返す別のメソッドを呼び出します構文エラーは表示されません。 #{alias_name}がnilまたはstringを返す場合、これが原因でエラーになるのはなぜですか?

は、すべてこの後、すべての作品:alias_nameがnilのとき

> nil || 'something else' 
=> "something else" 
> 'something' || 'something else' 
=> "something" 

が、それはまったく評価されません。それはinstance_eval文字列にはまったく存在しないので、構文エラーが発生します。しかし、たとえこれは動作しません:あなたはそれを参照してください

Uncaught exception: (eval):2: syntax error, unexpected '.' 
     if .present? 
      ^

alias_name = alias_name || "" 
klass.instance_eval <<-EOS 
    def alias_name 
    if #{alias_name}.present? 
     #{alias_name} 
    else 
     demodulized_name 
    end 
    end 
EOS 

それは、このエラーを与えるだろうか?その場合はalias_nameのように存在しません。

+1

それは '潜在的にトリッキーな、非常に危険なツールをeval'行い、このような問題です。可能であれば、 'define_method'システムや' send(alias_name) 'のようなもので試してみてください。 – tadman

答えて

2

ストリングの補間を使用して、"s #{expr} s"と等価である:

klass.instance_eval %q{ 
    def alias_name 
    || name 
    end 
} 

場合alias_name

klass.instance_eval <<-EOS 
    def alias_name 
    #{alias_name} || name 
    end 
EOS 

は次のように終わる:

's ' + expr.to_s + ' s' 

nil.to_sので、この空の文字列でありますnilまたは空のs次のようになります。

def alias_name 
    || name 
end 

は構文上正しいRubyコードです。

あなたは特別な存在だということを知らないklass.instance_evalに供給しているヒアドキュメントはそれだけで他の文字列のような文字列を構築し、盲目的#{}補間にto_sを呼び出すされ、コンテキスト「これはRubyのコードです」。

おそらく、あなたの代わりにto_sinspectを使用したい:

klass.instance_eval <<-EOS 
    def alias_name 
    #{alias_name.inspect} || name 
    end 
EOS 

あなたのようなRubyコード与える:

def alias_name 
    "pancakes" || name 
end 

alias_namenilとする場合

def alias_name 
    nil || name 
end 

alias_nameは、文字列'pancakes'です。

それともalias_name場合はinstance_eval外でテストをしたいが、他のメソッドの名前であることを意味する:

if alias_name.present? 
    klass.instance_eval <<-EOS 
    def alias_name 
     #{alias_name} || name 
    end 
    EOS 
else 
    klass.instance_eval <<-EOS 
    def alias_name 
     name 
    end 
    EOS 
end 
+0

興味深いことに、私はto_sの違いを本当に理解したことはありません。 – Donato

関連する問題