<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智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                # 2.3 深入路由(routes) ## 概要: 本課時詳細解讀如何設置復雜情況下的路由(routes),以及路由文件中常用方法。 ## 知識點: 1. routes 定義 1. 嵌套(nested) 1. namespace 1. concern 1. 參數 1. 測試 ## 正文 ### 2.3.1 定義路由(routes) 上一節,我們講了 Rails 通過 routes,來實現 REST 風格的架構。本節我們講詳細介紹下如何使用 routes,定義我們想要的地址(URL)。 我們先為項目,創建一個 controller: ~~~ rails g controller home index welcome about contact ~~~ 在我們專門講解 controller 前,先簡單解釋下: - g 是 generate 的縮寫,我想你已經在 2.1.1 里看到了。 - controller,說明我們創建的是一個 controller,也可以是 model。 - home 是 controller 的名字。 - index... 和其他幾個名字,是 controller 中的方法,并且會自動創建對應的 views 文件。 好了,我們在它上面做一些簡單的例子,打開routes,你可以看到它已經增加了幾個定義: ~~~ get 'home/index' get 'home/welcome' get 'home/about' get 'home/contact' ~~~ 我們訪問 `http://localhost:3000/home/index` 可以看到它。但是,如果我想訪問 `http://localhost:3000/` 就進入到 index 方法呢? ~~~ get '/', to: 'home#index' get '/welcome', to: 'home#welcome' ~~~ 如上,我們自己定義了訪問和方法之間的對應關系。其實我們更經常使用 root 來定義地址: ~~~ root 'home#index' ~~~ 運行 `rake routes`,我們可以看到 | Prefix | Verb | URI Pattern | Controller#Action | |-----|-----|-----|-----| | home_contact | GET | /home/contact(.:format) | home#contact | | | GET | / | home#index | | welcome | GET | /welcome(.:format) | home#welcome | | root | GET | / | home#index | 我們也可以用其他的 Verb 來定義非 GET 請求,比如 ~~~ put '/haha', to: 'home#index' delete '/hehe', to: 'home#index' patch '/wawa', to: 'home#index' ~~~ routes 中我們可以拋開資源的要求(非 REST 風格),直接設定一個訪問地址: ~~~ get '/something/:controller/:name/:action' ~~~ 這時我們訪問 `http://localhost:3000/home/aaa/index` 也會進入到 `'home#index'` 中,因為 Rails 會 這樣解析: - something 是個前綴 - 訪問的 controller 是 home - name 參數是 aaa - 方法是 index 建議你看一下的終端: ~~~ Started GET "/something/home/aaa/index" for ::1 at 2015-02-19 17:10:26 +0800 Processing by HomeController#index as HTML Parameters: {"name"=>"aaa"} ~~~ Rails 已經將你的請求轉移到對應的 controller 中了。 如果一個地址,即可以接收 post 請求,也可以接收 get 等請求,我們可以使用 match 方法: ~~~ match ':controller/:action/:id', via: [:get, :post] ~~~ 提示:在開發(development)環境中,修改 routes 是不需要重啟服務的。 #### 2.3.1.1 擴展 resources 前面我們已經定義了一個 `resource :products`,這在實際開發中還是不夠的,比如,一個 Product 下如果查看評論,比如,顯示賣的最好的十個 Products: ~~~ resources :products do collection do get :top # 排行榜功能 end member do post :buy # 添加到購物車 end end ~~~ 運行 `rake routes` 可以看到: | Prefix | Verb | URI Pattern | Controller#Action | |-----|-----|-----|-----| | top_products | GET | /products/top(.:format) | products#top | | buy_product | POST | /products/:id/buy(.:format) | products#buy | 不同的是,collection 用于 products 中增加方法,member 給具體一個 product 增加方法。 補充一點,我們可以在一行里,定義多個 resources,比如: ~~~ resources :photos, :books, :videos ~~~ 雖然方便,但不夠靈活,實踐中還是要按照需求調整的。 我們在這里提出了兩個功能需求:top 排行榜,和添加到購物車。這里我使用 trello.com 來記錄這兩個需求。 ![](https://box.kancloud.cn/2015-08-18_55d2e47f5a6a6.png) 我在“計劃”里增加了一個 card,在 checklist 中記錄了這兩個需求。當我們開始功能開發的時候,可以將 card 拖動到“進行中”,當我們完成一個功能的時候,可以在 checklist 的項目前打一個√,當我們完成一個 card 的任務后,可以講 card 拖動到“完成”中。 Rails 被很多開發團隊使用,在一些開發團隊中,經常會提到敏捷開發,trello 是一個很好的敏捷開發工具,可以方便的管理我們的日常工作,和記錄項目進展狀態。 #### 2.3.1.2 單個資源 resource ~~~ resource :settings resource :profile ~~~ 這是設定一個單數資源的方法,項目里,哪些是單數呢?比如系統設定,比如當前用戶的個人信息,運行 `rake routes` 可以看到,它是沒有 `:id` 這個參數的。 在這個例子里,我們還未給 settings 和 profile 創建 controller 和 view,不過這不妨礙 routes 產生我們想要的地址。 #### 2.3.1.3 選擇方法 `resources` 給我們創建了七個方法,但是不見得我們都要用到,為了代碼的整潔[1],我們可以做一些排除: ~~~ resources :users, only: [:index, :show] resources :products, except: [:destroy] ~~~ `only` 表示我們需要的方法,`except` 表示我們不需要的方法。通常,我們的確會像上面這么做,比如我們的網站只提供用戶(User)的列表和查看功能,而管理功能(增刪改)要在管理界面進行,而它的地址一般不會是 `/users/1/edit` 這樣,而是 `/admin/users/1/edit`。 [1]這是個人癖好,有的人的確不愿意這么做,不過 Rails 給了我們讓項目變得“整潔”的方法。 #### 2.3.1.5 地址解析的輔助方法 剛才,我們講到了 `_path` 這個后綴,Rails 還有一個 `_url`。 | 地址 | 結果 | |-----|-----| | products_path | '/products' | | products_url | '[http://localhost:3000/products](http://localhost:3000/products)' | `_path` 和 `_url` 是 routes 的輔助方法,我們在下一章將詳細介紹。 ### 2.3.2 嵌套的路由(routes) 在我們定義資源的時候,有時候一個資源會有它的子資源,比如一個商品(product)會有多個商品種類(variants),當我們購買一個商品的時候,也需要選擇哪個種類,比如T恤的種類氛圍尺碼,而每一個尺碼有不同的價格。 這時該如何定義 routes 呢? ~~~ resources :products do resources : variants end ~~~ 運行 `rake routes`,可以看到一個商品(product)下,增加了這些routes: | Prefix | Verb | URI Pattern | Controller#Action | |-----|-----|-----|-----| | product_variants | GET | /products/:product_id/variants(.:format) | variants#index | | | POST | /products/:product_id/variants(.:format) | variants#create | | new_product_variant | GET | /products/:product_id/variants/new(.:format) | variants#new | | edit_product_variant | GET | /products/:product_id/variants/:id/edit(.:format) | variants#edit | | product_variant | GET | /products/:product_id/variants/:id(.:format) | variants#show | | | PATCH | /products/:product_id/variants/:id(.:format) | variants#update | | | PUT | /products/:product_id/variants/:id(.:format) | variants#update | | | DELETE | /products/:product_id/variants/:id(.:format) | variants#destroy | 我們為 variants 也使用一下 `scaffold`: ~~~ rails g scaffold variant product_id:integer price:decimal size ~~~ 在運行 `rails s` 前,記得要更新數據庫: ~~~ rake db:migrate ~~~ 記得,我們應該刪除 routes 中自動添加的 `resources :vriants`,因為我們不需要在 `http://localhost:3000/variants` 下看到它,不是么?我們可以在每一個商品(Product)頁面,比如:`http://localhost:3000/products/1` 中看到它了。 ### 2.3.3 路由中的命名空間(namespace) 接下來我們說兩個項目中經常會見到的情形。 一個項目,肯定要有 admin 的,我們如何把管理地址都放到 [http://localhost:3000/admin/](http://localhost:3000/admin/) 這個目錄下? ~~~ namespace :admin do resources :products end ~~~ 這時,這樣就足夠了,不過,它所使用的 controller 和 view 是在 admin 這個文件夾下面的,多說一點,它的controller 代碼也是在 Admin 這個 module 下的。如果你還對 Ruby 的 module 不熟悉,是時候補充下了。 它的代碼是: ~~~ class Admin::ProductsController < ApplicationController ... end ~~~ 這里,我們反過來想,能否讓 `/admin/articles` 下的代碼去訪問 ArticlesController ?這里不再是 `Admin::` 開頭的。這時我們用到 `scope`: ~~~ scope '/admin' do resources :articles end ~~~ 對于 admin 下的資源管理,可以試試 active admin 這個 Gem。 [https://github.com/activeadmin/activeadmin](https://github.com/activeadmin/activeadmin) ### 2.3.4 concern 方法 再來看一個讓 routes 更簡潔,也很實用的方法。 ~~~ concern :commentable do resources :comments end concern :image_attachable do resources :images, only: :index end resources :messages, concerns: :commentable resources :articles, concerns: [:commentable, :image_attachable] ~~~ `concern` 定義好的資源,可以被其他 resource 里多次引用。 Rails 的原則之一:`不要重復自己(Don't Repeat Yourself)` ### 2.3.5 有用的參數 #### :as 別名 如果再上面地址后面,加上 `as` 參數,會直接創建一個別名的地址,比如 ~~~ get 'home/welcome', as: :welcome ~~~ 之前,我們在 views 或者 controller 中,連接到或跳轉到 `/home/index` 可以這么寫:`home_welcome_path`,增加了 `:as` 后,就變成了 `welcome_path` 了。好處是,如果我們某一天更改了對應的 action 甚至 controller,這個寫法 `welcome_path` 是不會變的,而只需要改動 routes 中的定義。 在定義 routes 時,要注意不要重復定義,因為:寫在上面的會覆蓋下面的。比如: ~~~ get 'home/index', to: 'home#welcome' get 'home/index' ~~~ 訪問 `http://localhost:3000/home/index` 會進入到 `welcome` 方法中。 下面在介紹幾個實用的參數。 #### shallow 這時 Rails 4 中增加的一個很實用的參數。 ~~~ resources :products do resources :comments, shallow: true end ~~~ 它把 index、new 和 create 方法保留在了 `products/:id` 這個資源下,而把其他方法,重新放回到 `/comments` 下。這樣的考慮是避免過多的實用嵌套 routes,并且讓代碼更簡潔。 #### constraints 我們可以給 routes 建立約束(Constraints),比如: ~~~ get 'photos/:id', to: 'photos#show', constraints: { id: /[A-Z]\d{5}/ } ~~~ 這時,id 為 A 到 Z 開頭,且后面為5位數字的 id,才符合路由條件,轉入到 `show` 方法。而 `products/A123456` 將會提示 `No route matches`。 ### 2.3.6 Rspec 測試 通常,我們會在 controller 中寫上測試,不過 Rspec 也為我們提供了測試路由的方法。我們在 spec 下建立一個routing 文件夾,并且添加一個 `products_routing_spec.rb` 的文件: ~~~ RSpec.describe ProductsController, type: :routing do describe "routing" do it "routes to #index" do expect(:get => "/products").to route_to("products#index") end ... ~~~ 我們為它單獨運行測試,因為scaffold 自動為我們添加的測試代碼,我們將在后面的章節完成: ~~~ % rspec spec/routing/products_routing_spec.rb ~~~ routes 測試的參考,可以查看[這里](https://github.com/rspec/rspec-rails#routing-specs)。 好了,本章結束了,本節的內容多來自 Rails 手冊中的 [Rails Routing from the Outside In](http://guides.rubyonrails.org/routing.html),你也可以找到在 [這里](https://github.com/liwei78/rails-practice-code) 找到本章調試的代碼。下一章,我們將開始完成 shop 的頁面(views)代碼,希望它可以讓你更加了解 Rails。
                  <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>

                              哎呀哎呀视频在线观看