Auch wenn wir mit Rails hauptsächlich Webseiten generieren, so ist es
doch hin und wieder ganz praktisch, auch mal eine E-Mail verschicken zu
können.
Bauen wir uns mal ein Beispiel mit einer minimalen Userverwaltung für
einen Webshop, die beim Anlegen eines neuen Users diesem automatisch eine
E-Mail schickt:
MacBook:~ xyz$ rails new webshop
[...]
MacBook:~ xyz$ cd webshop
MacBook:webshop xyz$ rails generate scaffold User name email
[...]
MacBook:webshop xyz$ rake db:migrate
[...]
MacBook:webshop xyz$
Für das User-Model erstellen wir in der
app/models/user.rb
noch eine minimale Validierung,
damit wir sichergehen können, dass jeder User einen Namen und eine
syntaktisch korrekte E-Mail-Adresse hat.
class User < ActiveRecord::Base
attr_accessible :email, :name
validates :name,
:presence => true
validates :email,
:presence => true,
:format => { :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i }
end
Es gibt einen Generator namens
mailer
, der für uns die
fürs Mailen notwendigen Dateien anlegt. Als Erstes schauen wir uns die
Ausgabe des
rails generate mailer an, ohne dass wir
weitere Argumente übergeben:
MacBook:webshop xyz$ rails generate mailer
Usage:
rails generate mailer NAME [method method] [options]
Options:
[--skip-namespace] # Skip namespace (affects only isolated applications)
[--old-style-hash] # Force using old style hash (:foo => 'bar') on Ruby >= 1.9
-e, [--template-engine=NAME] # Template engine to be invoked
# Default: erb
-t, [--test-framework=NAME] # Test framework to be invoked
# Default: test_unit
Runtime options:
-f, [--force] # Overwrite files that already exist
-p, [--pretend] # Run but do not make any changes
-q, [--quiet] # Supress status output
-s, [--skip] # Skip files that already exist
Description:
============
Stubs out a new mailer and its views. Pass the mailer name, either
CamelCased or under_scored, and an optional list of emails as arguments.
This generates a mailer class in app/mailers and invokes your template
engine and test framework generators.
Example:
========
rails generate mailer Notifications signup forgot_password invoice
creates a Notifications mailer class, views, test, and fixtures:
Mailer: app/mailers/notifications.rb
Views: app/views/notifications/signup.erb [...]
Test: test/functional/notifications_test.rb
Fixtures: test/fixtures/notifications/signup [...]
MacBook:webshop xyz$
Das ist alles so, wie wir es erwarten. Legen wir also den Mailer
notification
an:
MacBook:webshop xyz$ rails generate mailer notification
create app/mailers/notification.rb
invoke erb
create app/views/notification
invoke test_unit
create test/functional/notification_test.rb
MacBook:webshop xyz$
In der Datei
app/mailers/notification.rb
finden
Sie den Controller:
class Notification < ActionMailer::Base
default from: "from@example.com"
end
Wir legen darin eine Methode
new_account(user)
an, mit der wir die
Bestätigungs-E-Mail für einen neuen Account verschicken:
class Notification < ActionMailer::Base
default from: "from@example.com"
def new_account(user)
@user = user
mail(:to => user.email,
:subject => "The new account #{user.name} is active.")
end
end
Danach legen wir den View zu dieser Methode an. Der Dateiname
app/views/notification/new_account.text.erb
setzt sich
dabei aus dem Methodennamen und der Endung
text.erb
zusammen.
Hello <%= @user.name %>,
your new account is active.
Have a great day!
A Robot
Da wir diese E-Mail nach dem create eines
Users
verschicken wollen, müssen wir noch die
app/models/user.rb
-Datei anpassen:
class User < ActiveRecord::Base
attr_accessible :email, :name
validates :name,
:presence => true
validates :email,
:presence => true,
:format => { :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i }
after_create :send_welcome_email
private
def send_welcome_email
Notification.new_account(self).deliver
end
end
Nachfolgend legen wir in der Console einen neuen
User
an:
MacBook:webshop xyz$ rails console
Loading development environment (Rails 3.2.3)
1.9.3p194 :001 > User.create(name: 'Wintermeyer', email: 'stefan.wintermeyer@amooma.de')
(0.1ms) begin transaction
SQL (7.7ms) INSERT INTO "users" ("created_at", "email", "name", "updated_at") VALUES (?, ?, ?, ?) [["created_at", Wed, 30 May 2012 15:30:30 UTC +00:00], ["email", "stefan.wintermeyer@amooma.de"], ["name", "Wintermeyer"], ["updated_at", Wed, 30 May 2012 15:30:30 UTC +00:00]]
(1.4ms) commit transaction
=> #<User id: 1, name: "Wintermeyer", email: "stefan.wintermeyer@amooma.de", created_at: "2012-05-30 15:30:30", updated_at: "2012-05-30 15:30:30">
1.9.3p194 :002 > exit
MacBook:webshop xyz$
Das war unspektakulär. Werfen wir nun einen Blick in die Log-Datei
log/development.log
:
Rendered notification/new_account.text.erb (2.5ms)
Sent mail to stefan.wintermeyer@amooma.de (58ms)
Date: Wed, 30 May 2012 17:30:31 +0200
From: from@example.com
To: stefan.wintermeyer@amooma.de
Message-ID: <4fc63d175ea71_a9f03fceda028cd8377c5@MacBook.local.mail>
Subject: The new account Wintermeyer is active.
Mime-Version: 1.0
Content-Type: text/plain;
charset=UTF-8
Content-Transfer-Encoding: 7bit
Hello Wintermeyer,
your new account is active.
Have a great day!
A Robot
Da wir im „development
“-Modus arbeiten, hat Rails
die E-Mail nicht verschickt, sondern nur in die
log/development.log
den Inhalt
hineingeschrieben.