Home > Articles > Programming > Ruby

  • Print
  • + Share This
From the author of

Sending Email Using Ruby

The last part of this puzzle turns out to be fairly simple, although the error handling required by the use case could end up being non-trivial. Although strictly for test-driven development it would be better to use a Mock Object to test sending the email, for simplicity I'll just send the email to myself so that I can manually check that the email was really sent.

require 'test/unit'
require 'Club'
require 'ClubEvent'
require 'Member'
require 'date'

class TC_Club < Test::Unit::TestCase
 def set_up
  @club = Club.new
  @runner1 = Member.new("Pete", "pete@mcbreen.ab.ca", "")
  @runner2 = Member.new("Peter", "", "")
  @club.add(@runner1)
  @club.add(@runner2)
  @evt = ClubEvent.new("Club AGM", Date.new(2002,4,1))
  @evt.append_description ("Annual general meeting")
  @evt.append_description ("Location: TBA")
 end
 def test_send_notice
  sent = @club.send_notice(@evt, "Pete") {
   |r,n| if n == r.name then r else nil end}
  assert_equal(1, sent, "wrong number of emails sent")
 end
end

The initial implementation of the Club class is as follows. Although it passes the unit test, it needs to be refactored to make it more readable.

require 'net/smtp'
class Club
 attr_accessor :members
 def initialize
  @members = Array.new
 end
 def add (runner)
  members << runner
 end
 def send_notice (evt, str, &comparison)
  sent = 0
  smtp = Net::SMTP.new("localhost", 25)
  smtp.start
  members.each {|r|
   selected = r.matches?(str, &comparison)
   if nil != selected then
    smtp.ready('secretary@club.ca', r.email) { |msg|
     msg.write "To: #{r.name} <#{r.email}>\r\n"
     msg.write "Subject: #{evt.name} on " +
      "#{evt.date.to_s}\r\n"
     msg.write "\r\n"
     evt.description.each { |str|
      msg.write str + "\r\n"
     }
    }
    sent += 1
   end
  }
  return sent
 end
end
  • + Share This
  • 🔖 Save To Your Account