A Gravatar image and a sidebar

這節要進一步地把個人資訊頁面養胖一點。

使用 Gravatar,這個是免費的服務,可以讓使用者上傳個人圖片(avatar),並透過 email 綁定。透過這個第三方服務,你就不必還要自己處理有關使用者的圖片上傳、圖片裁切以及儲存的問題了。你只要透過設定 Gravatar 的圖片 URL 與使用者的 email 綁定,Gravatar 的圖片就會自動產生了。(之後會再講要怎麼自己處理圖片上傳的問題)

現在我們需要建立一個 gravatar_for 輔助方法來回傳使用者的 Gravatar 圖片:

app/views/users/show.html.erb

<% provide(:title, @user.name) %>
<h1>
  <%= gravatar_for @user %>
  <%= @user.name %>
</h1>

Rails 預設中,任何在輔助方法檔案(helper file)建立的方法(methods)都可以在 view 中使用,但為了管理方便,會把 gravatar_for 方法放在 Users controller 對應的輔助方法中。

Gravatar documentation 裡面提到,Gravatar URLs 要使用使用者 email 的 MD5 hash。在 Ruby 中計算 MD5 hash 的方式是使用 Digest library 的 hexdigest 方法:

> email = "[email protected]"
> Digest::MD5::hexdigest(email.downcase)
=> "9098336a950c11635ca809af628ac1a4"

因為 email 沒有區分大小寫,但 MD5 hash 有分大小寫,所以使用 downcase 方法確保傳進 hexdigest 的參數都是小寫。(之前已經在 callback 中把 email 轉成小寫形式了,但這裡最好也轉換,以防止 email 來自其他地方)。

gravatar_for 方法如下:

app/helpers/users_helper.rb

module UsersHelper

  # Returns the Gravatar for the given user.
  def gravatar_for(user)
    gravatar_id = Digest::MD5::hexdigest(user.email.downcase)
    gravatar_url = "https://secure.gravatar.com/avatar/#{gravatar_id}"
    image_tag(gravatar_url, alt: user.name, class: "gravatar")
  end
end

這個方法最後會回傳 image tag,包含了 class gravatar 和屬性 alt 的值。

產生的畫面如下:

因為我們使用的 email [email protected] 不是真的 email,所以 Gravatar 會產生預設的圖片。

為了看到自訂的效果,可以使用 update_attributes 更新資料到資料庫:

$ rails console
> user = User.first
> user.update_attributes(name: "Example User",
                         email: "[email protected]",
                         password: "foobar",
                         password_confirmation: "foobar")
=> true

現在畫面有了真正的圖像了:

最後,我們要設定側邊欄:

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>

然後新增樣式:

app/assets/stylesheets/custom.css.sass

.
.
.
/* sidebar */

aside
  section.user_info
    margin-top: 20px

  section
    padding: 10px 0
    margin-top: 20px
    &:first-child
      border: 0
      padding-top: 0

    span
      display: block
      margin-bottom: 3px
      line-height: 1

    h1
      font-size: 1.4em
      text-align: left
      letter-spacing: -1px
      margin-bottom: 3px
      margin-top: 0

.gravatar
  float: left
  margin-right: 10px

.gravatar_edit
  margin-top: 15px

最後的畫面長這樣: