我想在instance_eval
字符串中插入一个值。参数alias_name
有时可以是nil或字符串。如果它是nil,那么我调用另一个返回字符串的方法,如下所示:
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
^
我正在仔细查看此代码,但我没有看到语法错误。如果#{alias_name}
返回nil或string,为什么会导致错误?
毕竟这一切都有效:
> nil || 'something else'
=> "something else"
> 'something' || 'something else'
=> "something"
当alias_name
为零时,根本不会对其进行评估。它就像在instance_eval字符串中只是不存在一样,导致语法错误。但即使这样也行不通:
alias_name = alias_name || ""
klass.instance_eval <<-EOS
def alias_name
if #{alias_name}.present?
#{alias_name}
else
demodulized_name
end
end
EOS
会出现此错误:
Uncaught exception: (eval):2: syntax error, unexpected '.'
if .present?
^
你知道吗?它好像alias_name
不存在。
答案 0 :(得分:2)
使用字符串插值时,"s #{expr} s"
相当于:
's ' + expr.to_s + ' s'
和nil.to_s
是一个空字符串,所以:
klass.instance_eval <<-EOS
def alias_name
#{alias_name} || name
end
EOS
结束如:
klass.instance_eval %q{
def alias_name
|| name
end
}
当alias_name
为nil
或空字符串时:
def alias_name
|| name
end
在语法上不是正确的Ruby代码。
你正在向klass.instance_eval
提供的heredoc不知道有任何特殊的“这是Ruby代码”上下文,它只是像任何其他字符串一样构建一个字符串并盲目地调用to_s
关于#{}
插值。
也许您想使用inspect
代替to_s
:
klass.instance_eval <<-EOS
def alias_name
#{alias_name.inspect} || name
end
EOS
这将为您提供类似以下的Ruby代码:
def alias_name
nil || name
end
alias_name
为nil
时:
def alias_name
"pancakes" || name
end
当alias_name
是字符串'pancakes'
时。
或许您希望在instance_eval
之外进行测试,如果alias_name
是另一种方法的名称:
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