はじめに
Ruby on Rails チュートリアル実例を使ってRailsを学ぼう 第4版の 10章 10.3 すべてのユーザーを表示するの演習まとめ&解答例です。
個人の解答例なので、誤りがあればご指摘ください。
動作環境
- cloud9
- ruby 2.3.0p0 (2015-12-25 revision 53290) [x86_64-linux]
- Rails 5.0.0.1
10.3.1 ユーザーの一覧ページ
本章での学び
テストコードの作成
indexアクションに対するテストコードを作成する。
yokoyan:~/workspace/sample_app (updating-users) $ rails routes Prefix Verb URI Pattern Controller#Action login GET /login(.:format) sessions#new POST /login(.:format) sessions#create users GET /users(.:format) users#index POST /users(.:format) users#create
- usert_pathにGETリクエストでアクセスする
- login_urlにリダイレクトされること
test "should redirect index when not logged in" do get users_path assert_redirected_to login_url end
【filter】beforeフィルターの修正
beforeフィルターに、indexアクションを追加する。
class UsersController < ApplicationController before_action :logged_in_user, only: [:index, :edit, :update]
【controller】indexアクションの作成
すべてのユーザー情報を表示するために、indexアクション内でUser.all
メソッドを呼び出す。
データベースから取得したすべてのユーザー情報を、インスタンス変数@users
に格納する。
def index @users = User.all end
【View】indexビューの作成
indexアクションで取得した@users
の中身を、@users.each do |user|
で1件ずつ取り出す。
<% provide(:title, 'All users')%> <h1>All users</h1> <ur class="users"> <% @users.each do |user| %> <li> <% gravatar_for_user, size:50 %> <% link_to user.name, user %> </li> <% end %> </ur>
【css】indexページ用のscssの作成
カスタムscssに、indexビューで使用するusersクラスを定義する。
.users { list-style: none; margin: 0; li { overflow: auto; padding: 10px 0; border-bottom: 1px solid $gray-lighter; } }
【view】ヘッダーにindexページヘのリンクを追加する
これまで、#
となっていた箇所を実装する。
<li><%= link_to "Users", users_path %></li>
動作確認
ブラウザで確認。
テストコードがgreenになることを確認。
yokoyan:~/workspace/sample_app (updating-users) $ rails test Running via Spring preloader in process 2279 Started with run options --seed 60667 36/36: [===============================================================================================================================================================================================] 100% Time: 00:00:06, Time: 00:00:06 Finished in 6.97019s 36 tests, 101 assertions, 0 failures, 0 errors, 0 skips
演習1
レイアウトにあるすべてのリンクに対して統合テストを書いてみましょう。ログイン済みユーザーとそうでないユーザーのそれぞれに対して、正しい振る舞いを考えてください。ヒント: log_in_asヘルパーを使ってリスト 5.32にテストを追加してみましょう。
site_layout_test.rb
にテストを追加する。
- 未ログインユーザーの場合
- home
- help
- about
- contact
- News(静的URLのため対象外とする)
- ログイン済みユーザーの場合
- home
- help
- Users
- Account
- Profile
- Settings
- Log out
- about
- contact
- News(静的URLのため対象外とする)
test "layout links" do get root_path assert_template 'static_pages/home' assert_select "a[href=?]", root_path, count: 2 assert_select "a[href=?]", help_path assert_select "a[href=?]", about_path assert_select "a[href=?]", contact_path assert_select "a[href=?]", login_path get contact_path assert_select "title", full_title("Contact") get signup_path assert_select "title", full_title("Sign up") end test "layout links when logged in user" do log_in_as(@user) get root_path assert_select "a[href=?]", root_path, count:2 assert_select "a[href=?]", help_path assert_select "a[href=?]", about_path assert_select "a[href=?]", contact_path assert_select "a[href=?]", users_path assert_select "a[href=?]", user_path(@user) assert_select "a[href=?]", edit_user_path(@user) assert_select "a[href=?]", logout_path end
10.3.2 サンプルのユーザー
本章での学び
Rubyを使って、一気にユーザーを作成する。
faker gemのインストール
事前準備として、fakerをインストールする。
gem 'faker', '1.6.6'
bundle install
Railsタスク(Rubyスクリプト)の生成
db/seeds.rb
にRubyスクリプトを生成する- Example Userを1人作成する
- fakerで、それらしい名前を持つユーザを99人生成する
User.create!( name: "Example User", email: "example@railstutorial.org", password: "foobar", password_confirmation: "foobar" ) 99.times do |n| name = Faker::Name.name email = "example-#{n+1}@railstutorial.org" password = "password" User.create!( name: name, email: email, password: password, password_confirmation: password ) end
Railsタスクの実行
以下を実行する。
rails db:migrate:reset rails db:seed
ブラウザからUsersメニューを選択すると、ユーザが100人に増えている!すごい!!
演習1
試しに他人の編集ページにアクセスしてみて、10.2.2で実装したようにリダイレクトされるかどうかを確かめてみましょう。
Example Userでログインしている状態で、猫アイコンのユーザ(id=5)にアクセス。
URLに「https://xxxxx/users/5/edit」でアクセスすると、TOPページにリダイレクトされることを確認。
10.3.3 ページネーション
本章での学び
100人のユーザに対して、1ぺージ30人ずつ表示するページネーションを追加する。
ページネーションメソッド(will paginate)のインストール
gemでwill_paginate
と、bootstrap-will_paginate
をインストールする。
gem 'will_paginate', '3.1.0' gem 'bootstrap-will_paginate', '0.0.10'
bundle install
インストールしたら、WEBサーバを再起動する。
【view】indexページでpaginateを使う
リストの上下に、<%= will_paginate %>
を追加する。
理由は、ページの上下にページネーションを表示するため。
<%= will_paginate %> <ul class="users"> <% @users.each do |user| %> <li> <%= gravatar_for user, size: 50 %> <%= link_to user.name, user %> </li> <% end %> </ul> <%= will_paginate %>
ページ上部のページネーション。
ページ下部のページネーション。
【controller】ユーザー情報をpaginateに格納する
User.all
を、User.paginate
に置き換える。
paginateメソッドは、Usersテーブルから30件取得した結果を格納している。
yokoyan:~/workspace/sample_app (updating-users) $ rails console Running via Spring preloader in process 2489 Loading development environment (Rails 5.0.0.1) >> User.paginate(page:1 ) User Load (2.2ms) SELECT "users".* FROM "users" LIMIT ? OFFSET ? [["LIMIT", 30], ["OFFSET", 0]] => #<ActiveRecord::Relation [#<User id: 1, name: "Example User", email: "example@railstutorial.org", created_at: "2017-06-13 03:57:28", updated_at: "2017-06-13 03:57:28", password_digest: "$2a$10$zGDH/dBloZT0Txbp62FHdO13Mt16cBWhQehUmwKcY4l...", remember_digest: nil>, #<User id: 2, name: "Myrl West", email: "example-1@railstutorial.org", created_at: "2017-06-13 03:57:29", updated_at: "2017-06-13 03:57:29", password_digest: "$2a$10$.1qwJtz9AnqDvkRfV9MYAetPEQP1dvl1EkVDGZ.HzTP...", remember_digest: nil>, #<User id: 3, name: "Rodger Simonis", email: "example-2@railstutorial.org", created_at: "2017-06-13 03:57:29", updated_at: "2017-06-13 03:57:29", password_digest: "$2a$10$BNzrCTPh.vPCbCo5L.JZ6eiaUxTQgvRT5y40sHjgYSF...", remember_digest: nil>, #<User id: 4, name: "Cecelia Adams", email: "example-3@railstutorial.org", created_at: "2017-06-13 03:57:29", updated_at: "2017-06-13 03:57:29", password_digest: "$2a$10$j9SIW6g6ASDW8j38XqNYtu/zsx2Y6Q43Smup7.uwSGW...", remember_digest: nil>, #<User id: 5, name: "Torey Schmitt", email: "example-4@railstutorial.org", created_at: "2017-06-13 03:57:29", updated_at: "2017-06-13 03:57:29", password_digest: "$2a$10$Lp8fRB0eUc0IFvBg6/xF6uMQg5eW2SXH7hP2Zggk6LM...", remember_digest: nil>, #<User id: 6, name: "Jorge Luettgen PhD", email: "example-5@railstutorial.org", created_at: "2017-06-13 03:57:29", updated_at: "2017-06-13 03:57:29", password_digest: "$2a$10$KPIuq2hPkHBsjeS7uG5X.u3LFz1j5PV.mjrAc4ht9w6...", remember_digest: nil>, #<User id: 7, name: "Eriberto Littel DVM", email: "example-6@railstutorial.org", created_at: "2017-06-13 03:57:29", updated_at: "2017-06-13 03:57:29", password_digest: "$2a$10$f8n9xlsWJXEdUUaWrNi6zeu4MwXSASplByQazMGj6Q4...", remember_digest: nil>, #<User id: 8, name: "Kelley Bode", email: "example-7@railstutorial.org", created_at: "2017-06-13 03:57:29", updated_at: "2017-06-13 03:57:29", password_digest: "$2a$10$SNwYoPOY5xtpmA6PkJ5wM.k7NycvFUrnUKZz2nDQedW...", remember_digest: nil>, #<User id: 9, name: "Jakob Muller", email: "example-8@railstutorial.org", created_at: "2017-06-13 03:57:29", updated_at: "2017-06-13 03:57:29", password_digest: "$2a$10$y6UTasDZYRzfoet.TG9wbO9dyQkiq1bkoleLhxMK6aE...", remember_digest: nil>, #<User id: 10, name: "Jean Franecki", email: "example-9@railstutorial.org", created_at: "2017-06-13 03:57:29", updated_at: "2017-06-13 03:57:29", password_digest: "$2a$10$A43xSShhuOePJ39KKQ3VWuzuq1oTkL25K2RG1t4.R8Q...", remember_digest: nil>, ...]>
実装する。
page:
パラメータのparams[:page]
は、will_paginateによって自動的に生成して代入される。
def index # @users = User.all @users = User.paginate(page: params[:page]) end
演習1
Railsコンソールを開き、pageオプションにnilをセットして実行すると、1ページ目のユーザーが取得できることを確認してみましょう。
nilの場合、1ページ目のユーザーが取得できることを確認。
yokoyan:~/workspace/sample_app (updating-users) $ rails console Running via Spring preloader in process 2221 Loading development environment (Rails 5.0.0.1) >> User.paginate(page: nil) User Load (10.0ms) SELECT "users".* FROM "users" LIMIT ? OFFSET ? [["LIMIT", 30], ["OFFSET", 0]] => #<ActiveRecord::Relation [#<User id: 1, name: "Example User", email: "example@railstutorial.org", created_at: "2017-06-13 03:57:28", updated_at: "2017-06-13 03:57:28", password_digest: "$2a$10$zGDH/dBloZT0Txbp62FHdO13Mt16cBWhQehUmwKcY4l...", remember_digest: nil>, #<User id: 2, name: "Myrl West", email: "example-1@railstutorial.org", created_at: "2017-06-13 03:57:29", updated_at: "2017-06-13 03:57:29", password_digest: "$2a$10$.1qwJtz9AnqDvkRfV9MYAetPEQP1dvl1EkVDGZ.HzTP...", remember_digest: nil>, #<User id: 3, name: "Rodger Simonis", email: "example-2@railstutorial.org", created_at: "2017-06-13 03:57:29", updated_at: "2017-06-13 03:57:29", password_digest: "$2a$10$BNzrCTPh.vPCbCo5L.JZ6eiaUxTQgvRT5y40sHjgYSF...", remember_digest: nil>, #<User id: 4, name: "Cecelia Adams", email: "example-3@railstutorial.org", created_at: "2017-06-13 03:57:29", updated_at: "2017-06-13 03:57:29", password_digest: "$2a$10$j9SIW6g6ASDW8j38XqNYtu/zsx2Y6Q43Smup7.uwSGW...", remember_digest: nil>, #<User id: 5, name: "Torey Schmitt", email: "example-4@railstutorial.org", created_at: "2017-06-13 03:57:29", updated_at: "2017-06-13 03:57:29", password_digest: "$2a$10$Lp8fRB0eUc0IFvBg6/xF6uMQg5eW2SXH7hP2Zggk6LM...", remember_digest: nil>, #<User id: 6, name: "Jorge Luettgen PhD", email: "example-5@railstutorial.org", created_at: "2017-06-13 03:57:29", updated_at: "2017-06-13 03:57:29", password_digest: "$2a$10$KPIuq2hPkHBsjeS7uG5X.u3LFz1j5PV.mjrAc4ht9w6...", remember_digest: nil>, #<User id: 7, name: "Eriberto Littel DVM", email: "example-6@railstutorial.org", created_at: "2017-06-13 03:57:29", updated_at: "2017-06-13 03:57:29", password_digest: "$2a$10$f8n9xlsWJXEdUUaWrNi6zeu4MwXSASplByQazMGj6Q4...", remember_digest: nil>, #<User id: 8, name: "Kelley Bode", email: "example-7@railstutorial.org", created_at: "2017-06-13 03:57:29", updated_at: "2017-06-13 03:57:29", password_digest: "$2a$10$SNwYoPOY5xtpmA6PkJ5wM.k7NycvFUrnUKZz2nDQedW...", remember_digest: nil>, #<User id: 9, name: "Jakob Muller", email: "example-8@railstutorial.org", created_at: "2017-06-13 03:57:29", updated_at: "2017-06-13 03:57:29", password_digest: "$2a$10$y6UTasDZYRzfoet.TG9wbO9dyQkiq1bkoleLhxMK6aE...", remember_digest: nil>, #<User id: 10, name: "Jean Franecki", email: "example-9@railstutorial.org", created_at: "2017-06-13 03:57:29", updated_at: "2017-06-13 03:57:29", password_digest: "$2a$10$A43xSShhuOePJ39KKQ3VWuzuq1oTkL25K2RG1t4.R8Q...", remember_digest: nil>, ...]> >>
演習2
先ほどの演習課題で取得したpaginationオブジェクトは、何クラスでしょうか? また、User.allのクラスとどこが違うでしょうか? 比較してみてください。
どちらのクラスも、User::ActiveRecord_Relation
であるため同じクラス。
User.paginate
で取得した結果を変数pageに格納する。
User.paginate
のクラスは、User::ActiveRecord_Relation
?> page = User.paginate(page: nil) User Load (0.4ms) SELECT "users".* FROM "users" LIMIT ? OFFSET ? [["LIMIT", 30], ["OFFSET", 0]] => #<ActiveRecord::Relation [#<User id: 1, name: "Example User", email: "example@railstutorial.org", created_at: "2017-06-13 03:57:28", updated_at: "2017-06-13 03:57:28", password_digest: "$2a$10$zGDH/dBloZT0Txbp62FHdO13Mt16cBWhQehUmwKcY4l...", remember_digest: nil>, #<User id: 2, name: "Myrl West", email: "example-1@railstutorial.org", created_at: "2017-06-13 03:57:29", updated_at: "2017-06-13 03:57:29", password_digest: "$2a$10$.1qwJtz9AnqDvkRfV9MYAetPEQP1dvl1EkVDGZ.HzTP...", remember_digest: nil>, #<User id: 3, name: "Rodger Simonis", email: "example-2@railstutorial.org", created_at: "2017-06-13 03:57:29", updated_at: "2017-06-13 03:57:29", password_digest: "$2a$10$BNzrCTPh.vPCbCo5L.JZ6eiaUxTQgvRT5y40sHjgYSF...", remember_digest: nil>, #<User id: 4, name: "Cecelia Adams", email: "example-3@railstutorial.org", created_at: "2017-06-13 03:57:29", updated_at: "2017-06-13 03:57:29", password_digest: "$2a$10$j9SIW6g6ASDW8j38XqNYtu/zsx2Y6Q43Smup7.uwSGW...", remember_digest: nil>, #<User id: 5, name: "Torey Schmitt", email: "example-4@railstutorial.org", created_at: "2017-06-13 03:57:29", updated_at: "2017-06-13 03:57:29", password_digest: "$2a$10$Lp8fRB0eUc0IFvBg6/xF6uMQg5eW2SXH7hP2Zggk6LM...", remember_digest: nil>, #<User id: 6, name: "Jorge Luettgen PhD", email: "example-5@railstutorial.org", created_at: "2017-06-13 03:57:29", updated_at: "2017-06-13 03:57:29", password_digest: "$2a$10$KPIuq2hPkHBsjeS7uG5X.u3LFz1j5PV.mjrAc4ht9w6...", remember_digest: nil>, #<User id: 7, name: "Eriberto Littel DVM", email: "example-6@railstutorial.org", created_at: "2017-06-13 03:57:29", updated_at: "2017-06-13 03:57:29", password_digest: "$2a$10$f8n9xlsWJXEdUUaWrNi6zeu4MwXSASplByQazMGj6Q4...", remember_digest: nil>, #<User id: 8, name: "Kelley Bode", email: "example-7@railstutorial.org", created_at: "2017-06-13 03:57:29", updated_at: "2017-06-13 03:57:29", password_digest: "$2a$10$SNwYoPOY5xtpmA6PkJ5wM.k7NycvFUrnUKZz2nDQedW...", remember_digest: nil>, #<User id: 9, name: "Jakob Muller", email: "example-8@railstutorial.org", created_at: "2017-06-13 03:57:29", updated_at: "2017-06-13 03:57:29", password_digest: "$2a$10$y6UTasDZYRzfoet.TG9wbO9dyQkiq1bkoleLhxMK6aE...", remember_digest: nil>, #<User id: 10, name: "Jean Franecki", email: "example-9@railstutorial.org", created_at: "2017-06-13 03:57:29", updated_at: "2017-06-13 03:57:29", password_digest: "$2a$10$A43xSShhuOePJ39KKQ3VWuzuq1oTkL25K2RG1t4.R8Q...", remember_digest: nil>, ...]> >> ?> page.class => User::ActiveRecord_Relation
User.all
で取得した結果を変数page_allに格納する。
User.all
のクラスは、User::ActiveRecord_Relation
?> page_all = User.all User Load (0.7ms) SELECT "users".* FROM "users" => #<ActiveRecord::Relation [#<User id: 1, name: "Example User", email: "example@railstutorial.org", created_at: "2017-06-13 03:57:28", updated_at: "2017-06-13 03:57:28", password_digest: "$2a$10$zGDH/dBloZT0Txbp62FHdO13Mt16cBWhQehUmwKcY4l...", remember_digest: nil>, #<User id: 2, name: "Myrl West", email: "example-1@railstutorial.org", created_at: "2017-06-13 03:57:29", updated_at: "2017-06-13 03:57:29", password_digest: "$2a$10$.1qwJtz9AnqDvkRfV9MYAetPEQP1dvl1EkVDGZ.HzTP...", remember_digest: nil>, #<User id: 3, name: "Rodger Simonis", email: "example-2@railstutorial.org", created_at: "2017-06-13 03:57:29", updated_at: "2017-06-13 03:57:29", password_digest: "$2a$10$BNzrCTPh.vPCbCo5L.JZ6eiaUxTQgvRT5y40sHjgYSF...", remember_digest: nil>, #<User id: 4, name: "Cecelia Adams", email: "example-3@railstutorial.org", created_at: "2017-06-13 03:57:29", updated_at: "2017-06-13 03:57:29", password_digest: "$2a$10$j9SIW6g6ASDW8j38XqNYtu/zsx2Y6Q43Smup7.uwSGW...", remember_digest: nil>, #<User id: 5, name: "Torey Schmitt", email: "example-4@railstutorial.org", created_at: "2017-06-13 03:57:29", updated_at: "2017-06-13 03:57:29", password_digest: "$2a$10$Lp8fRB0eUc0IFvBg6/xF6uMQg5eW2SXH7hP2Zggk6LM...", remember_digest: nil>, #<User id: 6, name: "Jorge Luettgen PhD", email: "example-5@railstutorial.org", created_at: "2017-06-13 03:57:29", updated_at: "2017-06-13 03:57:29", password_digest: "$2a$10$KPIuq2hPkHBsjeS7uG5X.u3LFz1j5PV.mjrAc4ht9w6...", remember_digest: nil>, #<User id: 7, name: "Eriberto Littel DVM", email: "example-6@railstutorial.org", created_at: "2017-06-13 03:57:29", updated_at: "2017-06-13 03:57:29", password_digest: "$2a$10$f8n9xlsWJXEdUUaWrNi6zeu4MwXSASplByQazMGj6Q4...", remember_digest: nil>, #<User id: 8, name: "Kelley Bode", email: "example-7@railstutorial.org", created_at: "2017-06-13 03:57:29", updated_at: "2017-06-13 03:57:29", password_digest: "$2a$10$SNwYoPOY5xtpmA6PkJ5wM.k7NycvFUrnUKZz2nDQedW...", remember_digest: nil>, #<User id: 9, name: "Jakob Muller", email: "example-8@railstutorial.org", created_at: "2017-06-13 03:57:29", updated_at: "2017-06-13 03:57:29", password_digest: "$2a$10$y6UTasDZYRzfoet.TG9wbO9dyQkiq1bkoleLhxMK6aE...", remember_digest: nil>, #<User id: 10, name: "Jean Franecki", email: "example-9@railstutorial.org", created_at: "2017-06-13 03:57:29", updated_at: "2017-06-13 03:57:29", password_digest: "$2a$10$A43xSShhuOePJ39KKQ3VWuzuq1oTkL25K2RG1t4.R8Q...", remember_digest: nil>, ...]> >> ?> page_all.class => User::ActiveRecord_Relation
10.3.4 ユーザー一覧のテスト
本章での学び
paginateに対するテストを作成する。
【fixture】テストユーザを30人一気に追加する
埋め込みRubyを使って、30回繰り返す。
<% 30.times do |n| %> user_<%= n %>: name: <%= "User #{n}" %> email: <%= "user-#{n}@example.com" %> password_digest: <%= User.digest('password')%> <% end %>
【test】統合テストの作成
rails generate
コマンドで自動生成する。
yokoyan:~/workspace/sample_app (updating-users) $ rails generate integration_test users_index Running via Spring preloader in process 2260 Expected string default value for '--jbuilder'; got true (boolean) invoke test_unit create test/integration/users_index_test.rb
【test】テストコードの実装
- ログインする
- usersコントローラのindexアクションにGETリクエストを送信する(users_path)
- インデックス画面のテンプレートが表示されることを確認
- paginationクラスを持つdivタグが存在することを確認
- 1ページ目にユーザーが存在することを確認
上記を踏まえ、実装する。
test "index including pagination" do log_in_as(@user) get users_path assert_template 'users/index' assert_select 'div.pagination' User.paginate(page: 1).each do |user| assert_select 'a[href=?]', user_path(user), text: user.name end end
testがgreenになることを確認。
yokoyan:~/workspace/sample_app (updating-users) $ rails test Running via Spring preloader in process 2578 Started with run options --seed 20647 38/38: [===============================================================================================================] 100% Time: 00:00:01, Time: 00:00:01 Finished in 1.88566s 38 tests, 142 assertions, 0 failures, 0 errors, 0 skips
演習1
試しにリスト 10.45にあるページネーションのリンク (will_paginateの部分) を2つともコメントアウトしてみて、リスト 10.48のテストが redに変わるかどうか確かめてみましょう。
<% #= will_paginate %> ・・・略・・・ <% #= will_paginate %>
テストがredになることを確認。
yokoyan:~/workspace/sample_app (updating-users) $ rails test Running via Spring preloader in process 2684 Started with run options --seed 62689 FAIL["test_index_including_pagination", UsersIndexTest, 1.3556210420210846] test_index_including_pagination#UsersIndexTest (1.36s) Expected at least 1 element matching "div.pagination", found 0.. Expected 0 to be >= 1. test/integration/users_index_test.rb:16:in `block in <class:UsersIndexTest>' 38/38: [===============================================================================================================] 100% Time: 00:00:01, Time: 00:00:01 Finished in 1.74196s 38 tests, 112 assertions, 1 failures, 0 errors, 0 skips
演習2
先ほどは2つともコメントアウトしましたが、1つだけコメントアウトした場合、テストが greenのままであることを確認してみましょう。will_paginateのリンクが2つとも存在していることをテストしたい場合は、どのようなテストを追加すれば良いでしょうか? ヒント: 表 5.2を参考にして、数をカウントするテストを追加してみましょう。
1つだけコメントアウトする。
<% #= will_paginate %> ・・・略・・・ <%= will_paginate %>
テストがgreenになることを確認。
yokoyan:~/workspace/sample_app (updating-users) $ rails test Running via Spring preloader in process 2468 Started with run options --seed 50744 38/38: [===================================================================================================================================================================================] 100% Time: 00:00:02, Time: 00:00:02 Finished in 2.01556s 38 tests, 142 assertions, 0 failures, 0 errors, 0 skips
will_paginateのリンクを2つカウントするためには、count: 2
を追加する。
assert_select 'div.pagination', count: 2
10.3.5 パーシャルのリファクタリング
本章での学び
動きは変えずに、より効率的なコードにリファクタリングを行う。
【view】indexビューのリファクタリング
<li>
以下をrender
に変更する。
<ul class="users"> <% @users.each do |user| %> <li> <%= gravatar_for user, size: 50 %> <%= link_to user.name, user %> </li> <% end %> </ul>
修正後。
<ul class="users"> <% @users.each do |user| %> <%= render user %> <% end %> </ul>
【view】_userパーシャルの作成
render user
で呼び出される、_user.html.erb
を作成する。
パーシャルは、物理ファイルだけでなく、Userクラスのuser変数に対しても使用できる。
<li> <%= gravatar_for user, size: 50 %> <%= link_to user.name, user %> </li>
この時点でアプリケーションをブラウザで確認すると、ユーザー一覧の表示はできる。
【view】indexページの完全なリファクタリング
@users.each do |user|
の部分を排除して、render
を、@users
変数に対して直接実行する。
Railsが自動的に、@users
が、Userオブジェクトのリストであると推測する。
さらに、自動的にそれぞれのユーザー情報を、_user.html.erb
パーシャルで出力する。
リファクタリング前のソース。
<ul class="users"> <% @users.each do |user| %> <%= render @user %> <% end %> </ul>
完全なリファクタリング後のソース
<ul class="users"> <%= render @users %> </ul>
演習1
リスト 10.52にあるrenderの行をコメントアウトし、テストの結果が redに変わることを確認してみましょう。
該当箇所をコメントアウトする。
<ul class="users"> <% #= render @users %> </ul>
テストがredになることを確認。
yokoyan:~/workspace/sample_app (updating-users) $ rails test Running via Spring preloader in process 2268 Started with run options --seed 34372 FAIL["test_index_including_pagination", UsersIndexTest, 1.2261453189421445] test_index_including_pagination#UsersIndexTest (1.23s) Expected at least 1 element matching "a[href="/users/14035331"]", found 0.. Expected 0 to be >= 1. test/integration/users_index_test.rb:18:in `block (2 levels) in <class:UsersIndexTest>' test/integration/users_index_test.rb:17:in `block in <class:UsersIndexTest>' 38/38: [===============================================================================================================] 100% Time: 00:00:01, Time: 00:00:01 Finished in 1.74507s 38 tests, 113 assertions, 1 failures, 0 errors, 0 skips
おわりに
ユーザー一覧画面が完成しました。 Faker gemで100人のデータを生成して、will_paginate gemとパーシャルを使うことで、 ページ送り処理が簡単に実装することができました。 gemを組み合わせていくだけでWEBアプリケーションができるのはすごいです。 Railsチュートリアルが終わったら、他にどんなgemがあるのか組み込んでみたいと思います。