无法将 nil 转换为字符串——编辑以重述所有失败的尝试

发布于 2024-08-05 15:45:10 字数 1838 浏览 0 评论 0原文

在我的代码中的某个时刻,我希望 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

[浮城] 2024-08-12 15:45:10

current_partnil 时,测试 current_part.to_s == "" 在我的 ruby​​ 系统上返回 true。与其他一些语言不同,您可以说 nil.to_snil.nil? 并让它们工作。我认为还有其他原因导致了这个问题。你能展示更多的代码吗?

(我的测试是在 ruby​​ 1.8.6 中进行的)

编辑:环顾四周,通常导致上述错误的是诸如 "text" + nil 之类的表达式,而不是 nil.to_s 。你周围有类似的东西吗?

The test current_part.to_s == "" returns true on my ruby system when current_part is nil. Unlike some other languages, you can say nil.to_s and nil.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, not nil.to_s. Do you have anything like that around?

小女人ら 2024-08-12 15:45:10

问题出在您的截断行中,concept.title 与加号相交。

当你这样做

"Foo" + some_obj.some_attr

并且对象中的 some_attr 为 nil 时,Ruby 不会将其自动转换为字符串。可能经常发生(!),因为 Rails 将数据库中的 NULL 值转换为 nils。解决方法是字符串内评估:

"Foo #{some_obj.attr_that_can_be_nil}"

模式替换(自动截断 nil)

"Foo %s" % some_obj.attr_that_can_be_nil

或数组连接(同上)

["Foo ", some_obj.attr_that_can_be_nil].join

您找不到它的原因是您的“截断行”值得它自己的 5-6 行正确展开,这样就可以了您更容易发现问题。

顺便说一句,您不需要“和朋友 - 只需按字面输入即可,因为无论如何,Rails 现在都是 UTF-8。此外,当将内容传递给标签助手时,您可能会将其转换为“”这完全不是你想要的(如果助手逃脱实体 - 我不记得他们是否这样做,但 Builder 肯定这样做)。

The problem is in your truncated line where concept.title meets the plus.

When you do

"Foo" + some_obj.some_attr

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:

"Foo #{some_obj.attr_that_can_be_nil}"

pattern substitution (automatically truncates nil)

"Foo %s" % some_obj.attr_that_can_be_nil

or array joining (idem ditto)

["Foo ", some_obj.attr_that_can_be_nil].join

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

世界如花海般美丽 2024-08-12 15:45:10

托比亚斯是对的。如果对象的任何成员为零(因为它不存在),则您无法访问该对象的任何成员。
在执行任何操作或访问任何成员变量或函数之前,必须检查 nil 值。

在cpp中,是这样的:

if(!current_part) {
执行操作
}

`
这是几乎所有编程语言中都非常常见的 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:

if(!current_part) {
perform operation
}

`
This is a very common NPE(Null Pointer Exception) in almost every programming language.

断肠人 2024-08-12 15:45:10

如果该对象为 nil,则您不能使用其任何成员,因为该对象本身不存在。所以比较应该是对象和nil,而不是对象和nil的成员。

这就像空指针异常。

如果未初始化,您应该使用类似于

x = get_some_object if x.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

x = get_some_object if x.nil?

to initialize the variable x if uninitialized.

谈下烟灰 2024-08-12 15:45:10

这是某个部分中的局部变量吗?如果是这样,那么即使执行 current_part.nil? 也会在该变量未传递给部分时引发错误。

要克服这个问题,请执行以下操作:

counter_part = defined?(counter_part) ? : counter_part : nil

顺便说一句:通常,Ruby 会查找赋值语句来确定某物是否是
变量——如果尚未分配名称,那么 Ruby 会假定该名称是一个方法调用,因此如果 x 未初始化,执行以下语句将引发错误:

irb(main):001:0> puts "yes nil" if x.nil?
#=>NameError: undefined local variable or method `x' for main:Object

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:

counter_part = defined?(counter_part) ? : counter_part : nil

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:

irb(main):001:0> puts "yes nil" if x.nil?
#=>NameError: undefined local variable or method `x' for main:Object
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文