Ruby如何仅在对象不为nil时调用方法
我正在编写一个简单的脚本,它从 debian 网站获取一些包的详细信息。我在处理没有与之关联的版本的虚拟包时遇到问题。
我收到以下错误消息
undefined method `first' for nil:NilClass (NoMethodError)
罪魁祸首是
version = doc.css('#content h1').text.strip.scan( /\(([^>]*)\)/).last.first
我尝试将其放入这样的 if 条件中,但这不起作用。
if doc.css('#content h1').text
version = doc.css('#content h1').text.strip.scan( /\(([^>]*)\)/).last.first
end
所以我想知道如何检查对象是否不为零,然后尝试从中提取子字符串。
这是添加了 except 块的整个脚本
require 'rubygems'
require 'nokogiri'
require 'open-uri'
# additional code to make sure that we can resume after a break seamlessly
last_package = 0
File.open('lastbreak','r') { |fptr| last_package = fptr.gets.to_i }
puts "Resuming from package:#{last_package}" if last_package != 0
# to read each package from packageslist.txt and fetch the required info
# also to store this into a file that can easily be read by the c++ program
BASE_URL = "http://packages.debian.org/stable/"
File.open('packages_list.txt','r') do | fptr |
while line = fptr.gets
package_id = line.split[0].to_i
package = line.split[1]
dependencies = ""
url = BASE_URL + package
if package_id >= last_package
doc = doc = Nokogiri::HTML(open(url))
doc.css(".uldep a").each do |dependency|
dependencies << dependency.text + ","
end
dependencies = dependencies.split(',').uniq.join(',')
description = doc.css('#pdesc').text.strip
version = ""
unless doc.css('#content h1').nil?
version = doc.css('#content h1').text.strip.scan( /\(([^>]*)\)/).last.first
end
File.open("packages/#{package}","w") do |wfptr|
wfptr.puts "PackageId:#{package_id}"
wfptr.puts "Name:#{package}"
wfptr.puts "Version:#{version}"
wfptr.puts "Deps:#{dependencies}"
end
File.open("packages/#{package}.description",'w') {|wf| wf.write(description.capitalize)}
package_id += 1
puts "Now Processing #{package_id}"
File.open('lastbreak','w') { |fptr| fptr.puts "#{package_id}" }
end
end
end
,现在错误消息是
/Users/ccuser008/Documents/oops_project/repo/repobuilder.rb:30:in `block': undefined method `first' for nil:NilClass (NoMethodError)
from /Users/ccuser008/Documents/oops_project/repo/repobuilder.rb:15:in `<main>'
I'm writing a simple script, that fetches the details of some packages from the debian website. I encounter a problem when dealing with virtual packages that ave no version no associated with them.
I get the following error message
undefined method `first' for nil:NilClass (NoMethodError)
The culprit line is
version = doc.css('#content h1').text.strip.scan( /\(([^>]*)\)/).last.first
I tried to put it into an if conditional like this but that doesn't work.
if doc.css('#content h1').text
version = doc.css('#content h1').text.strip.scan( /\(([^>]*)\)/).last.first
end
So I'd like to know how I can check if the object is not nil and then try to extract the sub-string from it.
Here is the entire script with the unless block added
require 'rubygems'
require 'nokogiri'
require 'open-uri'
# additional code to make sure that we can resume after a break seamlessly
last_package = 0
File.open('lastbreak','r') { |fptr| last_package = fptr.gets.to_i }
puts "Resuming from package:#{last_package}" if last_package != 0
# to read each package from packageslist.txt and fetch the required info
# also to store this into a file that can easily be read by the c++ program
BASE_URL = "http://packages.debian.org/stable/"
File.open('packages_list.txt','r') do | fptr |
while line = fptr.gets
package_id = line.split[0].to_i
package = line.split[1]
dependencies = ""
url = BASE_URL + package
if package_id >= last_package
doc = doc = Nokogiri::HTML(open(url))
doc.css(".uldep a").each do |dependency|
dependencies << dependency.text + ","
end
dependencies = dependencies.split(',').uniq.join(',')
description = doc.css('#pdesc').text.strip
version = ""
unless doc.css('#content h1').nil?
version = doc.css('#content h1').text.strip.scan( /\(([^>]*)\)/).last.first
end
File.open("packages/#{package}","w") do |wfptr|
wfptr.puts "PackageId:#{package_id}"
wfptr.puts "Name:#{package}"
wfptr.puts "Version:#{version}"
wfptr.puts "Deps:#{dependencies}"
end
File.open("packages/#{package}.description",'w') {|wf| wf.write(description.capitalize)}
package_id += 1
puts "Now Processing #{package_id}"
File.open('lastbreak','w') { |fptr| fptr.puts "#{package_id}" }
end
end
end
now the error message is
/Users/ccuser008/Documents/oops_project/repo/repobuilder.rb:30:in `block': undefined method `first' for nil:NilClass (NoMethodError)
from /Users/ccuser008/Documents/oops_project/repo/repobuilder.rb:15:in `<main>'
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
Ruby 2.3.0 添加了一个安全导航运算符 (
&.
),用于在调用方法之前检查 nil。如果
foo
为nil
,它将返回nil
,而不是引发NoMethodError
。Ruby 2.3.0 added a safe navigation operator (
&.
) that checks for nil before calling a method.It will return
nil
iffoo
isnil
, rather than raisingNoMethodError
.取决于返回的内容 nil
doc.css('#content h1')
或doc.css('#content h1').text
或doc.css ('#content h1').text.strip.scan( /\(([^>]*)\)/).last
示例 -
您可以在 except 子句中包含适当的条件。
从你的异常
doc.css('#content h1').text.strip.scan( /\(([^>]*)\)/).last
似乎为零。所以你可以检查一下。Depends what is being returned nil
doc.css('#content h1')
ordoc.css('#content h1').text
ordoc.css('#content h1').text.strip.scan( /\(([^>]*)\)/).last
Example -
you can include the proper condition in the unless clause.
From your exception
doc.css('#content h1').text.strip.scan( /\(([^>]*)\)/).last
seems to be nil. So you can check on this.你用过试试吗?
类似 This 的内容
如果您在项目中包含 active_support 或者您正在使用 Rails 应用程序,则
将起作用。查找“try”方法的语法和文档。
更新:
仅供参考:我知道这并不真正适用于您的问题,但也许链接方法这么长而不检查其间的 null 可能与输入的文档结构耦合非常非常困难。如果 .css("#content h1").text 为空怎么办?
Have you used try?
Something like
This will work if you're including active_support in your project or if you are working in a Rails app.
Lookup the syntax and documentation of the "try" method.
Updated:
Just FYI: I know this doesnt really apply to your question, but perhaps chaining methods this long without checks for null in between is probably coupling very very hard to the input's document structure. What if .css("#content h1").text is null?
在您的情况下使用
:
有关详细信息,请参阅:
http://www.intridea.com/blog/2010/11/2/calling-methods-on-pottial-nil-objects-in-rails
Use
in your case:
For more info see:
http://www.intridea.com/blog/2010/11/2/calling-methods-on-potential-nil-objects-in-rails