Ruby, OO newb, subclassing question

I am a Ruby, OO newbie. I mostly work with databases. I am trying to use
ruby for scripting some of my routine tasks.

I am trying to sub class a File, to create a HtmlReportFile with
additional methods.

class HtmlReport < File

  def initialize(filename)
    open(filename,'w') #Don't know why this does not return a file
object
  end

  def header(title)
    html_head = <<-EOF_HTML_HEAD
      <html>
        <head><title>#{title}</title>
        </head>
        <body>
    EOF_HTML_HEAD
    puts html_head #shouldn't this write to self(file)??
  end

  def content(text)
    puts text
  end

  def footer
    puts '</body></html>'
    close
  end

end

if $0 == __FILE__
  my_report = HtmlReport.new('test.html')
  my_report.header('Test report')
  my_report.content('Some text')
  my_report.footer
end

But running the above returns the following error:

c:\code\ruby\sample>ruby test2.rb
test2.rb:11:in `write': uninitialized stream (IOError)
        from test2.rb:11:in `header'
        from test2.rb:28

Can somebody please tell me How it needs to be done.

Thanks
Saleo

···

--
Posted via http://www.ruby-forum.com/.

I am a Ruby, OO newbie. I mostly work with databases. I am trying to use
ruby for scripting some of my routine tasks.

I am trying to sub class a File, to create a HtmlReportFile with
additional methods.

class HtmlReport < File

  def initialize(filename)
    open(filename,'w') #Don't know why this does not return a file
object
  end

[snipped]

Initialize doesn't return a value; it's called when the object is
instantiated (created). So the return value from open is disappearing
into thin air.

The "correct" way to do this is to use "super" to pass the appropriate
arguments to File#initialize, like so:

  # load CGI library (for CGI.escapeHTML)
  require 'cgi'

  class HtmlReport < File
    HEADER = '<html><head><title>%s</title></head><body>'
    FOOTER = '</body></html>'

    def initialize(path)
      # call File#initialize with the correct arguments
      super(path, 'w')
    end

    def header(title)
      # HTML-escape the report title
      self.puts HEADER % CGI.escapeHTML(title)
    end

    def content(text)
      self.puts text
    end

    def footer
      self.puts FOOTER
      close
    end
  end

[snipped]

if $0 == __FILE__
  my_report = HtmlReport.new('test.html')
  my_report.header('Test report')
  my_report.content('Some text')
  my_report.footer
end

With the code I pasted above, running your test code produces a file
called test.html that looks like so:

  <html><head><title>Test report</title></head><body>
  Some text
  </body></html>

Hope that helps...

···

* Newbie (saleo@bellsouth.net) wrote:

--
Paul Duncan <pabs@pablotron.org> pabs in #ruby-lang (OPN IRC)
http://www.pablotron.org/ OpenPGP Key ID: 0x82C29562

It does return a file, but you don't do anything with it... initialize
is not used to create an instance, but only to initialize de
attributes of an instance created by Ruby when you invoke
HtmlReport.new. So you'd have to assign the opened file to an instance
variable of your classe to avoid loosing the reference to it.

But the problem is deeper than that. I would not want to subclass
File. Subclassing is cool and very attractive when you first study OO,
but it's not the right solution in many cases.

Cheers,

Luciano

···

On 2/13/07, Newbie <saleo@bellsouth.net> wrote:

  def initialize(filename)
    open(filename,'w') #Don't know why this does not return a file object
  end