}}最後に、サイト内移動用のヘッダーにユーザー一覧表示用のリンクを追加します。7.1に残っている最後の名前付きルートを割り当てます。10.40に示します。greenになります。次はこの問題をもう少し何とかしてみましょう。ユーザーの一覧ページにユーザーが1人しか表示されていない演習レイアウトにあるすべてのリンクに対して統合テストを書いてみましょう。ログイン済みユーザーとそうでないユーザーのそれぞれに対して、正しい振る舞いを考えてください。5.32にテストを追加してみましょう。サンプルのユーザーこの項では、一人ぼっちのユーザーに仲間を加えてあげることにします。indexページに複数のユーザーを表示させるためには、ブラウザからユーザー登録ページへ行って手作業で1人ずつ追加するという方法もできますが、せっかくなのでRubyを使ってユーザーを一気に作成してみましょう。これは、実際にいそうなユーザー名を作成するgemです9。次のようにすべての環境で使えるようにしています。installを実行します。Railsではdb/seeds.rbというファイルを標準として使います。10.43に示します。10.43のコードは少し応用的です。詳細が完全に理解できなくても問題ありません。Userという名前とメールアドレスを持つ1人のユーザと、それらしい名前とメールアドレスを持つ99人のユーザーを作成します。しておくと見過ごしやすいエラーを回避できるので、デバッグが容易になります。db:seedデータベース上にデータを追加するのは遅くなりがちで、システムによっては数分かかることもあり得ます。db:migrate:resetコマンドがうまく動かない時もあるそうです。db:seedでRailsタスクを実行し終わると、サンプルアプリケーションのユーザーが100人になっています。最初のいくつかのメールアドレスについては、デフォルトのGravatar画像以外の写真を関連付けてみました。試しに他人の編集ページにアクセスしてみて、10.2.2で実装したようにリダイレクトされるかどうかを確かめてみましょう。ページネーションこれで、最初のユーザーにも仲間ができました。今度は逆に、1つのページに大量のユーザーが表示されてしまっています。100人でもかなり大きい数であると思いますし、今後は数千ユーザーに増える可能性もあります。いうもので、この場合は、例えば1つのページに一度に30人だけユーザーを表示するというものです。Railsには豊富なページネーションメソッドがあります。今回はその中で最もシンプルかつ堅牢なwill_paginateメソッドを使ってみましょう。gemを両方含め、Bootstrapのページネーションスタイルを使ってwill_paginateを構成する必要があります。installを実行します。install実行したら、新しいgemが正しく読み込まれるように、Webサーバーを再起動してください。ページネーションが動作するには、ユーザーのページネーションを行うようにRailsに指示するコードをindexビューに追加する必要があります。indexアクションにあるUser.allを、ページネーションを理解できるオブジェクトに置き換える必要もあります。同じコードがリストの上と下に2つありますが、その理由はこの後で説明します。%>このwill_paginateメソッドは少々不思議なことに、usersビューのコードの中から@usersオブジェクトを自動的に見つけ出し、それから他のページにアクセスするためのページネーションリンクを作成しています。10.45のビューはこのままでは動きません。10.36)、will_paginateではpaginateメソッドを使った結果が必要だからです。必要となるデータの例は次のとおりです。1,...paginateでは、キーが:pageで値がページ番号のハッシュを引数に取ります。したがって、1ページ目は1から30のユーザー、2ページ目は31から60のユーザーといった具合にデータが取り出されます。paginateは単に最初のページを返します。paginateを使うことで、サンプルアプリケーションのユーザーのページネーションを行えるようになります。ここで:pageパラメーターにはparams[:page]が使われていますが、これはwill_paginateによって自動的に生成されます。(システム環境によっては、ここでRailsを再起動する必要があるかもしれません)。will_paginateをユーザーリストの上と下の両方に配置してあるので、ページネーションのリンクもページの上と下の両方に表示されています。10.12のように次ページに移動することができるようになります。(2ページ目)演習Railsコンソールを開き、pageオプションにnilをセットして実行すると、1ページ目のユーザーが取得できることを確認してみましょう。比較してみてください。ユーザー一覧のテストこれでユーザーの一覧ページが動くようになったので、10.3.3のページネーションに対する簡単なテストも書いておきましょう。今回のテストでは、ログイン、indexページにアクセス、最初のページにユーザーがいることを確認、ページネーションのリンクがあることを確認、といった順でテストしていきます。最後の2つのステップでは、テスト用のデータベースに31人以上のユーザーがいる必要があります。10.23で2人目のユーザーをfixtureに追加しましたが、今回はもっと多くのユーザーを作成する必要があります。手動で追加するのは面倒そうですね。幸運にも、ユーザー用fixtureファイルのpassword_digest属性で使ったように、fixtureでは埋め込みRubyをサポートしています。10.47では2人の名前付きユーザーも一緒に追加しています。10.47のfixtureファイルができたので、indexページに対するテストを書いてみます。いつものように統合テストを生成します。test/integration/users_index_test.rb今回のテストでは、paginationクラスを持ったdivタグをチェックして、最初のページにユーザーがいることを確認します。10.48に示します。redに変わるかどうか確かめてみましょう。greenのままであることを確認してみましょう。5.2を参考にして、数をカウントするテストを追加してみましょう。パーシャルのリファクタリングユーザー一覧ページにページネーションを実装することができましたが、私はここで1つの改良を加えてみたいのです。実はRailsにはコンパクトなビューを作成するための素晴らしいツールがいくつもあります。サンプルアプリケーションのテストは既に完了しているので、Webサイトの機能を損なうことなく安心してリファクタリングに取りかかれます。対してではなく、Userクラスのuser変数に対して実行している点に注目してください12。%></li>これは間違いなく大きな進歩です。ここで終わらせず、さらに改良してみましょう。Userオブジェクトのリストであると推測します。ユーザーのコレクションを与えて呼び出すと、Railsは自動的にユーザーのコレクションを列挙し、それぞれのユーザーを_user.html.erbパーシャルで出力します。10.52のコードは極めてコンパクトになります。なることを確認するようにしてください。redに変わることを確認してみましょう。ユーザーを削除するユーザーの一覧ページはついに完了しました。残るはdestroyだけです。これを実装することで、RESTに準拠した正統なアプリケーションとなります。この節では、ユーザーを削除するためのリンクを追加します。10.13に示します。削除を行うのに必要なdestroyアクションも実装します。ユーザーのクラスを作成しましょう。特権を持つ管理ユーザーを識別するために、論理値をとるadmin属性をUserモデルに追加します。使えるようになりますので、これを使って管理ユーザーの状態をテストできます。10.14のようになります。論理値をとるadmin属性が追加されたUserモデルここでいつものように、マイグレーションを実行してadmin属性を追加しましょう。ターミナル上で、この属性の型をbooleanと指定します。falseという引数をadd_columnに追加しています。adminの値はデフォルトでnilになりますが、これはfalseと同じ意味ですので、必ずしもこの引数を与える必要はありません。このように明示的に引数を与えておけば、コードの意図をRailsと開発者に明確に示すことができます)。endend後はいつものようにマイグレーションを実行します。db:migrateRailsコンソールで動作を確認すると、期待どおりadmin属性が追加されて論理値をとり、さらに疑問符の付いたadmin?メソッドも利用できるようになっています。admin属性の状態をfalseからtrueに反転しています。password)end次に、データベースをリセットして、サンプルデータを再度生成します。trueを設定することでユーザーを管理者にしていることにお気付きになりましたでしょうか。ここでは、荒れ狂うWeb世界にオブジェクトをさらすことの危険性を改めて強調しています。任意のWebリクエストの初期化ハッシュをオブジェクトに渡せるとなると、攻撃者は次のようなPATCHリクエストを送信してくるかもしれません13。/users/17?admin=1このリクエストは、17番目のユーザーを管理者に変えてしまいます。ユーザーのこの行為は、少なくとも重大なセキュリティ違反となる可能性がありますし、実際にはそれだけでは済まないでしょう。このような危険があるからこそ、編集してもよい安全な属性だけを更新することが重要になります。Parametersを使って対策します。次のようにparamsハッシュに対してrequireとpermitを呼び出します。end上のコードでは、許可された属性リストにadminが含まれていないことに注目してください。これにより、任意のユーザーが自分自身にアプリケーションの管理者権限を与えることを防止できます。この問題は重大であるため、編集可能になってはならない属性に対するテストを作成することをぜひともオススメします。(10.4.1.2)。演習Web経由でadmin属性を変更できないことを確認してみましょう。送信するテストを作成してみてください。テストが正しい振る舞いをしているかどうか確信を得るために、まずはadminをuser_paramsメソッド内の許可されたパラメータ一覧に追加するところから始めてみましょう。redになるはずです。destroyアクションUsersリソースの最後の仕上げとして、destroyアクションへのリンクを追加しましょう。ユーザーindexページの各ユーザーに削除用のリンクを追加し、続いて管理ユーザーへのアクセスを制限します。:deleteによって行われている点に注意してください。各リンクをif文で囲い、管理者にだけ削除リンクが表示されるようにしています。10.15のようになります。ブラウザはネイティブではDELETEリクエストを送信できないため、RailsではJavaScriptを使って偽造します。JavaScriptがオフになっているとユーザー削除のリンクも無効になるということです。JavaScriptをサポートしないブラウザをサポートする必要がある場合は、フォームとPOSTリクエストを使ってDELETEリクエストを偽造することもできます。こちらはJavaScriptがなくても動作します14。追加する必要があります。10.58では:destroyアクションもlogged_in_userフィルターに追加しています。している点に注目してください。(より具体的には、削除リンクが見えているユーザーのみ削除できる)。実はまだ大きなセキュリティホールがあります。ある程度の腕前を持つ攻撃者なら、コマンドラインでDELETEリクエストを直接発行するという方法でサイトの全ユーザーを削除してしまうことができるでしょう。サイトを正しく防衛するには、destroyアクションにもアクセス制御を行う必要があります。これを実装してようやく、管理者だけがユーザーを削除できるようにします。10.2.1と10.2.2と同じように、今回はbeforeフィルターを使ってdestroyアクションへのアクセスを制御します。10.59に示します。管理者ユーザーとしてログインし、試しにサンプルユーザを2〜3人削除してみましょう。ユーザー削除のテストユーザーを削除するといった重要な操作については、期待された通りに動作するか確かめるテストを書くべきです。%>10.2.1で経験してきたように、Usersコントローラをテストするために、アクション単位でアクセス制御をテストします。8.31のログアウトのテストと同様に、削除をテストするために、DELETEリクエストを発行してdestroyアクションを直接動作させます。このとき2つのケースをチェックします。1つは、ログインしていないユーザーであれば、ログイン画面にリダイレクトされることです。1つは、ログイン済みではあっても管理者でなければ、ホーム画面にリダイレクトされることです。10.61に示します。使って、ユーザー数が変化しないことを確認している点に注目してください。10.61のテストでは、管理者ではないユーザーの振る舞いについて検証していますが、管理者ユーザーの振る舞いと一緒に確認できるとよさそうです。10.48のテストに今回のテストを追加していくことにします。これにより、後ほど追加する管理者の振る舞いについても簡単にテストが書けそうです。今回のテストで唯一の手の込んだ箇所は、管理者が削除リンクをクリックしたときに、ユーザーが削除されたことを確認する部分です。今回は次のようなテストでこれを実現しました。7.33ではassert_differenceメソッドを使ってユーザーが作成されたことを確認しましたが、今回は同じメソッドを使ってユーザーが削除されたことを確認しています。減ったかどうかを確認しています。10.62のようになります。10.57により、管理者であれば削除リンクが表示されないからです)。これで、削除に関するコードに対して、よくテストできている状態になりました。redに変わることを確認してみましょう。最後に5.4でUsersコントローラをご紹介して以来、長い道のりをたどってきました。あの頃はユーザー登録すらありませんでしたが、今は登録もログインもログアウトもできます。プロフィールの表示も、設定の編集も、すべてのユーザーの一覧画面もあります。一部のユーザーは他のユーザーを削除することすらできるようになりました。整ったといえるでしょう。続く第11章と第12章では、さらに2つの改善を加えます。1つはユーザーがパスワードを忘れてしまったときのためのパスワードを再設定する機能です。次の章に進む前に、すべての変更をmasterブランチにマージしておきましょう。(本番データベースをリセットするにはpg:resetタスクを使います)。10.11にあるようなローカル環境での表示順序と異なってしまうことです。これは現時点ではまだデフォルトの表示順序が指定されていないことが原因です。結果として、データベースの内容に応じて表示順序が異なってしまいます。それだけのことかと思われるかもしれませんが、これは今後マイクロポストを実装するときに問題となります。この問題については13.1.4で解決していきます。(2014-08-25)。(悪いことをしているわけでもありません)。この詳細に関心を抱くのはRailsフレームワークそのものの開発者ぐらいであり、Railsでアプリケーションを開発する人にとっては重要ではありません。Gómezの指摘と提案に感謝します。この方法だと、newとeditのパーシャルにある重複をキレイに取り除くことができます。before_actionはこれまでbefore_filterという名前でしたが、「アクションの直前で実行される」という点を強調するためにRailsコアチームによって名前が変更されました。gemを適用しています。Adlerの指摘によって、この問題と解決策が見つかりました。(2014-08-25)。ちなみにこれはTwitterの認可モデルと同じです。これまでと同様に、Gemfileで指定した各gemのバージョンはgemfiles-4th-ed.railstutorial.orgと一致している必要があります。うまく次に進めない場合はチェックしてみてください。db:resetコマンド1つでこれら2つのタスクを実行することもできますが、最新のRailsだとうまく動かないのでこのようにしています。これまでと同様に、Gemfileで指定した各gemのバージョンはgemfiles-4th-ed.railstutorial.orgと一致している必要があります。うまく次に進めない場合はチェックしてみてください。このuserという名前そのものはまったく重要ではないことに注意してください。foobarと呼び出しても問題なく動作します。curlなどのコマンドラインツールを使うと、PATCHリクエストをこの形式で送信することができます。株式会社によって運営されています。基づく表記プライバシーポリシーお問い合わせTIPS原著者からのメッセージ目次コードサンプルみんなのつぶやきRailsガイド。