Aran
Aran

Reputation: 3338

Errors with Ruby and File.open

Having problems with a Ruby script that uses File.Open

Here is the code that I am speaking of...

f = File.open(Socket.gethostname().gsub!(/[[:space:].]/,"")+".log","a")

The issue is the + inside of .open, it is returning a error message saying its a undefined method.

Anyone able to help?

Edit: Here is some code from the class which is causing the problem.

Not sure if this will help though.

def logExecution()
  f = File.open(Socket.gethostname().gsub!(/[[:space:].]/,"")+".log","a")
  f.puts(" [" + Time.new().to_s() + "] " +\
         File.basename($0) + " " + $*.join(" "))
  f.close
end

Upvotes: 0

Views: 580

Answers (3)

duncan
duncan

Reputation: 6283

There is more than the ruby code style that you can improve:

  • use gethostbyname, and rescue to a default
  • open the file using a block, ensures that if something throws, the file is closed

The result would be:

require 'socket'

def log_execution()
  logname = Socket.gethostbyname(Socket.gethostname).first rescue "localhost"
  File.open("#{logname}.log", 'a') do |f|
    f.puts(" [" + Time.new().to_s() + "] " + File.basename($0) + " " + $*.join(" "))
  end
end

And then you can improve further, by not reinventing the stdlib:

require 'socket'
require 'logger'

# do only once in your program
logname = Socket.gethostbyname(Socket.gethostname).first rescue "localhost"
log = Logger.new(logname)
log.level = Logger::WARN

Then just log using the standard api:

log.info("hello!")
log.warn("message!")

If you don't like the format which looks like:

W, [2009-12-05T03:05:48.764552 #22759]  WARN -- : message!

You can use log4r, which is api compatible but has more options...

Upvotes: 0

Bob Aman
Bob Aman

Reputation: 33239

First of all, there's no really compelling reason to strip dots from hostnames. "www.example.com.log" is a better filename than "wwwexamplecom.log". So my recommendation would be to use this:

def log_execution
  hostname = (Socket.gethostname() || "localhost")
  File.open(hostname + ".log", "a") do |f|
    f.puts(
      " [" + Time.new.to_s + "] " +
      File.basename($0) + " " + $*.join(" ")
    )
  end
end

But if you really must, then use this:

def log_execution
  hostname = (Socket.gethostname() || "localhost")
  File.open(hostname.gsub(".", "") + ".log", "a") do |f|
    f.puts(
      " [" + Time.new.to_s + "] " +
      File.basename($0) + " " + $*.join(" ")
    )
  end
end

Essentially, this block of code just logs the name of the command being run and the command line arguments used to invoke it. Also note, I renamed and reformatted the method to use standard Ruby coding style. The original was really awful.

Upvotes: 1

philant
philant

Reputation: 35806

What is the error message you're getting: NoMethodError: undefined method+' for nil:NilClass` ?

If yes, then Socket.gethostname().gsub!(/[[:space:].]/,"") is returning nil

How do you create your Socket ? You could try with a fully qualified domain name, i.e. "myhost.mydomain.com" instead of "myhost".

What name should your log file have ?

Upvotes: 3

Related Questions