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: "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的區別
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容