<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>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                # 11.2 顯示微博 盡管我們還沒實現直接在網頁中發布微博的功能(將在 [11.3.2 節](#creating-microposts)實現),不過還是有辦法顯示微博,并對顯示的內容進行測試。我們將按照 Twitter 的方式,不在微博資源的 `index` 頁面顯示用戶的微博,而在用戶資源的 `show` 頁面顯示,構思圖如[圖 11.4](#fig-user-microposts-mockup) 所示。我們會先使用一些簡單的 ERb 代碼,在用戶的資料頁面顯示微博,然后在 [9.3.2 節](chapter9.html#sample-users)的種子數據中添加一些微博,這樣才有內容可以顯示。 ![user microposts mockup 3rd edition](https://box.kancloud.cn/2016-05-11_5733306f2af9d.png)圖 11.4:顯示有微博的資料頁面構思圖 ## 11.2.1 渲染微博 我們計劃在用戶的資料頁面(`show.html.erb`)顯示用戶的微博,還要顯示用戶發布了多少篇微博。你會發現,很多做法和 [9.3 節](chapter9.html#showing-all-users)列出所有用戶時類似。 雖然 [11.3 節](#manipulating-microposts)才會用到微博控制器,但馬上就需要使用視圖,所以現在就要生成控制器: ``` $ rails generate controller Microposts ``` 這一節的主要目的是渲染用戶發布的所有微博。[9.3.5 節](chapter9.html#partial-refactoring)用過這樣的代碼: ``` <ul class="users"> <%= render @users %> </ul> ``` 這段代碼會自動使用局部視圖 `_user.html.erb` 渲染 `@users` 變量中的每個用戶。同樣地,我們要編寫 `_micropost.html.erb` 局部視圖,使用類似的方式渲染微博集合: ``` <ol class="microposts"> <%= render @microposts %> </ol> ``` 注意,我們使用的是有序列表標簽 `ol`(而不是無需列表 `ul`),因為微博是按照一定順序顯示的(按時間倒序)。相應的局部視圖如[代碼清單 11.21](#listing-micropost-partial) 所示。 ##### 代碼清單 11.21:渲染單篇微博的局部視圖 app/views/microposts/_micropost.html.erb ``` <li id="micropost-<%= micropost.id %>"> <%= link_to gravatar_for(micropost.user, size: 50), micropost.user %> <span class="user"><%= link_to micropost.user.name, micropost.user %></span> <span class="content"><%= micropost.content %></span> <span class="timestamp"> Posted <%= time_ago_in_words(micropost.created_at) %> ago. </span> </li> ``` 這個局部視圖使用了 `time_ago_in_words` 輔助方法,這個方法的作用應該很明顯,效果會在 [11.2.2 節](#sample-microposts)看到。[代碼清單 11.21](#listing-micropost-partial) 還為每篇微博指定了 CSS ID: ``` <li id="micropost-<%= micropost.id %>"> ``` 這是好習慣,說不定以后要處理(例如使用 JavaScript)單篇微博呢。 接下來要解決顯示大量微博的問題。我們可以使用 [9.3.3 節](chapter9.html#pagination)顯示大量用戶的方法來解決這個問題,即使用分頁。和前面一樣,我們要使用 `will_paginate` 方法: ``` <%= will_paginate @microposts %> ``` 如果和用戶列表頁面的代碼([代碼清單 9.41](chapter9.html#listing-will-paginate-index-view))比較的話,會發現之前使用的代碼是: ``` <%= will_paginate %> ``` 前面之所以可以直接調用,是因為在用戶控制器中,`will_paginate` 假定有一個名為 `@users` 的實例變量([9.3.3 節](chapter9.html#pagination)說過,這個變量所屬的類應該是 `AvtiveRecord::Relation`)。現在,因為還在用戶控制器中,但是我們要分頁顯示微博,所以必須明確地把 `@microposts` 變量傳給 `will_paginate` 方法。當然了,我們還要在 `show` 動作中定義 `@microposts` 變量,如[代碼清單 11.22](#listing-user-show-microposts-instance) 所示。 ##### 代碼清單 11.22:在用戶控制器的 `show` 動作中定義 `@microposts` 變量 app/controllers/users_controller.rb ``` class UsersController < ApplicationController . . . def show @user = User.find(params[:id]) @microposts = @user.microposts.paginate(page: params[:page]) end . . . end ``` 注意看 `paginate` 方法是多么智能,甚至可以在關聯上使用,從 `microposts` 表中取出每一頁要顯示的微博。 最后,還要顯示用戶發布的微博數量。我們可以使用 `count` 方法實現: ``` user.microposts.count ``` 和 `paginate` 方法一樣,`count` 方法也可以在關聯上使用。`count` 的計數過程不是把所有微博都從數據庫中讀取出來,然后再在所得的數組上調用 `length` 方法,如果這樣做的話,微博數量一旦很多,效率就會降低。其實,`count` 方法直接在數據庫層計算,讓數據庫統計指定的 `user_id` 擁有多少微博。(所有數據庫都會對這種操作做性能優化。如果統計數量仍然是應用的性能瓶頸,可以使用“[計數緩存](http://railscasts.com/episodes/23-counter-cache-column)”進一步提速。) 綜上所述,現在可以把微博添加到資料頁面了,如[代碼清單 11.23](#listing-user-show-microposts) 所示。注意,`if @user.microposts.any?`(在[代碼清單 7.19](chapter7.html#listing-errors-partial) 中見過類似的用法)的作用是,如果用戶沒有發布微博,不顯示一個空列表。 ##### 代碼清單 11.23:在用戶資料頁面中加入微博 app/views/users/show.html.erb ``` <% provide(:title, @user.name) %> <div class="row"> <aside class="col-md-4"> <section class="user_info"> <h1> <%= gravatar_for @user %> <%= @user.name %> </h1> </section> </aside> <div class="col-md-8"> <% if @user.microposts.any? %> <h3>Microposts (<%= @user.microposts.count %>)</h3> <ol class="microposts"> <%= render @microposts %> </ol> <%= will_paginate @microposts %> <% end %> </div> </div> ``` 現在,我們可以查看一下修改后的用戶資料頁面,如[圖 11.5](#fig-user-profile-no-microposts)。可能會出乎你的意料,不過也是理所當然的,因為現在還沒有微博。下面我們就來改變這種狀況。 ![user profile no microposts 3rd edition](https://box.kancloud.cn/2016-05-11_5733306f440e6.png)圖 11.5:添加顯示微博的代碼后用戶的資料頁面,但沒有微博 ## 11.2.2 示例微博 在 [11.2.1 節](#rendering-microposts),為了顯示用戶的微博,創建或修改了幾個模板,但是結果有點不給力。為了改變這種狀況,我們要在 [9.3.2 節](chapter9.html#sample-users)用到的種子數據中加入一些微博。 為所有用戶添加示例微博要花很長時間,所以我們決定只為前六個用戶添加。為此,要使用 `take` 方法: ``` User.order(:created_at).take(6) ``` 調用 `order` 方法的作用是按照創建用戶的順序查找六個用戶。 我們要分別為這六個用戶創建 50 篇微博(數量要多于 30 個才能分頁)。為了生成微博的內容,我們要使用 Faker 提供的 [`Lorem.sentence`](http://rubydoc.info/gems/faker/1.3.0/Faker/Lorem) 方法。[[2](#fn-2)]添加示例微博后的種子數據如[代碼清單 11.24](#listing-sample-microposts) 所示。 ##### 代碼清單 11.24:添加示例微博 db/seeds.rb ``` . . . users = User.order(:created_at).take(6) 50.times do content = Faker::Lorem.sentence(5) users.each { |user| user.microposts.create!(content: content) } end ``` 然后,像之前一樣重新把種子數據寫入開發數據庫: ``` $ bundle exec rake db:migrate:reset $ bundle exec rake db:seed ``` 完成后還要重啟 Rails 開發服務器。 現在,我們能看到 [11.2.1 節](#rendering-microposts)的勞動成果了——用戶資料頁面顯示了微博。[[3](#fn-3)]初步結果如[圖 11.6](#fig-user-profile-microposts-no-styling) 所示。 ![user profile microposts no styling 3rd edition](https://box.kancloud.cn/2016-05-11_5733306f59e20.png)圖 11.6:用戶資料頁面顯示的微博,還沒添加樣式 [圖 11.6](#fig-user-profile-microposts-no-styling) 中顯示的微博還沒有樣式,那我們就加入一些樣式,如[代碼清單 11.25](#listing-micropost-css) 所示,[[4](#fn-4)]然后再看一下頁面顯示的效果。 ##### 代碼清單 11.25:微博的樣式(包含本章要使用的所有 CSS) app/assets/stylesheets/custom.css.scss ``` . . . /* microposts */ .microposts { list-style: none; padding: 0; li { padding: 10px 0; border-top: 1px solid #e8e8e8; } .user { margin-top: 5em; padding-top: 0; } .content { display: block; margin-left: 60px; img { display: block; padding: 5px 0; } } .timestamp { color: $gray-light; display: block; margin-left: 60px; } .gravatar { float: left; margin-right: 10px; margin-top: 5px; } } aside { textarea { height: 100px; margin-bottom: 5px; } } span.picture { margin-top: 10px; input { border: 0; } } ``` [圖 11.7](#fig-user-profile-with-microposts) 是第一個用戶的資料頁面,[圖 11.8](#fig-other-profile-with-microposts) 是另一個用戶的資料頁面,[圖 11.9](#fig-user-profile-microposts) 是第一個用戶資料頁面的第 2 頁,頁面底部還顯示了分頁鏈接。注意觀察這三幅圖,可以看到,微博后面顯示了距離發布的時間(例如,“Posted 1 minute ago.”),這就是[代碼清單 11.21](#listing-micropost-partial) 中 `time_ago_in_words` 方法實現的效果。過一會再刷新頁面,這些文字會根據當前時間自動更新。 ![user profile with microposts 3rd edition](https://box.kancloud.cn/2016-05-11_5733306f9ac5c.png)圖 11.7:顯示有微博的用戶資料頁面([/users/1](http://localhost:3000/users/1))![other profile with microposts 3rd edition](https://box.kancloud.cn/2016-05-11_5733306fb5879.png)圖 11.8:另一個用戶的資料頁面([/users/5](http://localhost:3000/users/5)),也顯示有微博![user profile microposts page 2 3rd edition](https://box.kancloud.cn/2016-05-11_5733306fd199a.png)圖 11.9:微博分頁鏈接([/users/1?page=2](http://localhost:3000/users/1?page=2)) ## 11.2.3 資料頁面中微博的測試 新激活的用戶會重定向到資料頁面,那時已經測試了資料頁面是否能正確渲染([代碼清單 10.31](chapter10.html#listing-signup-with-account-activation-test))。本節,我們要編寫幾個簡短的集成測試,檢查資料頁面中的其他內容。首先,生成資料頁面的集成測試文件: ``` $ rails generate integration_test users_profile invoke test_unit create test/integration/users_profile_test.rb ``` 為了測試資料頁面中顯示有微博,我們要把微博固件和用戶關聯起來。Rails 提供了一種便利的方法,可以在固件中建立關聯,例如: ``` orange: content: "I just ate an orange!" created_at: <%= 10.minutes.ago %> user: michael ``` 把 `user` 的值設為 `michael` 后,Rails 會把這篇微博和指定的用戶固件關聯起來: ``` michael: name: Michael Example email: michael@example.com . . . ``` 為了測試微博分頁,我們要使用[代碼清單 9.43](chapter9.html#listing-users-fixtures-extra-users) 中用到的方法,通過嵌入式 Ruby 代碼多生成一些微博固件: ``` <% 30.times do |n| %> micropost_<%= n %>: content: <%= Faker::Lorem.sentence(5) %> created_at: <%= 42.days.ago %> user: michael <% end %> ``` 綜上,修改后的微博固件如[代碼清單 11.26](#listing-updated-micropost-fixtures) 所示。 ##### 代碼清單 11.26:添加關聯用戶后的微博固件 test/fixtures/microposts.yml ``` orange: content: "I just ate an orange!" created_at: <%= 10.minutes.ago %> user: michael tau_manifesto: content: "Check out the @tauday site by @mhartl: http://tauday.com" created_at: <%= 3.years.ago %> user: michael cat_video: content: "Sad cats are sad: http://youtu.be/PKffm2uI4dk" created_at: <%= 2.hours.ago %> user: michael most_recent: content: "Writing a short test" created_at: <%= Time.zone.now %> user: michael <% 30.times do |n| %> micropost_<%= n %>: content: <%= Faker::Lorem.sentence(5) %> created_at: <%= 42.days.ago %> user: michael <% end %> ``` 測試數據準備好了,測試本身也很簡單:訪問資料頁面,檢查頁面的標題、用戶的名字、Gravatar 頭像、微博數量和分頁顯示的微博,如[代碼清單 11.27](#listing-user-profile-test) 所示。注意,為了使用[代碼清單 4.2](chapter4.html#listing-title-helper) 中的 `full_title` 輔助方法測試頁面的標題,我們要把 `ApplicationHelper` 模塊引入測試。[[5](#fn-5)] ##### 代碼清單 11.27:用戶資料頁面的測試 GREEN test/integration/users_profile_test.rb ``` require 'test_helper' class UsersProfileTest < ActionDispatch::IntegrationTest include ApplicationHelper def setup @user = users(:michael) end test "profile display" do get user_path(@user) assert_template 'users/show' assert_select 'title', full_title(@user.name) assert_select 'h1', text: @user.name assert_select 'h1>img.gravatar' assert_match @user.microposts.count.to_s, response.body assert_select 'div.pagination' @user.microposts.paginate(page: 1).each do |micropost| assert_match micropost.content, response.body end end end ``` 檢查微博數量時用到了 `response.body`,[第 10 章的練習](chapter10.html#account-activation-and-password-reset-exercises)中見過。別被名字迷惑了,其實 `response.body` 的值是整個頁面的 HTML 源碼(不只是 `body` 元素中的內容)。如果我們只關心頁面中某處顯示的微博數量,使用下面的斷言找到匹配的內容即可: ``` assert_match @user.microposts.count.to_s, response.body ``` `assert_match` 沒有 `assert_select` 的針對性強,無需指定要查找哪個 HTML 標簽。 [代碼清單 11.27](#listing-user-profile-test) 還在 `assert_select` 中使用了嵌套式句法: ``` assert_select 'h1>img.gravatar' ``` 這行代碼的意思是,在 `h1` 標簽中查找類為 `gravatar` 的 `img` 標簽。 因為應用能正常運行,所以測試組件應該也能通過: ##### 代碼清單 11.28:**GREEN** ``` $ bundle exec rake test ```
                  <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>

                              哎呀哎呀视频在线观看