无法将 nil 转换为字符串——编辑以重述所有失败的尝试
在我的代码中的某个时刻,我希望 current_part
有时为 nil
,并且我想运行一些代码(在 if
块内)事实并非如此。
使用 script/server --debugger
,我已经确定,当发生以下错误时,current_part
实际上是 nil
。
以下所有版本都会在第二行生成 can't conversion nil into String
错误:
#
def map_concepts_to_part(part, current_part)
if current_part
part.concepts.map { |concept| content_tag(:li, "stuff...")}.join
end
end
#
def map_concepts_to_part(part, current_part)
if test_if_exists(current_part)
part.concepts.map { |concept| content_tag(:li, "stuff...")}.join
end
end
def test_if_exists(test_subject)
test_subject rescue nil
end
#
def map_concepts_to_part(part, current_part)
if test_if_complete(current_part)
part.concepts.map { |concept| content_tag(:li, "stuff...")}.join
end
end
def test_if_complete(test_subject)
test_subject.id rescue nil
end
#
def test_if_complete(part, current_part)
unless current_part.to_s == ""
part.concepts.map { |concept| content_tag(:li, "stuff...")}.join
end
end
#
def test_if_complete(part, current_part)
unless current_part.nil?
part.concepts.map { |concept| content_tag(:li, "stuff...")}.join
end
end
#
PS,上面每个版本中的截断行是:
part.concepts.map { |concept| content_tag(:li, "Concept: “" + concept.title + "”", :class => "one_concept") + content_tag(:li, "Attached images (" + concept.images.size.to_s + ")", :class => "all_images") + content_tag(:li, "Attached docs (XX)", :class => "all_docs")}.join
At a point in my code, I expect current_part
to sometimes be nil
, and I want to run some code (inside an if
block) when that's not the case.
Using script/server --debugger
, I've established that current_part
is in fact nil
at that point when the following errors occur.
All the following versions generate the can't convert nil into String
error on the second line:
#
def map_concepts_to_part(part, current_part)
if current_part
part.concepts.map { |concept| content_tag(:li, "stuff...")}.join
end
end
#
def map_concepts_to_part(part, current_part)
if test_if_exists(current_part)
part.concepts.map { |concept| content_tag(:li, "stuff...")}.join
end
end
def test_if_exists(test_subject)
test_subject rescue nil
end
#
def map_concepts_to_part(part, current_part)
if test_if_complete(current_part)
part.concepts.map { |concept| content_tag(:li, "stuff...")}.join
end
end
def test_if_complete(test_subject)
test_subject.id rescue nil
end
#
def test_if_complete(part, current_part)
unless current_part.to_s == ""
part.concepts.map { |concept| content_tag(:li, "stuff...")}.join
end
end
#
def test_if_complete(part, current_part)
unless current_part.nil?
part.concepts.map { |concept| content_tag(:li, "stuff...")}.join
end
end
#
PS, the truncated line in each of the above is:
part.concepts.map { |concept| content_tag(:li, "Concept: “" + concept.title + "”", :class => "one_concept") + content_tag(:li, "Attached images (" + concept.images.size.to_s + ")", :class => "all_images") + content_tag(:li, "Attached docs (XX)", :class => "all_docs")}.join
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
当
current_part
为nil
时,测试current_part.to_s == ""
在我的 ruby 系统上返回true
。与其他一些语言不同,您可以说nil.to_s
和nil.nil?
并让它们工作。我认为还有其他原因导致了这个问题。你能展示更多的代码吗?(我的测试是在 ruby 1.8.6 中进行的)
编辑:环顾四周,通常导致上述错误的是诸如
"text" + nil
之类的表达式,而不是nil.to_s
。你周围有类似的东西吗?The test
current_part.to_s == ""
returnstrue
on my ruby system whencurrent_part
isnil
. Unlike some other languages, you can saynil.to_s
andnil.nil?
and have them work. I think there is something else that is causing the problem. Can you show more of the code?(My tests were in ruby 1.8.6)
Edit: Looking around, what usually causes the above error is an expression such as
"text" + nil
, notnil.to_s
. Do you have anything like that around?问题出在您的截断行中,concept.title 与加号相交。
当你这样做
并且对象中的 some_attr 为 nil 时,Ruby 不会将其自动转换为字符串。可能经常发生(!),因为 Rails 将数据库中的 NULL 值转换为 nils。解决方法是字符串内评估:
模式替换(自动截断 nil)
或数组连接(同上)
您找不到它的原因是您的“截断行”值得它自己的 5-6 行正确展开,这样就可以了您更容易发现问题。
顺便说一句,您不需要“和朋友 - 只需按字面输入即可,因为无论如何,Rails 现在都是 UTF-8。此外,当将内容传递给标签助手时,您可能会将其转换为“”这完全不是你想要的(如果助手逃脱实体 - 我不记得他们是否这样做,但 Builder 肯定这样做)。
The problem is in your truncated line where concept.title meets the plus.
When you do
and some_attr in the object is nil, Ruby won't autocast it to string. Might happen often (!) since Rails casts NULL value in the DB to nils. Workarounds are in-string evaluation:
pattern substitution (automatically truncates nil)
or array joining (idem ditto)
The reason you could not find it is that your "truncated line" deserves it's own 5-6 lines unwrapped properly, that way it would be much easier for you to spot the problem.
On a sidenote, you don't need “ and friends - just type it literally since Rails is UTF-8 nowadays anyway. Moreover, when passing stuff to tag helpers you might get this thing converted to “ which is totally not what you want (if helpers escape entities - I don't remember if they do, but Builder certainly does).
托比亚斯是对的。如果对象的任何成员为零(因为它不存在),则您无法访问该对象的任何成员。
在执行任何操作或访问任何成员变量或函数之前,必须检查 nil 值。
在cpp中,是这样的:
`
这是几乎所有编程语言中都非常常见的 NPE(空指针异常)。
Tobias is right. You cannot access any member of the object if it is nil (as it does not exist).
You must check for nil value before performing any operation or before accessing any member varible or function.
In cpp, is it like:
`
This is a very common NPE(Null Pointer Exception) in almost every programming language.
如果该对象为 nil,则您不能使用其任何成员,因为该对象本身不存在。所以比较应该是对象和nil,而不是对象和nil的成员。
这就像空指针异常。
如果未初始化,您应该使用类似于
初始化变量 x 的方法。
If the object is nil, then you can't use any of its member because the object itself does not exist. So the comparison should be of the object and nil, not a member of the object and nil.
It's like a null pointer exception.
You should use something like
to initialize the variable x if uninitialized.
这是某个部分中的局部变量吗?如果是这样,那么即使执行
current_part.nil?
也会在该变量未传递给部分时引发错误。要克服这个问题,请执行以下操作:
顺便说一句:通常,Ruby 会查找赋值语句来确定某物是否是
变量——如果尚未分配名称,那么 Ruby 会假定该名称是一个方法调用,因此如果
x
未初始化,执行以下语句将引发错误:Is that a local variable in some partial? if so, then even doing
current_part.nil?
will raise an error in case that variable is not passed to the partial.to overcome this do:
BTW: Normally, Ruby looks for an assignment statement to determine whether something is a
variable—if a name hasn’t been assigned to, then Ruby assumes that name is a method call, so executing the following statement will raise an error if
x
wasn't initialized: