Like this article? We recommend
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