Template Method Pattern (GoF) without abstract methods in Ruby

Michael Schwarze <[email protected]>
Newsgroups gmane.comp.lang.ruby.general
Message-ID <[email protected]>
Hi!

I have some questions re. the Template Method Pattern (GoF) in Ruby.

I need to update a simple management reporting system and have to add HTML to the so far text-based reports. Looks to me like the classical use case for the Template Method Pattern. I learned from Russ Olsen’s book »Design Patterns in Ruby« that we do not have / use / „make up“ abstract methods in Ruby. But a lot of infos concerning this topic on the web use these 'abstract‘ methods by raising some kind of error upon calling the methods (see [1, 2, 3]).

Does anybody out there in real ruby code bases actually use this approach with made up 'abstract‘ methods?

I’ve come up with three simple and obviously contrived example implementations without using abstract methods (and without meta programming):
a) Inheritance from a simple(r) use case [4]
b) Inheritance from an 'abstract‘ class [5]
c) Composition by mixin of an 'abstract' module with the concerning template method(s) [6]

Anything I might have missed here? And which way is most idiomatic Ruby (if at all;-)

Many thanks!

Cheers,
Michael


~~~
[1]: https://medium.com/@dljerome/design-patterns-in-ruby-template-method-753443f5a1c8
[2]: https://github.com/pruett/ruby-patterns/blob/master/patterns/template_method.md
[3]: https://stackoverflow.com/questions/12873873/ruby-base-class-call-child-class-like-in-abstract-classes/12873925#12873925

[4]: Example 1 - Inheritance from a simple(r) use case:
# Represents a simple (text) report
class Report
  def initialize
    @title = 'My Report'
    @text = ['Line 1', 'Line 2.']
  end

  def output_report
    output =  head
    output << body
    output << footer

    output
  end

  def head
    "#{@title}\n"
  end

  def body
    output = ''
    @text.each do |line|
      output << "#{line}\n"
    end

    output
  end

  def footer
    ''
  end
end

# Represents an HTML report, inherits from the simple text report
class HTMLReport < Report
  def head
    <<~HTML
      <html>
      <head>
      <title>#{@title}</title>
      </head>
    HTML
  end

  def body
    output = "<body>\n"
    @text.each do |line|
      output << "<p>#{line}</p>\n"
    end
    output << "</body>\n"

    output
  end

  def footer
    "</html>\n"
  end
end

[5]: Example 2 - Inheritance from an 'abstract‘ class:
# Represents an abstract report / template method(s)
class Report
  def initialize
    @title = 'My Report'
    @text = ['Line 1', 'Line 2.']
  end

  def output_report
    output =  head
    output << body
    output << footer

    output
  end
end

# Represents a text report
class TextReport < Report
  def head
    "#{@title}\n"
  end

  def body
    output = ''
    @text.each do |line|
      output << "#{line}\n"
    end

    output
  end

  def footer
    ''
  end
end

# Represents an HTML report
class HTMLReport < Report
  def head
    <<~HTML
      <html>
      <head>
      <title>#{@title}</title>
      </head>
    HTML
  end

  def body
    output = "<body>\n"
    @text.each do |line|
      output << "<p>#{line}</p>\n"
    end
    output << "</body>\n"

    output
  end

  def footer
    "</html>\n"
  end
end

[6]: Example 3 - Mixin of an 'abstract' module with the template method(s):
# Template method(s) for a report
module Report
  def initialize
    @title = 'My Report'
    @text = ['Line 1', 'Line 2.']
  end

  def output_report
    output =  head
    output << body
    output << footer

    output
  end
end

# Represents a text report
class TextReport
  include Report

  def head
    "#{@title}\n"
  end

  def body
    output = ''
    @text.each do |line|
      output << "#{line}\n"
    end

    output
  end

  def footer
    ''
  end
end

# Represents an HTML report
class HTMLReport
  include Report

  def head
    <<~HTML
      <html>
      <head>
      <title>#{@title}</title>
      </head>
    HTML
  end

  def body
    output = "<body>\n"
    @text.each do |line|
      output << "<p>#{line}</p>\n"
    end
    output << "</body>\n"

    output
  end

  def footer
    "</html>\n"
  end
end


Unsubscribe: <mailto:[email protected]?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-talk>
signature.asc (application/pgp-signature, 833 B)
-----BEGIN PGP SIGNATURE-----

iQIzBAEBCgAdFiEE78Xb8K/0Nf8MzAJdI9hGZAGIlMEFAlw3dvwACgkQI9hGZAGI
lMH8lg/8DXtigvb/DiidNhcz0P56kfHqLXvjwpXq2QYsNsAFbiGr4Tq/W1BZ4nir
kSjyl1G2J0O9W4sK4scUVcrl/ZgFelNzrxVcpxIdhpk70Sjd3bB4CD17pADlwB47
H87RW7LajAQB+GnZf6FWEZs7PlXTjdKm5SJ3oRExIN45JXdBICZ2mgYNEN7nOT0B
5HV4VzVFgUH/a9xSy2O7QqQVhLTbzydXddhUqrD/sBwkl1uggUrLRma7+5iV7R5N
qa4hkeiDsBrgBi5DhrAza0gBG9ngsAloj0FXYx/jK8llSBIxA7Ri7bUyyo/nvWqa
zkrkT4cYD+vHkt44ZElzKvHpNmzBFV1OEwoe6nDpBK5JSba9c9EUb8kRdq2gwQNl
5Z18rKgoccyFYOE+G8i8MrjRA64eWo0HRMYZ35dcIgsanJv9axUKNB2bFv9/uBML
dsaGcLiqdCuairz3MuudGycpla1yqMjTQgBgahz+tCWBMEK6v8bvY8c2qSfLAzM3
BYnaYwYYtFJJerNnPa4ZdPX5lCxHWY0K0LEgsI7gemfhm+tmZw2oGhl3MQLTDUlL
ViLHMPOjzKJMMRaq2JPS6/gMwE9x6pJkDlTB4oQl+DlBZv0ue5zOCEuEDmk6QC4G
Glxi3KQPSxPq662HW1L5Xj+wu1JCSxKwoymlW7STHnOCwC2qyXw=
=SsLa
-----END PGP SIGNATURE-----
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.