Ruby on Railsチュートリアル第6版の第6章のまとめです。
個人的に気になったところ、難しかったところ、わからなかったところを中心にまとめていきます。基本的に自分の理解を助けることと、復習しやすくすることを目的とした記事ですが、今Ruby on Railsチュートリアルをやってる人に役立つ情報があるかもしれません。
僕の学習の順番は、1周目はRailsチュートリアル第4版(Rails5.1)を使い、2周目で第6版を使うという感じになってます。これは1周目が終わったところで第6版のWebテキスト版がリリースされたからです。
ちなみに、2周目は解説動画を購入してやってます。オススメです。
第6章 ユーザーのモデルを作成する
第6章はユーザーモデルの作成です。アプリケーションらしくなってくるので、楽しくなってくるところかなと思います。
Railsチュートリアルでは勉強のために認証システムを作っていきますが、実際にはDeviseというgemが使われるようです。そういうのを使う前に、認証システムがどういう仕組みになってるかを理解するのが目的という感じのようです。
気になるのは、Railsチュートリアルでの認証システムからDeviseのような認証システムの利用にどうステップアップすればいいのか、というところ。気になりつつも、進んでいきます。
6.1 Userモデル
モデルはRailsアプリケーションとデータベースを繋ぐものです。Active RecordというRailsのライブラリが関係してるようなので、さらに踏み込んだ学習をするなら、Active Recordを調べる必要がありそうです。
いつも通りに、ブランチを作って先に進みます。
6.1.1 データベースの移行
データベースはデータを永続的に保存するために必要です。サーバーを再起動してデータが消えたら困るので、データベースが重要になるわけです。
Railsチュートリアルの指示通りにUserモデルを作ります。コントローラ名は複数形でしたが、モデル名は単数形を使う慣習になってるそうです。テーブル名は複数形なので、混乱しそうです。
マイグレーションを実行することで、データベースが作られます。
Railsではマイグレーションでデータベースを作ると、id、created_at、updated_atというカラムが自動的に作られます(マジックカラムと呼ぶみたいですが、idも入るのかは不明)。これらは後で活躍してくれます。
本当にデータベースが作られたかを確認するために、DB Browser for SQLiteというツールを使います。英語が苦手でWindows環境の人は、「開発環境構築備忘録 DB Browser for SQLite編(Windows)」を参考にするといいと思います。
6.1.2 modelファイル
モデルファイルの確認です。指示通りで問題ないと思います。
6.1.3 ユーザーオブジェクトを作成する
Railsコンソールを使っていろいろ実験します。データベースを変更しないために、サンドボックスモードで起動します。
指示通りにやればOKです。サンドボックスモードで起動してるので、気になることがあったらとりあえず試してみることをオススメします。
6.1.4 ユーザオブジェクトを検索する
Railsコンソールでの実験の続きです。
findメソッドとfind_byメソッドの両方でidを使った検索ができますが、存在しないユーザーidに対して実行したときの返答が異なるようです。ここの説明は解説動画の方がわかりやすいと思います。
6.1.5 ユーザーオブジェクトを更新する
Railsコンソールでの実験はまだ続きます。
ユーザーのデータの更新にはいくつかの方法があるようです。updateメソッドとupdate_attributeメソッドの違いが重要になる場面もあるそうです。
6.2 ユーザーを検証する
ユーザー登録時にちゃんとしたデータで登録するように変更を加えます。バリデーションです。
6.2.1 有効性を検証する
ここではテスト駆動開発を使います。
ここで出てくるsetupメソッドはこれから何度も出てくるので、覚えておくと楽になると思います。
6.2.2 存在性を検証する
ユーザー名とかメールアドレスが空欄だったりすると困るので、ちゃんと文字が入ってることを検証します。
そのためのテストを書き、テストが通るようにコードを書いていきます。何かを追加するたびにテストを走らせると、何をやってるのかわかりやすくなると思います。
6.2.3 長さを検証する
ユーザー名とメールアドレスの文字数に上限を設定します。
ここで書くテストで、文字の掛け算が出てきます。「〇文字以上の適当な文字列が欲しい」ときに役立つので覚えておくと便利かなと思います。
>> "a" * 5
=> "aaaaa"
>> "abc" * 5
=> "abcabcabcabcabc"
6.2.4 フォーマットを検証する
メールアドレスが適切なものであるかの検証です。
「.com」が「,com」になってたりとか、入力時のミスは必ず起きるので、それも防止する感じですね。考えられるミスなどをテストに書くみたいです。
ここで重要なのは「正規表現」だと思います。
ただ、正規表現はそれだけで1冊の本になるくらいのものらしいので、Ruby on Railsの学習という意味では、何となくの理解でいいと思います。必要になったら勉強ですね。
とりあえず、ざっと読んで、コピペしました。
6.2.5 一意性を検証する
同じメールアドレスを使った別のユーザーが登録されないように、メールアドレスの一意性を検証する仕組みを入れます。
基本的にはじっくり読めばわかるかなと思いますが、データベースレベルでも一意性を強制するところは、解説動画の方がわかりやすいなと思いました。
コラム6.2「データベースのインデックス」に書かれてる、インデックスを付けると「索引の中から探すだけ~」という話は、わかるような、わからないような感じで、「そういうもんなんだ」くらいの理解になってます。
データベースレベルで一意性を強制した後に、Railsチュートリアルの方を読まずにテストを走らせたら、REDになった上にたくさんのエラーが出て焦りました。
でも、これは自動的に作られたfixtureの問題で、Railsチュートリアルにもちゃんと書いてありました。
次に、データベースによって大文字と小文字を区別するかどうかが違うかもしれないという問題を解決します。
before_saveコールバックを使って、メールアドレスを小文字に変換してからデータベースに保存するようにします。
ここのところのコード変更がよくわからなかったので、自分なりの理解をまとめておきます。
メールアドレスを小文字に変換してからデータベースに保存すると、データベースにあるメールアドレスは必ず小文字になってるので、大文字と小文字の区別をしないようにuniquenessを設定する必要がなくなります。
ということで、validatesのところには
uniqueness: true
と書くことになります。
この変更の影響はテストに出てきます。このままテストを実行するとREDになります。
テストではデータベースに保存したメールアドレスを大文字に変換して、それが一意性の検証で引っかかるようにしてたからです。
つまり、最初は「大文字と小文字の区別をしない状態」をテストしてましたが、変更したことで「大文字と小文字の区別をする状態」をテストするようになってるということです。
これはuniquenessを変更したことで起こってます。
そもそもデータベースには小文字でしか保存されないようにしたので、大文字が使われてるかどうかは関係なくなりました。ということで、テストで大文字に変換するところが必要なくなったわけです。
図にするとこんな感じですかね。
6.3 セキュアなパスワードを追加する
パスワードをそのままデータベースに保存してると危険なので、「ハッシュ化」という処理をして保存します。
他のプログラミング言語でいうところの連想配列である「ハッシュ」とは別物です。
6.3.1 ハッシュ化されたパスワード
ハッシュ化されたパスワードを保存するためのカラムをusersテーブルに作ります。このとき、決められた方法でマイグレーション名を付けると、自動的に必要なカラムを追加するコードが書かれたファイルが作られます。
Railsチュートリアルではサラッとした説明ですが、解説動画では詳しく説明されてます。
ハッシュ化するための「bcrypt」というgemをインストールします。Gemfileに書いて、bundle installですね。ここではbundle updateは必要ありません。理由は、「Ruby on Railsチュートリアル第6版 第3章まとめ」に書いてあります。
6.3.2 ユーザーがセキュアなパスワードを持っている
Userモデルにhas_secure_passwordを追加して完了なんですが、テストは失敗します。これはテスト側の問題なので、テストを書き換えます。
6.3.3 パスワードの最小文字数
「パスワードは〇文字以上」というよくやる制限を付けます。セキュリティ的には大事なものですよね。ここもテスト駆動開発です。
テストコードに「多重代入(Multiple Assignment)」が出てきます。
a = b = "Rails"
これは
a = "Rails"
b = "Rails"
これと同じ意味です。最初は混乱するかもしれませんが、わかれば便利ですよね。
6.3.4 ユーザーの作成の認証
ここまででUserモデルの基本的なところが完成したので、Railsコンソールで実際に試してみましょう。
ここで出てくるauthenticateメソッドは重要なもので、この先にも出てきます。
これで第6章は終わりです。最後に、いつも通りコミット、プッシュ、デプロイして完了となります。
ただ、Herokuなどの本番環境でUserモデルを使うには、本番環境でもマイグレーションを実行する必要があります。
RailsチュートリアルではHerokuでマイグレーションしてから、本番環境のコンソールでユーザー登録を試してみるように書いてありましたが、マイグレーション前にやってみました。
それで出てきたエラーがこれです
ActiveRecord::StatementInvalid (PG::UndefinedTable: ERROR: relation "users" does not exist)
「usersが存在しないよ!」と言われてますね。
マイグレーションしてからやってみると成功します。これでマイグレーションしないとダメなのがわかりますね。
まとめ
第6章ではUserモデルを作って、パスワードの管理をセキュアなものにしました。普段使ってるWebサービスの裏側にはこんな感じの仕組みがあったんですね。
ここまででMVCのモデル、ビュー、コントローラについて学びました。これはRailsの基本的な構造なのでしっかりと覚えておいた方がいいと思います。
もしよくわかってなかったら、先に進む前に復習するのもいいかもしれません。
次章からはUserモデルに機能を追加してくことになります。だんだん本格的なアプリケーションになっていきます。