[AWDwR4]13章 Playtime1 的实现
13.PlayTime 1:
向orders表加入ship_date字段,当OrdersController更新这个值后发送一个emial通知。这个官方网站上没有提供参考的答案,论坛里有简单版本我自己实现了一个稍微复杂一点的。
我的思路是在每个order的show模板中加入一个按钮 Ship it now,每个order只有一次ship的机会,这样就避免了重复ship。
step1:
先在 orders_controller 中手动加入ship这个action:
# PUT /orders/1 # PUT /orders/1.json def ship @order = Order.find(params[:id]) respond_to do |format| if @order.ship_date.nil? && @order.update_attributes(:ship_date=>Time.now) Notifier.order_shipped(@order).deliver format.html { redirect_to @order, notice: 'Order was successfully shiped.' } format.json { head :no_content } else format.html { redirect_to order_url(@order), notice: 'Order already shiped.'} format.json { render json: @order.errors, status: :unprocessable_entity } end end end
使用了PUT方法,因为之前看过酷壳上的一篇文章讲到,PUT方法具有幂等性,所以对同一个order进行多次ship操作和一次ship操作的副作用是相同的。
step2 因为ship这个action是手动添加进去的,所以需要手动添加路由,让Rails路由能够识别URL并将请求分发到order控制器的ship中,可参照成员(Member)路由:
修改 config/routes.rb,加入:
resources :orders do put :ship, :on => :member end
step3 在app/views/orders/show.html.erb模板中添加ship按钮
<% if @order.ship_date.nil? %> <%= button_to 'Ship it now!', ship_order_path(@order), :method => :put %> <% end%>
其中使用了 ship_order_path这个helper,我是仿照 <%= link_to 'Edit', edit_order_path(@order) %> 这个来写的,当时没有添加路由,所以报错,找不到这个函数。后来看了rails路由后,才明白 "建立一个 Resourceful 的路由的同时也会为你的应用自动添加一系列的 Helper 方法"这句话的意思。