前言
消費者購買商品后,一般我們會發送一封郵件告訴消費者他的購買明細,以方便消費者查看和核實訂單
思路
- 創建mailer,記錄訂單詳情
- 安裝gem letter_opener 來預覽郵件
實作步驟:
step1. 創建訂單Order的Mailer
終端執行:
rails g mailer OrderMailer
此時,在app/views下會自動新建一個order_mailer的目錄
**step2. **設定訂單通知的寄信功能
(1)修改application_mailer.rb,加入下列代碼:
class ApplicationMailer < ActionMailer::Base
- default from: "from@example.com"
+ default from: "service@jdstore.com" #這里說明發送人是誰
layout 'mailer'
end
(2)修改order_mailer.rb
class OrderMailer < ApplicationMailer
def notify_order_placed(order) #建立通知信
@order = order #記錄訂單(為下面步驟3的order_url參數傳入做準備)
@user = order.user #記錄訂單的所有者
@product_lists = @order.product_lists #記錄訂單的商品明細
mail(to: @user.email, subject: "[JDstore]感謝您完成本次下單,以下是您的本次購物明細#{order.token}")
# 發送到收件人的email,提示信息為"購物商城]感謝您完成本次下單,以下是您的本次購物明細"和訂單的亂碼序號
end
end
**step3. **建立訂單通知詳情頁面
touch app/views/order_mailer/notify_order_placed.html.erb
向其中加入代碼,寫入詳細的購買明細信息
<div class="row">
<div class="col-md-12">
<h2>
訂單明細 <br>
<small>
<%= link_to("訂單連結", order_url(@order.token)) %> #不能用order_path,因為發送郵件要用絕對路徑,否則收件人打不開郵件
</small>
</h2>
<table class="table table-bordered">
<thead>
<tr>
<th width="70%">商品明細</th>
<th>單價</th>
<th>數量</th>
<th>小記</th>
</tr>
</thead>
<tbody>
<% @product_lists.each do |product_list| %>
<tr>
<td>
<%= product_list.product_name %>
</td>
<td>
<%= product_list.product_price %>
</td>
<td>
<%= product_list.quantity %>
</td>
<td>
<%= product_list.quantity * product_list.product_price %>
</td>
</tr>
<% end %>
</tbody>
</table>
<div class="total group clearfix">
<h4 class="pull-right">
總計 <%= @order.total %> CNY
</h4>
</div>
<hr>
<h2> 寄送資訊 </h2>
<table class="table table-striped table-bordered">
<tbody>
<tr>
<td> 訂購人 </td>
</tr>
<tr>
<td>
<%= @order.billing_name %> - <%= @order.billing_address %>
</td>
</tr>
<tr>
<td> 收件者 </td>
</tr>
<tr>
<td>
<%= @order.shipping_name %> - <%= @order.shipping_address %>
</td>
</tr>
</tbody>
</table>
</div>
</div>
**step4. **安裝gem letter_open來預覽郵件
(1)修改Gemfile,加入下列代碼:
+ gem 'letter_open', group: :development
(2)修改development.rb的設定
#設定默認的路徑為localhost: 3000
+ config.action_mailer.default_url_options = {host: 'localhost: 3000'}
# 設定發送并打開郵件的方法來自于letter_opener
+ config.action_mailer.delivery_method = :letter_opener
(3)執行
bundel install
重開rails s
**step5. **此時可以在console模式下測試信件預覽
終端執行:
rails c
查看第一筆order訂單的通知信內容:
終端執行:
OrderMailer.notify_order_placed(Order.first).deliver!
實際訂單通知信的效果:
step6. 在訂單建立時寄送通知信,并清空購物車
修改orders_controller,加入下列代碼:
before_action :authenticate_user!
def create
@order = Order.new(order_params)
@order.user = current_user
@order.total = current_cart.total_price
if @order.save
current_cart.cart_items.each do |cart_item|
product_list = ProductList.new
product_list.order = @order
product_list.product_name = cart_item.product.title
product_list.product_price = cart_item.product.price
product_list.quantity = cart_item.quantity
product_list.save
end
+ current_cart.clean! #清空購物車
+ OrderMailer.notify_order_placed(@order).deliver! #發送訂單通知信
redirect_to order_path(@order.token)
else
render 'carts/checkout'
end
end
補充:
(1) 為什么這里用ulr,而不用path?
發送郵件的時候必須使用url,不能使用path,否則會報錯:
這是因為path是相對路徑,url是絕對路徑。
我們可以看到打開通知信時,地址如下圖中的網頁地址欄中顯示的地址
使用url,則點擊"訂單連結"會尋找在development中設定'localhost: 3000'和orders形成的絕對路徑,即
http://localhost:3000/orders/6afef09a-5664-4745-9bcd-580c1855e53d
如果用path,則點擊"訂單連結"會在地址欄后面添加orders/token亂碼序號,來尋找訂單,這樣是找不到的,因此會報錯.
進一步舉例子說明path和url的區別:
users_url => http://localhost:3000/users
users_path => /users
user_path(1) => /users/1
user_url(1) => http://localhost:3000/users/1
如果網站不需要跳轉到外部地址,那么用path或者url,rails都能正確找到路徑。
一些重要的場景,如發送郵件要用到絕對路徑,如果使用相對路徑,別人收到郵件會打不開。
對于大部分郵件客戶端加個 base 設置也能繼續用 path
根據規范,301/302 redirect 響應需要指定完整的地址(雖然瀏覽器都支持path) 所以 redirect_to 一般都用 url
(2)保證OrderMailer中建立通知信的方法notify_order_placed要和訂單通知信頁面notify_order_placed.html.erb文件的命名一致 ,并且保證該html文件的路徑是放在order_mailer下的,否則rails找不到訂單通知信的html文件,會發生報錯,如下圖: