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
