<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                # 5.2 控制器中的方法 ## 概要 本課時講解 Controller 中的回調,權限控制,及如何實現網店的購物車和支付功能,以及使用 datatable 查看訂單數據。 ## 知識點 1. 回調 1. 權限設置 1. 狀態變更 1. 支付 1. 帶分頁的數據列表 1. datatable ## 正文 ### 5.2.1 回調 和 Model 中的回調一樣,Controller 中也有回調。Rails 4 之前,它稱作過濾器,Filter,現在一些文檔也在使用 filter 字樣。 回調它之前的名字是 `xxx_filter`,但是這種稱呼很是歧義,于是在 Rails 4 中改成了 `xxx_action`。 Controller 中的回調有三個,before,after,around。并且可以通過 `:only` 和 `:except` 指定在哪些方法上應用該回調。 在我們的項目里,為了使登錄用戶才能訪問,我們在 `application_controller.rb` 中已經使用了一個前置回調: ~~~ class ApplicationController < ActionController::Base ... before_action :authenticate_user! ... end ~~~ 因為其他的 Controller 都繼承自它,所以這個前置回調會在所有 Controller 中生效。也就是說,訪問所有頁面,都需要登錄狀態。 但是對于首頁,展示頁等,可以公開訪問的頁面,我們需要跳過這個登錄校驗,Controller 中還可以使用 `skip_before_action :xxx` 跳過回調。 ~~~ class ProductsController < ApplicationController skip_before_action :authenticate_user!, only: [:index, :show, :top] end ~~~ 回調也可以使用 block 和單獨的回調類,方法和 Model 中一樣,或者參考[這里](http://guides.rubyonrails.org/action_controller_overview.html#filters)。(注:它還在用 filter 字樣) ### 5.2.2 權限控制 Controller 除了對請求作出相應,另一個重要的事情是做權限控制,只有擁有權限的用戶才可以觸發方法。權限管理有很多 gem 可用,常用的有 [cancan](https://github.com/ryanb/cancan),[pundit](https://github.com/elabs/pundit) 等。 由于 cancan 已經兩年沒有維護了,所以Ruby社區推出cancan 的社區版 [cancancan](https://github.com/CanCanCommunity/cancancan)。 ~~~ % rails g cancan:ability create app/models/ability.rb ~~~ 編輯 ability.rb,我們的權限是:當一個 user(已登錄)字段 role 是 admin 時,可以管理所有資源,否則,只能管理它自己的資源。 ~~~ user ||= User.new # guest user (not logged in) if user.admin? can :manage, :all else can :read, :all [1] can :manage, Address, :user_id => user.id [2] end ~~~ [1] 非管理員可讀所有 [2] 用戶管理自己的收貨地址 我們給 `users` 表添加 role 字段: ~~~ rails g migration addRoleToUsers role:string ~~~ 在視圖中判斷權限: ~~~ <%= link_to "Edit", edit_product_path(product) if can? :update, product %> ~~~ 這里有四個動作可以判斷:`:read`,`:create`,`:update`,`:destroy`。 我們在 Controller 中增加 `load_and_authorize_resource` 回調,這個回調將自動加載一個資源,并且進行權限校驗,這適合資源管理中的方法: ~~~ class ProductsController < ApplicationController load_and_authorize_resource ~~~ 也可以將這個回調分成兩個回調,這樣方便覆寫其中的方法: ~~~ class ProductsController < ApplicationController load_resource authorize_resource ~~~ 更多文檔詳見 [這里](https://github.com/CanCanCommunity/cancancan/wiki/authorizing-controller-actions)。 也可以不實用回調,直接在方法上判斷權限,比如判斷當前用戶是否可以創建商品: ~~~ class ProductsController < ApplicationController ... def create authorize! :create, @product ... ~~~ cancancan 更多用法,詳見 [wiki](https://github.com/CanCanCommunity/cancancan/wiki)。 ### 5.2.3 購物車 購物車有多種設計思路,有的會把信息保存在 cookie 中,有的保存在數據庫中。 我們將它保存到數據庫中,使用 CartItem 這個 Model。當向購物車增加商品時,我們將商品的商品類型(Variant)以及數量保存到購物車中。如果再次購買,會增加該商品類型的數量。 我們將訂單的創建過程分為三步,第一步:確認購物車,第二步:填寫收貨地址,第三部:形成訂單,第四部:支付,第五步:支付成功后通知訂單。 為了方便管理購物和支付流程,我把這個邏輯單獨的放置在 `checkout_controller.rb`。 當我們計算購物車和商品類型價格的時候,經常的出現 `line_item.variant.price`,這種查詢可以通過 Model 中的 `delegate` 進行改進: ~~~ class LineItem < ActiveRecord::Base ... delegate :price, to: :variant, prefix: true ~~~ 這樣,剛才的查詢可以改為 `line_item.variant_price`。`delegate` 方法的 api 在 [這里](http://api.rubyonrails.org/classes/Module.html#method-i-delegate)。 但是,這種方法會造成過多的查詢,所以在確定使用這種方法后,我們可以使用 `has_many` 中的 `includes` 選項: ~~~ class Order < ActiveRecord::Base has_many :line_items, -> { includes :variant } end ~~~ 當我們再次查詢 line_items 時,會自動的檢索關聯的 variant,避免多余的 sql 查詢。 我們編寫代碼的時候,有一些代碼可能需要優化,有一些功能還待完成,這時可以在代碼中增加特殊的注釋: ~~~ def checkout # OPTIMIZE # TODO # FIXME ~~~ 使用 rake 命令可以查看代碼中的注解 ~~~ rake notes:optimize/fixme/todo ~~~ 關注購物車的其他環節,我們可以查看[代碼演示](https://github.com/liwei78/rails-practice-code/tree/master/chapter_5/shop),它所使用的方法,我們之前已經介紹過了。 ### 5.2.4 支付 訂單創建時,它的 `payment_state` 為 `confirm`,當完成支付后,它的狀態改為 `paid`。這里我們使用支付寶來支付訂單。 我們需要安裝支付寶的 [gem](https://github.com/chloerei/alipay)。 并且增加初始配置文件 `config/initializers/alipay.rb`,這里需要填寫從支付寶商家服務 [申請](https://app.alipay.com/market/index.htm) 的 PID 和 KEY。 ~~~ Alipay.pid = '申請的 PID' Alipay.key = '申請的 KEY' ~~~ 支付寶常用實時到賬和擔保交易,如果開通了支付寶快捷登陸,在使用實時到賬時,可以掃描二維碼支付。 支付成功后,通常設定為跳轉回訂單詳細頁面,支付寶會通過接口自動通知 `notify` 方法,我們應該在該方法中更新訂單狀態,并且通知支付寶是否成功,只需 `render text: "success"` 或 `render text: "fail"`。 這里有一份非常詳盡的[支付寶集成](https://ruby-china.org/topics/26354)方案,歡迎參考。 ### 5.2.5 帶分頁的數據列表 進入到“我的訂單”頁面,會有多條訂單記錄,這里需要對訂單進行分頁。常用的分頁 gem 是 [will_paginate](https://github.com/mislav/will_paginate)。因為我們在使用 bootstrap,所以需要安裝 [will_paginate-bootstrap](https://github.com/bootstrap-ruby/will_paginate-bootstrap)。 分頁的代碼非常簡單: ~~~ class OrdersController < ApplicationController ... def index @orders = Order.paginate(:page => params[:page], :per_page => 20) ~~~ 頁面上: ~~~ <div class="well"> <%= page_entries_info @orders %> </div> <%= will_paginate @orders, renderer: BootstrapPagination::Rails %> ~~~ 為了讓 `page_entries_info` 方法和分頁按鈕顯示中文,我們增加一個新的語言包: ~~~ config/locales/will_paginate/zh-CN.yml ~~~ 除了 will_paginate,還有 [kaminari](https://github.com/amatsuda/kaminari),以及 [datatable](https://datatables.net) ### 5.2.6 datatable datatable 是傳統分頁方法的一個極好的替代,當數據量較多,且需要 ajax 加載數據時,可以使用 server 端 datatable 實現,具體請參考 [示例列表](#)。 當我們的訂單數量巨大的時候,我們需要使用 datatable 的 server-side,來減輕分頁加載時的壓力。這里有一個[演示](https://github.com/liwei78/datatable-rails4-bootstrap-on-server-side),供大家參考。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看