ruby on rails:发送订单确认通知信

前言

消费者购买商品后,一般我们会发送一封邮件告诉消费者他的购买明细,以方便消费者查看和核实订单

思路

  • 创建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: "[email protected]"
+  default from: "[email protected]"  #这里说明发送人是谁
   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
向其中加入代码,写入详细的购买明细信息

订单明细
<%= link_to("订单连结", order_url(@order.token)) %> #不能用order_path,因为发送邮件要用绝对路径,否则收件人打不开邮件

<% @product_lists.each do |product_list| %> <% end %>
商品明细 单价 数量 小记
<%= product_list.product_name %> <%= product_list.product_price %> <%= product_list.quantity %> <%= product_list.quantity * product_list.product_price %>

总计 <%= @order.total %> CNY


寄送资讯

订购人
<%= @order.billing_name %> - <%= @order.billing_address %>
收件者
<%= @order.shipping_name %> - <%= @order.shipping_address %>

**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!


实际订单通知信的效果:
ruby on rails:发送订单确认通知信_第1张图片

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,否则会报错:

ruby on rails:发送订单确认通知信_第2张图片

这是因为path是相对路径,url是绝对路径。
我们可以看到打开通知信时,地址如下图中的网页地址栏中显示的地址
ruby on rails:发送订单确认通知信_第3张图片

使用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文件,会发生报错,如下图:


ruby on rails:发送订单确认通知信_第4张图片

参考资料:

  1. ruby china Rails path 和 url 有什么区别吗?
  2. Rails中path和url的区别以及用法对待
  3. rails中 url和path的区别

你可能感兴趣的:(ruby on rails:发送订单确认通知信)