美文网首页ruby on rails
ruby on rails:发送订单确认通知信

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

作者: 稻草人_b788 | 来源:发表于2017-08-30 18:49 被阅读34次

    前言

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

    思路

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


    参考资料:

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

    相关文章

      网友评论

        本文标题:ruby on rails:发送订单确认通知信

        本文链接:https://www.haomeiwen.com/subject/cmpxjxtx.html