27.02.2013 Views

Rails%203%20In%20Action

Rails%203%20In%20Action

Rails%203%20In%20Action

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

316 CHAPTER 12 Sending email<br />

Let’s now create a new folder at app/observers so that you can also reduce clutter<br />

in the app/models folder. All the files inside the app directory are added to the load<br />

path, so they will be require’able by your application. Inside the app/observers folder<br />

you create a new file called comment_observer.rb that will hold the code for the observant<br />

observer. In this file, put this:<br />

class CommentObserver < ActiveRecord::Observer<br />

def after_create(comment)<br />

(comment.ticket.watchers - [comment.user]).each do |user|<br />

Notifier.comment_updated(comment, user).deliver<br />

end<br />

end<br />

end<br />

This defines the observer that watches the Comment model and defines a method that<br />

will be called after a new Comment is saved to the database, more commonly known as<br />

the after_create callback.<br />

At the top of the after_create method, you get the list of watchers for a ticket and<br />

remove the user who has just made the comment from that list, because they<br />

shouldn’t receive an email for a comment they just created!<br />

The Notifier referenced inside the after_create is something you’ll create in a<br />

little while. Consider it similar to an Active Record object, but for handling emails<br />

instead. The comment_updated method will build an email for each of the users watching<br />

this ticket, and deliver will send it out.<br />

There’s a little bit of configuration you must do before this observer is used, however.<br />

You must open config/application.rb and put this line inside the Ticketee<br />

::Application class definition:<br />

config.active_record.observers = :comment_observer<br />

By calling this method, you are telling Rails to load the CommentObserver class, which<br />

it will find without your help, because Rails will infer the name of the observer from the<br />

symbol passed in. When you run bin/cucumber features/ticket_notifications<br />

.feature, you’re told this:<br />

And I press "Create Comment"<br />

undefined method `watchers' for # (NoMethodError)<br />

In this after_create method in your observer, you’re calling the watchers method to<br />

get at the watchers for this ticket. It’s failing because you haven’t defined this association<br />

yet, so let’s go ahead and do that now.<br />

12.1.3 Defining the watchers association<br />

The watchers method should return a collection of users who are watching a ticket,<br />

including (by default) the user who has created the ticket in the first place, so that in<br />

your feature alice@ticketee.com receives the email triggered by bob@ticketee.com’s<br />

comment.

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!