読者です 読者をやめる 読者になる 読者になる

コンパイラかく語りき

文系新卒プログラマーのメモ

文系プログラマーがRailsでロシア語アプリケーションをつくる⑩ ~ユーザーモデルに制約をかける~

Rails

どうも!chuckです。

早いもので、このシリーズも10回目ですね〜。今回はユーザーモデルに対して色々な制約をかけていきますヽ(=´▽`=)ノ

 

chuckwebtips.hatenablog.com

 

 

今回はRubyOnRailsチュートリアル6章の内容にほぼ準拠しています。

 

RSpecを使ったUserモデルのテスト

前回までで、Userモデルに対するテストは以下のようになっています。

f:id:chuck0523:20150722062050p:plain

5行目のbeforeブロックを使って前処理をしています。処理の内容は、新しくUserのインスタンスを作成して、userインスタンス変数に格納しています。

 

7行目では、subjectブロックを使ってテストサンプルのデフォルトとして@userを設定しています。

 

9,10行目では、オブジェクトが各々の属性に反応するかを確認しています(よくわからない…)

 

ここまでが基本的なテスト。

bundle exec rspec spec/ を実行するとテストにパスしますヽ(=´▽`=)ノ

 

ここからはUserモデルに対する4つの検証を行っていきます。

1,存在性(presense)の確認

Userモデルを作成して保存する際に、name属性とemail属性が存在することを確認します。NotNull的なことかな??

検証をするためには、app/model/user.rbファイルにvalidateメソッドを加えます。

f:id:chuck0523:20150722063419p:plain

validates :name, presenece: true と書くことでname属性が必須となります。この状態でname属性が空のデータを保存しようとするとエラーになります(作成自体はできる)

 

f:id:chuck0523:20150722063539p:plain

Rails consoleでの確認。

 

userのname属性が空だった時のテストを書きます。

f:id:chuck0523:20150722063748p:plain

spec/model/user_spec.rb

 

テストの結果は成功になります。

f:id:chuck0523:20150722064101p:plain

 

ただし、validateメソッドコメントアウトするとエラーになってしまうことから、存在性の確認が正常に働いていることがわかります。

f:id:chuck0523:20150722064136p:plain

f:id:chuck0523:20150722064151p:plain

 

これで、ユーザー登録の際に名前が必須となりました。(Emailにも同様の処理を行います)

 

2,長さ(length)の検証

データの長さに対する制限を加えます。

f:id:chuck0523:20150722064541p:plain

spec/model/user_spec.rb

 

長さに対する検証は lengthとを使います。

f:id:chuck0523:20150722064653p:plain

app/model/user.rb

 

3, フォーマットの検証

メールアドレスの検証も実施しますが、ちょっと工夫をします。こちらがRSpecへの追記。

f:id:chuck0523:20150722065050p:plain

spec/model/user_spec.rb

 

上のブロックでは無効なアドレスが不正になることを、下のブロックではその逆を検証しています。

31,42行目の %wは文字列の配列を作成し、それに対してeachで各々に処理を行っています。

 

フォーマットの検証には format を使います。

f:id:chuck0523:20150722070149p:plain

3行目で正規表現の定数を作成し、4行目でformatに渡しています。

 

4, 一意性の検証

そのデータが唯一無二であり、他のデータと被っていないことを検証します。ただし、今回のテストは今までと異なり、実際にデータを登録する必要があります。

 

追記するテストがこちら。

f:id:chuck0523:20150722070734p:plain

spec/model/user_spec.rb

 

@user.dupはデータを複製しています。これを.saveすることで、作成したデータと同様のデータを事前に登録することができます。

このうえでデータを登録すると、既に存在するのでエラーになることを確認します。

 

f:id:chuck0523:20150722071120p:plain

app/model/user.rb

 

9行目に一意性を強いることを追記しました。

 

ただし、更に変更を加えてメールアドレスの大文字と小文字を無視するようにします。

f:id:chuck0523:20150722071419p:plain

case_sensitive: falseとすることで大文字と小文字を無視するようになります。

 

ただし、ここでは念の為にメールアドレスに対してさらにユニーク性を高めます。

f:id:chuck0523:20150722071832p:plain

rails generate migration add_index_to_user_email を実行します。うわーこれカラムに追加でやったやつだ!

 

出来上がったファイルにこのように記述。

f:id:chuck0523:20150722071936p:plain

add_iindexメソッドを利用して、emailカラムをユニークにしています。

 

マイグレーションファイルを作成したので、bundle exec rake db:migrate を実行。

 

すると、db/schema.rbが以下のように変更されます。

f:id:chuck0523:20150722072112p:plain

23行目に追記されたことがわかります。

 

ただし、もう1つやることがあります。それはデータを保存する前にメールアドレスを全部小文字に変換する作業です。

データベースのアダプタが常に大文字と小文字を区別するindexを使ってるかどうか分からないから、らしい。(ふーん)

 

そのためにコールバックというメソッドを使います。ActiveRecordに何かをしてもらう便利なメソッドのよう。

f:id:chuck0523:20150722072505p:plain

app/model/user.rb

 

2行目のbefore_saveがコールバックです。保存する前にブロック内の処理を行ってくれます。ブロック内では、.downcaseメソッドを使ってメールアドレスを小文字に変換しています。

 

長くなりましたが以上で検証は終わりですヽ(=´▽`=)ノ

今回施した検証。

  1. 存在性(presence)
  2. 長さ(length)
  3. フォーマット(format)
  4. 一意性(unique)

 

まとめ的な

ユーザモデルに対して制約をかけました。単語データの方は制約も何もあったもんじゃないので笑、いかにもモデルの作成って感じで楽しかったです!

さらに、制約をかけつつRSpecも書けて良かった!Railsチュートリアルで2回やってるはずなのに、今回ようやく制約とそのテストを理解できたように思います(´ω`)

 

次回はユーザーモデルに安全なパスワードを付け加える予定です(`・ω・´)ゞ

 

Railsチュートリアル

railstutorial.jp

 

Follow Me