nikhil nikhil - 4 years ago 96
Ruby Question

Ruby how to call a method only when the object is not nil

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

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'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 = ""'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 + ","
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"packages/#{package}","w") do |wfptr|
wfptr.puts "PackageId:#{package_id}"
wfptr.puts "Name:#{package}"
wfptr.puts "Version:#{version}"
wfptr.puts "Deps:#{dependencies}"
end"packages/#{package}.description",'w') {|wf| wf.write(description.capitalize)}

package_id += 1
puts "Now Processing #{package_id}"'lastbreak','w') { |fptr| fptr.puts "#{package_id}" }

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>'

Answer Source

Depends what is being returned nil doc.css('#content h1') or doc.css('#content h1').text or doc.css('#content h1').text.strip.scan( /\(([^>]*)\)/).last

Example -

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

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.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download