iT邦幫忙

2017 iT 邦幫忙鐵人賽
DAY 20
2

本系列文章內容同步發佈於這裡,若有任何問題或錯誤,都歡迎直接到 GitHub 上發 PR 修正,或是在這裡留言討論。


寄發信件

寄發信件

在 Rails 要寄發信件其實滿容易的,可以使用內建的 ActionMailer 來做這件事。首先,讓我們先用 mailer 產生器來產生需要的檔案:

$ rails g mailer Contact
    create  app/mailers/contact_mailer.rb
    invoke  erb
    create    app/views/contact_mailer
 identical    app/views/layouts/mailer.text.erb
 identical    app/views/layouts/mailer.html.erb
    invoke  test_unit
    create    test/mailers/contact_mailer_test.rb
    create    test/mailers/previews/contact_mailer_preview.rb

這裡透過產生器,產生了一個 ContactMailer 類別。先讓我們看一下 app/mailers 目錄,現在裡面應該有 2 個檔案,分別是 application_mailer.rbcontact_mailer.rb。先看一下 application_mail.erb

class ApplicationMailer < ActionMailer::Base
  default from: 'from@example.com'
  layout 'mailer'
end

這裡的 default 方法後面接著 from: 'from@example.com',意思就是如果沒有特別指定的話,預設信件的寄件者就是 from@example.com,所以這裡可以改成我們自己的信箱。下一行的 layout 是指會去找 app/views/layouts/mailer 這個樣版。

再讓我們看一下 contact_mailer.rb

class ContactMailer < ApplicationMailer
end

有沒發現這好像有點熟悉? 其實 Mailer 的檔案結構,跟 Controller 有點像:

Controller Mailer
類別 UsersController ContactMailer
繼承類別 ApplicationController ApplicationMailer
Layout app/views/application.rb /app/views/mailer
View app/views/users/*.erb /app/views/contact_mailer/*.erb

mailer 上的 action?

即然說 Mailer 跟 Controller 有點像,在 Mailer 也有類似像 action 之類的角色,寫起來大概像這樣:

class ContactMailer < ApplicationMailer
  def say_hello_to(user)
    @user = user
    mail to:@user.email, subject:"你好!!"
  end
end

在這邊我定義了一個叫做 say_hello_to 的方法,並期待會接一個 user 物件做為參數。其中真正進行寄信的是 mail 那行。

咦? 等等,那信件內容呢? 其實跟 Controller 相比較起來,信件內容大概就是跟 View 差不多的角色。讓我們在 app/views/contact_mailer 目錄裡新增一個跟剛剛這個方法「同名」的檔案(檔案名稱:say_hello_to.html.erb),並且加上以下內容:

<%= @user.name %>,你好:

今天你也有過得開心嗎!

謝謝你的來信,再見!

寫起來的手感是不是真的跟一般的 View 很像呢? 它一樣也可以從 Mailer 取得實體變數,並輸出在這個檔案裡。

準備寄發!

準備來寄信吧! 我希望在新增 User 的時候,如果新增成功,就寄一封通知信給這位使用者:

class UsersController < ApplicationController
  # ...[略]
  def create
    @user = User.new(user_params)
    if @user.save
      ContactMailer.say_hello_to(@user).deliver
      redirect_to @user, notice: 'User was successfully created.'
    else
      render :new
    end
  end
  # ...[略]
end

其中這行:

ContactMailer.say_hello_to(@user).deliver

就是寄信的地方了。

有發現不對勁的地方嗎? 我們在 ContactMailer 裡定義 say_hello_to 方法的時候,明明是實體方法,為什麼這邊用起來像類別方法? 其實這算是 Mailer 幫你做的魔術,定義在 Mailer 裡的方法,都會被轉換成類別方法,使用起來更方便。

試一下:

http://ithelp.ithome.com.tw/upload/images/20170104/20065770mWbkt4tqpi.png

按下送出之後,過沒多久就能收到信了:

http://ithelp.ithome.com.tw/upload/images/20170104/20065770WV1ovHHoVS.png


本系列文章內容同步發佈於這裡,若有任何問題或錯誤,都歡迎直接到 GitHub 上發 PR 修正,或是在這裡留言討論。


上一篇
第 18 章 - Model 驗證及回呼
下一篇
第 20 章 - 背景工作及工作排程
系列文
為你自己學 Ruby on Rails30

1 則留言

0
gn1692401
iT邦新手 5 級 ‧ 2017-03-20 14:11:44

我按照本文章內容操作但卻收不到發出的email,請問可能是什麼原因呢?

因為其實這篇文章省略了使用外部的 SMTP 寄信的設定,預設會使用本機寄發,而這通常會寄不出去。

之後把內容補完後會更新在這裡 http://railsbook.tw/

感謝您!謝謝

我要留言

立即登入留言