静的なページ、コントローラ、モデルと来て、ここからはいよいよ真に動的なページの作成に取り掛かっていきます。その記念すべき第一弾となるのが、今回実装するプロフィールページです。
今節においては、以下の要素が表示できるプロフィールページを作成していきます。
- ユーザーの名前
- プロフィール写真
プロフィールページの最終的な完成像としては、以下の要素が表示できることを目指します。
- プロフィール写真
- 基本ユーザーデータ
- マイクロポストの一覧
デバッグとRails環境
Webサイトのレイアウトにデバッグ情報を追加する
デバッグ情報の追加は、サンプルアプリケーションに動的なページを追加する前段階となります。使用するのは以下のリソースです。
-
debug
メソッド -
params
変数
<!DOCTYPE html>
<html>
...略
<body>
<%= render 'layouts/header' %>
<div class="container">
<%= yield %>
<%= render 'layouts/footer' %>
+ <%= debug(params) if Rails.env.development? %>
</div>
</body>
</html>
以上のコードを追加することにより、開発環境(development)において、各プロフィールページにデバッグ用の情報が表示されるようになります。
特筆すべきは以下のRubyコードです。
if Rails.env.development?
これは、開発環境(development)でのみtrue
になる条件式です。
<%= debug(params) if Rails.env.development? %>
ゆえに、上記の埋め込みRubyは以下の動作をすることになります。
- 本番環境やテストには挿入されない
- 開発環境1でのみ、各プロフィールページにデバッグ用の情報を表示する
デバッグ出力の表示を整形するために、カスタムスタイルシートに追加の記述を行う
@import "bootstrap-sprockets";
@import "bootstrap";
/* mixins, variables, etc. */
$gray-medium-light: #eaeaea;
+ @mixin box_sizing {
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+ }
..略
+
+ /* miscellaneous */
+ .debug_dump {
+ clear: both;
+ float: left;
+ width: 100%;
+ margin-top: 45px;
+ @include box_sizing;
+ }
上記は、デバッグ出力をきれいに整形するためにapp/assets/stylesheets/custom.scss
に追加で記述するコードです。「Sassのミックスイン機能を使用している(@mixin box_sizing
以下の記述)」というのがポイントです。
結果として、デバッグ環境のHomeページをWebブラウザでレンダリングした結果は、現在のところは以下のスクリーンショットのような出力となります。
Sassのミックスイン機能
Sassのミックスイン機能を使うことにより、CSSルールのグループをパッケージ化して複数の要素に適用することができます。
例えば、例1のコードは例2のように展開されます。
@mixin box_sizing {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
.debug_dump {
/* ...略 */
@include box_sizing;
}
.debug_dump {
/* ...略 */
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
デバッグ出力の内容
演習 - デバッグとRails環境
1. ブラウザから/aboutにアクセスし、デバッグ情報が表示されていることを確認してください。このページを表示するとき、どのコントローラとアクションが使われていたでしょうか?params
の内容から確認してみましょう。
params
の内容は以下のとおりです。
--- !ruby/object:ActionController::Parameters
parameters: !ruby/hash:ActiveSupport::HashWithIndifferentAccess
controller: static_pages
action: about
permitted: false
- コントローラは
static_pages
- アクションは
about
以上であることがわかります。
2. Railsコンソールを開き、データベースから最初のユーザー情報を取得し、変数user
に格納してください。その後puts user.attributes.to_yaml
を実行すると何が表示されますか?
>> user = User.find(1)
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
=> #<User id: 1, name: "Michael Hartl", email: "mhartl@example.com", created_at: "2019-10-13 06:43:53", updated_at: "2019-10-13 06:43:53", password_digest: "$2a$10$rb26ZPyWkUh8T/cWML/OM.VhDiuJaii877zf3SvsfN5...">
>> puts user.attributes.to_yaml
---
id: 1
name: Michael Hartl
email: mhartl@example.com
created_at: !ruby/object:ActiveSupport::TimeWithZone
utc: &1 2019-10-13 06:43:53.935111000 Z
zone: &2 !ruby/object:ActiveSupport::TimeZone
name: Etc/UTC
time: *1
updated_at: !ruby/object:ActiveSupport::TimeWithZone
utc: &3 2019-10-13 06:43:53.935111000 Z
zone: *2
time: *3
password_digest: "$2a$10$rb26ZPyWkUh8T/cWML/OM.VhDiuJaii877zf3SvsfN56IOU/ibHei"
=> nil
2.2. 2.1.で表示された結果と、y
メソッドを使ったy user.attributes
の実行結果を比較してみましょう。
>> y user.attributes
---
id: 1
name: Michael Hartl
email: mhartl@example.com
created_at: !ruby/object:ActiveSupport::TimeWithZone
utc: &1 2019-10-13 06:43:53.935111000 Z
zone: &2 !ruby/object:ActiveSupport::TimeZone
name: Etc/UTC
time: *1
updated_at: !ruby/object:ActiveSupport::TimeWithZone
utc: &3 2019-10-13 06:43:53.935111000 Z
zone: *2
time: *3
password_digest: "$2a$10$rb26ZPyWkUh8T/cWML/OM.VhDiuJaii877zf3SvsfN56IOU/ibHei"
=> nil
puts user.attributes.to_yaml
の結果とy user.attributes
の結果は、特に変わりないように見えます。いずれも戻り値はnil
であり、副作用として、ユーザーオブジェクトの内容をyamlとしてパースしたものが標準出力に出力されています。
Usersリソース
RDB上に一人分のユーザー情報が登録されていることを確認する
ユーザープロフィールページを作成するには、RDB上にユーザーが登録されている必要があります。第6章の時点で「Railsコンソールを使ってRDB上にユーザーを登録する」という操作を行ったのは、実はそのためだったのです。
# rails console
>> User.count
(2.1ms) SELECT COUNT(*) FROM "users"
=> 1
>> User.first
User Load (0.4ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ? [["LIMIT", 1]]
=> #<User id: 1, name: "Michael Hartl", email: "mhartl@example.com", created_at: "2019-10-13 06:43:53", updated_at: "2019-10-13 06:43:53", password_digest: "$2a$10$rb26ZPyWkUh8T/cWML/OM.VhDiuJaii877zf3SvsfN5...">
ここでは、「RDB上に既に1個のユーザー情報が存在しており、そのユーザーのIDは1である」というのがポイントです。
RESTアーキテクチャと、ユーザー情報の表示の実装計画
Railsアプリケーションにおいては、RESTアーキテクチャの習慣に従い、「データの作成・表示・更新・削除2をリソースに割り付ける」という手法を取ることが好まれます。HTTP標準のリクエストとCRUDの各操作は、以下のように対応付けられるのが一般的です。
HTTP標準のリクエスト | CRUDの各操作 |
---|---|
POST | Create |
GET | Read |
PATCH | Update |
DELETE | Delete |
RESTの原則に従う場合、リソースへの参照は、リソース名とユニークなIDを使うのが一般的です。例えば、id=1のユーザーの情報を表示する場合、対応する操作は、「/users/1というURLに対してGETリクエストを発行する」という操作になります。
というわけで、RESTの原則に従うならば、ユーザー情報に対するCRUD機能のコントローラを実装するためには、POST・GET・PATCH・DELETEの各リクエストをコントローラのアクションに割り付けていくというのが基本方針となります。
show
アクション、その他RESTfulなUsersリソースに対するルーティングが利用できるようにする
Railsのコントローラで定義されたアクションは7つあり、そのうちのshow
アクションは、暗黙的にGETリクエストと対応付けられています。RailsのREST機能が有効になっていれば、GETリクエストは自動的にshow
アクションとして扱われるのです。
ただ、現時点で/users/1にアクセスするとエラーになります。/users/1へのGETリクエストに対するルーティングが定義されていないためです。
Started GET "/users/1" for 172.17.0.1 at 2019-10-13 15:37:30 +0000
Cannot render console from 172.17.0.1! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
ActionController::RoutingError (No route matches [GET] "/users/1"):
...略
というわけで、/users/1へのGETリクエストに対するルーティングを定義しましょう。修正するファイルは、/config/routes.rb
です。
Rails.application.routes.draw do
get 'users/new'
root 'static_pages#home'
get '/help', to: 'static_pages#help'
get '/about', to: 'static_pages#about'
get '/contact', to: 'static_pages#contact'
get '/signup', to: 'users#new'
+ resources :users
end
/config/routes.rb
にresources :users
という記述を加えると、/users/1に限らず、RESTfulなUsersリソースで必要となるHTTPリクエスト(POST・GET・PATCH・DELETE)と対応するURLの組すべてに対するルーティングが定義されます。実際に定義されるルーティングの一覧表は、Railsチュートリアルの表 7.1の通りになります。
次になすべきことは
ただ、ルーティングが定義されたとしても、まだルーティング先のアクションがコントローラで定義されていないですし、ルーティング先のページが存在するわけでもありません。/users/1にアクセスすると、やはりエラーになります。
Started GET "/users/1" for 172.17.0.1 at 2019-10-13 15:50:14 +0000
Cannot render console from 172.17.0.1! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
AbstractController::ActionNotFound (The action 'show' could not be found for UsersController):
...略
エラーにはなりますが、その内容が変化していますね。「ルーティングが見つからない」というのではなく、「コントローラでshow
アクションが定義されていない」という内容になりました。
この状態からshow
アクションが正しく動作するようにするためには、以下の2つの実装が必要になります。
- Usersリソースに対するshowビューの実装
- Usersコントローラに対する
show
アクションの実装
Usersリソースに対するshowビューの実装
Railsにおいて、「Usersリソースに対するshowビュー」を指すファイルは、app/views/users/show.html.erb
となります。しかしながら、現時点で当該ファイルは存在しません。まずはapp/views/users/show.html.erb
を新規作成するのが最初のプロセスとなります。
app/views/users/show.html.erb
の最初の内容は、以下の通りです。「埋め込みRubyにより、ユーザー名とメールアドレスを表示する」という内容になります。
<%= @user.name %>, <%= @user.email %>
Usersコントローラに対するshow
アクションの実装
Usersリソースに対するshowビューが正常に動作するためには、Usersコントローラにshow
アクションに、対応する@user
変数が実装されている必要があります。編集するファイルはapp/controllers/users_controller.rb
です。以下の内容を追加します。
class UsersController < ApplicationController
+
+ def show
+ @user = User.find(params[:id])
+ end
+
def new
end
end
ポイントは以下です。
- ユーザーのid読み出しには、
params
メソッドを用いている- Usersコントローラが正常なリクエストを受け取ると、例えばid=1の場合、
@user = User.find(1)
という処理を実行することに成る
- Usersコントローラが正常なリクエストを受け取ると、例えばid=1の場合、
-
param[:id]
の戻り値は文字列型の"1"
だが、find
メソッドでは自動的に整数型に変換される
ここまでの変更を反映した時点で、/users/1が完全に動作するようになります。以下にスクリーンショットを掲載します。
--- !ruby/object:ActionController::Parameters
parameters: !ruby/hash:ActiveSupport::HashWithIndifferentAccess
controller: users
action: show
id: '1'
上記のとおり、デバッグ情報からparam[:id]
の値を確認できるようになりました。id: '1'
というのは、/users/:id
というURLから取得された値です。これにより、User.find(params[:id])
がUser.find(1)
と解釈される一連の仕組みが確立されました。
演習 - Usersリソース
1. 埋め込みRubyを使って、マジックカラム (created_atとupdated_at) の値をshowページに表示してみましょう (リスト 7.4)。
変更対象のファイルはapp/views/users/show.html.erb
です。以下のように変更してみます。
<%= @user.name %>, <%= @user.email %>
+ Created: <%= @user.created_at %>, Updated: <%= @user.updated_at %>
結果は以下のようになりました。
2. 埋め込みRubyを使って、Time.now
の結果をshowページに表示してみましょう。ページを更新すると、その結果はどう変わっていますか? 確認してみてください。
<%= @user.name %>, <%= @user.email %>
Created: <%= @user.created_at %>, Updated: <%= @user.updated_at %>
+ 現在の時刻: <%= Time.now %>
「現在の時刻:」以降の表示内容が、Webページを更新するたびに変わっていきます。
debuggerメソッド
byebug gemは既にインストールされている
最初の環境構築の段階で、開発環境(Development)向けにbyebug
というGemをセットアップしました。
source 'https://rubygems.org'
...略
group :development, :test do
gem 'sqlite3', '1.3.13'
gem 'byebug', '9.0.6', platform: :mri
end
...略
このbyebug
gemが提供するdebugger
メソッドにより、今まで用いてきたdebug
メソッドよりさらに直接的にデバッグを行うことが可能です。
実際にdebuggerメソッドを使ってみる
まずは、実際にdebugger
メソッドをRailsアプリケーションに差し込んでみましょう。
class UsersController < ApplicationController
def show
@user = User.find(params[:id])
+ debugger
end
def new
end
end
この状態で/users/1というページを表示すると、rails server
を立ち上げたシェルに、以下のようなプロンプトが出てきます。
(byebug)
このプロンプトでは、Railsコンソールのようにコマンドを実行することができ、アプリケーションのdebugger
が呼び出された瞬間の状態を確認することが可能です。
(byebug) @user.name
"Michael Hartl"
(byebug) @user.email
"mhartl@example.com"
(byebug) params[:id]
"1"
プロンプトを抜けるには、Ctrl-Dを押します。また、デバッグが終わったらdebugger
行は削除する必要があります。プロンプトが出ている状態だと、アプリケーションの実行が中断されるからです。
class UsersController < ApplicationController
def show
@user = User.find(params[:id])
- debugger
end
def new
end
end
debuggerメソッドを使う際のポイント
- Railsアプリケーション内でよくわからない挙動があったら、躊躇なく
debugger
コードを挿し込んで調べてみる -
debugger
コードは、トラブルが起こっていそうなコードのできるだけ近くに差し込む
byebug gemによるシステム状態の調査は、アプリケーションの動作の追跡・デバッグに際して非常に強力なツールとなります。
演習 - debuggerメソッド
1. showアクションの中にdebuggerを差し込み (リスト 7.6)、ブラウザから /users/1 にアクセスしてみましょう。その後コンソールに移り、putsメソッドを使ってparamsハッシュの中身をYAML形式で表示してみましょう。
class UsersController < ApplicationController
def show
@user = User.find(params[:id])
+ debugger
end
def new
end
end
(byebug) puts params.to_yaml
--- !ruby/object:ActionController::Parameters
parameters: !ruby/hash:ActiveSupport::HashWithIndifferentAccess
controller: users
action: show
id: '1'
permitted: false
nil
2. new
アクションの中にdebugger
を差し込み、/users/new にアクセスしてみましょう。@user
の内容はどのようになっているでしょうか? 確認してみてください。
class UsersController < ApplicationController
def show
@user = User.find(params[:id])
end
def new
+ debugger
end
end
以下の通り、@user
をputs
しても、型もアドレスも表示されません。
(byebug) puts @user
nil
一方で、show
アクションにdebugger
メソッドを挿入した状態で@user
をputs
した結果は以下のようになります。型とアドレスが表示されていますね。
(byebug) puts @user
#<User:0x00007f34780e2de8>
nil
Gravater画像とサイドバー
Gravatarとは
Globally Recognized AVATARの略です。プロフィール写真をアップロードして、指定のメールアドレスと紐付ける事ができるサービスです。Gravatarを利用することにより、プロフィール写真の運用について、以下の利便を実現することができます。
- プロフィール写真をアップロードする面倒な作業から解放される
- 写真が欠けるトラブルから解放される
- 画像の置き場所の悩みが解決される
Gravatar画像を利用できるサービスとしては、例えば以下のものが挙げられます。
- Github
- Slack
- Qiita
RailsアプリケーションでもGravatarのプロフィール画像を利用することができます。
gravatar_for
ヘルパーメソッドを呼び出すようにする
現在作成中のアプリケーションでは、「gravatar_for
というヘルパーメソッドを使ってGravatarの画像を利用できるようにする」とう方針を取ることとします。
まず、ユーザー表示ビューでgravatar_for
ヘルパーメソッドを使用するようにコードを書き換えていきましょう。
- <%= @user.name %>, <%= @user.email %>
+ <% provide(:title, @user.name) %>
+ <h1>
+ <%= gravatar_for @user %>
+ <%= @user.name %>
+ </h1>
「デフォルトでは、ヘルパーファイルで定義されているメソッドは、自動的にすべてのビューで利用できる」という言及は注目に値します。
なお、今回は、利便性を考え「gravatar_for
をUsersコントローラに関連付けられているヘルパーファイルに置く」という方針を取ります。
文字列に対するMD5ハッシュを得る
GravatarのURLは、ユーザーのメールアドレスをMD5というハッシュ関数でハッシュ化したものを用いています。そのため、Gravatarを利用するシステムの側でもMD5ハッシュを得る処理を実装する必要があります。
Rubyでは、Digest
ライブラリのhexdigest
メソッドを用いることにより、文字列に対するMD5ハッシュを得ることができます。以下のRailsコンソールの処理結果がその例です。
>> email = "MHARTL@example.COM"
=> "MHARTL@example.COM"
>> Digest::MD5::hexdigest(email.downcase)
=> "1fda4469bcbec3badf5418269ffc5968"
以下の事柄は重要です。
- RubyのStringクラスの
downcase
メソッドを用いて、hexdigest
の引数を小文字に変換している- 現在作成中のアプリケーションではメールアドレスの大文字小文字を区別しない一方、MD5ハッシュを生成するための入力では大文字小文字を区別するため
- 現在作成中のアプリケーションを前提とした場合、実際のところ、MD5ハッシュを生成する時点でメールアドレスを小文字に変換する処理を入れるのは冗長である
- 現在作成中のアプリケーションでは、ユーザー情報を新規に作成してRDBMSに保存する時点でメールアドレスを小文字に変換する処理を行っているため
-
gravatar_for
メソッドが単独で呼び出される可能性を考え、MD5ハッシュを生成する時点で小文字に変換する処理を入れている
gravatar_for
ヘルパーメソッドを定義する
MD5ハッシュを得る処理の内容がわかったので、実際に「Railsアプリケーションの登録メールアドレスを元に、Gravatarからプロフィール画像を得る」という処理を実装していきましょう。
module UsersHelper
+ 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
メソッドのオプションハッシュには、alt
属性とclass
属性を与えています。それぞれ以下の意味になります。
-
alt
属性の内容は、画像が表示できない場合の代替テキストを意味する -
class
属性の内容により、HTMLの各要素をグループ化し、主にCSSで使うことができる
上記のコードを追加しても、プロフィール画像が表示されない場合
ここまでのコードを追加して、改めて/users/1をブラウザで表示した結果です。…プロフィール画像が表示されていません。なぜでしょうか。
teratailに答えがありました。当方の環境でも、確かにimg
要素に対してdisplay: none
という内容のCSSコードが存在します(下掲スクリーンショット)。
原因は何かというと、第5章の演習で追加したコード(リスト 5.11)のようです。app/assets/stylesheets/custom.scss
の対応する部分のコードを削除します。
@import "bootstrap-sprockets";
@import "bootstrap";
...略
-
- img {
- display: none;
- }
...略
今度こそプロフィール画像が表示されるようになりました。
実際にGravatarに登録されている情報を使ってみる
example@railstutorial.orgというメールアドレスに対しては、実際にGravatarにプロフィール画像が登録されています。当該メールアドレスを使って、実際にGravatarに登録されている情報を参照してみましょう。
現時点でユーザーの登録情報を変更するフォームは実装していないので、ユーザーの登録情報の変更はrails console
から行っていきます。
# rails console
>> user = User.first
...略
>> user.update_attributes(name: "Example User",
?> email: "example@railstutorial.org",
?> password: "foobar",
?> password_confirmation: "foobar")
...略
=> true
>> exit
Gravatarに登録されているプロフィール画像が表示されています。
サイドバーの最初のバージョン
ユーザーのshow
ビューにサイドバーを追加する
ユーザーのshow
ビューにサイドバーを追加していきましょう。まずは以下のように、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>
ポイントは以下です。
- サイドバーは、HTML5の
aside
要素を使って実装している - HTML全体として、以下のクラスを使っている
row
col-md-4
row
クラスとcol-md-4
クラスは、いずれもBootstrapフレームワークで使われているクラスの名前です。
SCSSを使ってサイドバーなどのユーザー表示ページにスタイルを与える
サイドバーの構成・クラス名が決まると、SCSSでスタイルを与えることができるようになります。今回は、以下のようなスタイルを与えていきます。
...略
+
+ /* 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: 0px;
+ }
+ }
+ }
+
+ .gravatar {
+ float: left;
+ margin-right: 10px;
+ }
+
+ .gravatar_edit {
+ margin-top: 15px;
+ }
...略
ここまでコードを追加した時点において、/users/1をブラウザで表示した結果です。
演習 - Gravater画像とサイドバー
1. (任意) Gravatar上にアカウントを作成し、あなたのメールアドレスと適当な画像を紐付けてみてください。メールアドレスをMD5ハッシュ化して、紐付けた画像がちゃんと表示されるかどうか試してみましょう。
メールアドレスをMD5ハッシュ化する手順は、Railsコンソールで試してみます。「文字列を引数として与えてMD5ハッシュを生成する」というメソッドは、RubyのDigest::MD5::hexdigest
でしたね。
# rails console --sandbox
>> Digest::MD5::hexdigest([Qiitaの登録メールアドレス])
=> "0aad88c4503ba3e1308c13025b89d4e5"
Qiitaの登録メールアドレスのMD5ハッシュが得られました。というわけで、Webブラウザで https://secure.gravatar.com/avatar/0aad88c4503ba3e1308c13025b89d4e5 にアクセスしてみます。きちんとQiitaのプロフィール画像が表示されています。
2. 7.1.4で定義したgravatar_for
ヘルパーをリスト 7.12のように変更して、size
をオプション引数として受け取れるようにしてみましょう。
うまく変更できると、
gravatar_for user, size: 50
といった呼び出し方ができるようになります。
module UsersHelper
- def gravatar_for(user)
+ def gravatar_for(user, options = { size:80 })
gravatar_id = Digest::MD5::hexdigest(user.email.downcase)
+ size = options[:size]
- gravatar_url = "https://secure.gravatar.com/avatar/#{gravatar_id}"
+ gravatar_url = "https://secure.gravatar.com/avatar/#{gravatar_id}?s=#{size}"
image_tag(gravatar_url, alt: user.name, class: "gravatar")
end
end
app/views/users/show.html.erb
において、gravatar_for
メソッドにsize
属性を与えず、メールアドレスがexample@railstutorial.orgである場合、Gravatarのプロフィール画像のURLがhttps://secure.gravatar.com/avatar/bebfcf57d6d8277d806a9ef3385c078d?s=80
となります。
app/views/users/show.html.erb
の内容に以下の変更を加えたらどうなるでしょう。gravatar_for
メソッドのsize
属性に50
という値を与えたものです。
<% provide(:title, @user.name) %>
<div class="row">
<aside class="col-md-4">
<section class="user_info">
<h1>
- <%= gravatar_for @user %>
+ <%= gravatar_for @user, size: 50 %>
<%= @user.name %>
</h1>
</section>
</aside>
</div>
スクリーンショットは以下のようになりました。Gravatarのプロフィール画像のURLはhttps://secure.gravatar.com/avatar/bebfcf57d6d8277d806a9ef3385c078d?s=50
となっています。
3. 先ほど変更したリスト 7.12を、リスト 7.13のように置き換えてもうまく動くことを確認してみましょう。この2つの実装方法はどういった違いがあるのでしょうか? 考えてみてください。
以下はオプションハッシュを使ったコードに対するキーワード引数を使ったコードの差分です。
module UsersHelper
- def gravatar_for(user, options = { size:80 })
+ def gravatar_for(user, size: 80)
gravatar_id = Digest::MD5::hexdigest(user.email.downcase)
- size = options[:size]
gravatar_url = "https://secure.gravatar.com/avatar/#{gravatar_id}?s=#{size}"
image_tag(gravatar_url, alt: user.name, class: "gravatar")
end
end
app/views/users/show.html.erb
において、gravatar_for
メソッドにsize
属性を与えず、メールアドレスがexample@railstutorial.orgである場合、Gravatarのプロフィール画像のURLがhttps://secure.gravatar.com/avatar/bebfcf57d6d8277d806a9ef3385c078d?s=80
となります。
gravatar_for
メソッドのsize
属性に値50
を与えた場合、Gravatarのプロフィール画像のURLはhttps://secure.gravatar.com/avatar/bebfcf57d6d8277d806a9ef3385c078d?s=50
とります。
オプションハッシュとキーワード引数の違い
「オプションハッシュの場合、引数の組がハッシュとしてひとかたまりにされており、ハッシュそのものを別のメソッドに渡すこともできる。一方のキーワード引数は、引数そのものはひとまとまりのオブジェクトにされていない。」というのが大きな違いかと思います。「別メソッドにオプションハッシュそのものを渡すことにより、呼び出し側のメソッドの内部構造を知らなければならなくなる。これはメソッド同士の結合度が高くなってよろしくない」という問題は考えられます。