Ruby如何在对象不为nil时调用方法

时间:2011-10-17 07:49:56

标签: ruby methods undefined null

我正在编写一个简单的脚本,从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

所以我想知道如何检查对象是否为零,然后尝试从中提取子字符串。

这是包含除非块

的整个脚本
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>'

4 个答案:

答案 0 :(得分:9)

Ruby 2.3.0添加了一个安全导航操作符foo&.bar ),在调用方法之前检查nil。

nil

如果foonil,则会返回NoMethodError,而非提出$("document").ready(function() { $('#remove_cv').click(removeCV); }); function completeHandler(event){ var response = JSON.parse(event.target.responseText); $('#remove_cv').removeAttr('disabled').attr('data-id', response.document_id); console.log($('#remove_cv').attr('data-id')); } function removeCV(){ var document_id = $(this).data('id'); // Fire Ajax call to delete the document $.ajax({ type: 'DELETE', url: getDomain() + 'documents/' + document_id, dataType: 'json', cache: false, success: function(data, textStatus){ $('#remove_cv').attr('disabled', 'disabled'); } }); }

答案 1 :(得分:2)

取决于doc.css('#content h1')doc.css('#content h1').textdoc.css('#content h1').text.strip.scan( /\(([^>]*)\)/).last

返回的内容

示例 -

unless doc.css('#content h1').text.strip.scan( /\(([^>]*)\)/).last.nil?
    version = doc.css('#content h1').text.strip.scan( /\(([^>]*)\)/).last.first
end

您可以在unless子句中包含适当的条件。

从您的例外doc.css('#content h1').text.strip.scan( /\(([^>]*)\)/).last似乎是零。所以你可以检查一下。

答案 2 :(得分:2)

你用过试试吗?

这样的东西
doc.css('#content h1').text.strip.scan( /\(([^>]*)\)/).last.try(:first)

如果您在项目中包含active_support或者您正在使用Rails应用程序,这将有效。

查找“try”方法的语法和文档。

更新:

x = doc.css('#content h1').text.strip.scan( /\(([^>]*)\)/).last
version = x.first if !x.nil? # why bother.

仅供参考:我知道这并不适用于您的问题,但是如果将这些方法链接起来而不检查其间的null,则可能非常难以与输入的文档结构耦合。如果.css(“#content h1”)。text为null?

答案 3 :(得分:-1)

使用

try(method, *args, &block)

在你的情况下:

doc.css('#content h1').text.strip.scan( /\(([^>]*)\)/).last.try(:first)

有关详细信息,请参阅:

http://www.intridea.com/blog/2010/11/2/calling-methods-on-potential-nil-objects-in-rails