In common Ruby on Rails 3/4 apps, there are two options to deliver mail after the creation of a model:
1) Send the mail directly from the controller's create action
#listings_controller.rb
def create
@listing.create(params[:listing])
if @listing.save
ListingMailer.new_listing_notice(@listing).deliver
format.html {redirect_to @listing}
...
end
end
or 2) Send the mail from a Model Callback
#listing.rb
class Listing
after_create :notify
...
def notify
ListingMailer.new_listing_notice(self).deliver
end
end
Is there a current consensus about which way is better? Sending from the controller gives more control, but if a mail will always be sent is there any reason not to use the callback? Is this mostly a question of style, or are there other important concerns?
Generally, it's much more difficult to maintain code that has after_*
hooks in models. There are, of course some cases, when using a callback is very reasonable (computing a checksum, for instance, should be done all the time in some applications), but those cases are exceptions to the rule.
In your example with the email, here's some drawbacks of the callback approach:
For instance, you would like your emails to be sent using a special queue. The interface of communicating with the queue should not, in any way, affect the way the Listing model is built.
Emailing is just one of the means of interacting with the outside world. Not all of the business logic will always require to be tied to the outside world. One of the examples, as apneadiving mentioned is import. Another example is the console interface (would you like to be sent an email when you're playing with the rails console?)
This is more of a result of 1 and 2, but testing after
hooks is increasingly difficult as time passes. The need of mocking the mailer while testing the Listing model makes the test unclear and more difficult to maintain whenever something changes.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With