前言
消费者购买商品后,一般我们会发送一封邮件告诉消费者他的购买明细,以方便消费者查看和核实订单
思路
- 创建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文件,会发生报错,如下图: