エンタープライズ領域での採用も増えてきたRuby on Railsを使ってWebアプリケーションを作るための入門連載。最新版の4に対応しています。今回は、SMTPにGmailも使えるActionMailerの設定、ERB記法で埋め込むメールのテンプレート、永続化しないデータをActiveModelで扱う方法などを解説。
今回はRailsのMVCアーキテクチャとは別のコンポーネントについて紹介します。一つはWebアプリケーションからメールを送信する機能を作るためのActionMailer、もう一つはDBに保存しない・永続化しないデータをActiveRecordのデータと同じように取り扱えるようにするActiveModelの紹介です。
いずれも必ず使用するコンポーネントというわけではありませんが、「Webアプリケーションでメールを送りたい」という要求は多くあり、永続化しないデータを扱う機会も少なくありません。前回の「RailsテストフレームワークRSpecのインストールと基本的な使い方、基礎文法」までと同様に、GitHubにあるサンプルプログラムの「book_library」を使って、メールの送信機能と複数のパラメーターを取る検索機能を作り、それらの使い方を学んでみましょう。
ActionMailerはメールの送受信を行うためのライブラリです。今回はメールの送信にのみ着目しますが、受信機能を作ることもできます。また、独立したライブラリなのでRails以外のアプリケーションでも使えます。
メールの送信機能を作っていく前にActionMailerの設定を行いましょう。ここでは「development」環境の設定を行うので「config/environments/development.rb」を編集します。
まず、「development」環境のデフォルトではActionMailerのエラーを無視するようになっているので、エラーを無視しないように変更します。こうしておかないとメールの送信に失敗してもエラーが起きず、原因が分かりません。次に示す「config.action_mailer.raise_delivery_errors」の設定をコメントアウトしてください。
# Don't care if the mailer can't send. # config.action_mailer.raise_delivery_errors = false
これにより、送信に失敗するとエラーが出力されるようになります。アプリケーションのサーバーが起動している場合は、設定を反映するために再起動しましょう。
次に「config/environments/development.rb」にSMTPの設定を次のように追加します。
config.action_mailer.delivery_method = :smtp config.action_mailer.smtp_settings = { address: 'smtp.address', port: 25, domain: 'book.library.domain', user_name: 'your.email@example.com', password: '<password>', authentication: 'plain', enable_starttls_auto: true }
このSMTPにはGmailのものを使うこともできます。これで、ひとまず開発環境におけるActionMailerの設定が完了しました。それではメール送信機能を実装してみましょう。
RailsではActionMailerのファイルを生成するためのコマンドが用意されています。次のコマンドでActionMailerにおけるメーラーとメール本文を定義するテンプレートを配置するディレクトリ、そしてテストコードを生成できます。
$ rails g mailer authentication_mailer create app/mailers/authentication_mailer.rb invoke slim create app/views/authentication_mailer invoke rspec create spec/mailers/authentication_mailer_spec.rb
メーラーは「app/mailers」に作られ、「アクション」と呼ばれるメソッドでメールを定義するなどコントローラーによく似ています。またメール本文のテンプレートは「app/views」に作られたメーラーの名前のディレクトリ(ここでは「app/views/authentication_mailer」)に、アクションに対応するビューとして追加していきます。
メーラーではメールの種類ごとにアクションを定義します。例えば、ユーザー登録が完了したことを通知するメールやパスワードのリセットURLを通知するメールごとにメールタイトルや本文の内容が異なるため、アクションによりそれらを分けて定義します。また認証に関するメールとは異なる場合、新たに別のメーラーを作るといいでしょう。以下にメールを定義するアクションの例を示します。
class AuthenticationMailer < ActionMailer::Base default from: "system@xxxxxxx.xxxxxxx" def complete_registration(user) @user = user mail { to: user.email, subject: 'ユーザー登録が完了しました。' } end end
この例ではメーラー「AuthenticationMailer」において、「complete_registration」アクションが定義されています。アクションは最後に「mail」メソッドを呼び出してメールオブジェクトを返します。「mail」メソッドに渡すハッシュでメールの宛先や送信元、タイトルを設定します。これらのパラメーターのデフォルト値をメーラー全体で設定する「default」メソッドも用意されており、上のコードの2行目のようにして設定します。
「mail」メソッドが呼ばれると、そのアクションのテンプレートがレンダリングされます。「complete_registration」アクションであれば「complete_registration.text.erb」がレンダリングされます。これは次のようにテキストにRuby式をERB記法で埋め込んだERBテンプレートです。
<%= @user.name %>様 ユーザー登録が完了しました。 身に覚えがない場合は inquiry@xxxxxxx.xxxxxxx までお問い合わせください。
アクションを実行しただけではメールは送信されません。メールを送信するにはメールオブジェクトの「deliver」メソッドを呼び出す必要があります。実際にはコントローラー中などで次のコードのように呼び出します。
def create @user = User.create(user_params) if @user.save @mail = AuthenticationMailer.complete_registration(@user) @mail.deliver # if Rails.env.production? redirect_to root_path else render 'new' end end
メールの送信機能を開発している間は実際にメールが届くか調べるため「deliver」メソッドを実行できるようにしておきます。しかし、完成した後も回帰テストが行われるたびにメールが送信されるとうっとうしいので、メールが届くことを確認できたら「deliver」メソッドの後ろのコメントアウトを外して「production」環境でのみ送信されるようにしておくといいでしょう。
コントローラーのアクション(ここでは「create」)のサンプルではインスタンス変数「@mail」が存在していることを確認できれば十分です。
Copyright © ITmedia, Inc. All Rights Reserved.