第6章の備忘録
##環境
Rails 6.0.3
Ruby 2.6.3
##目次
1 rails console --sandbox
2 new と update メソッドの違い
3 検証 Validation
4 セキュアなパスワード
###1 rails console --sandbox
rails console
と違って、終了時にrolbackされるのが特徴!
データベースを変更せずに色々試したい場合はこちらを使う。
###2 new と update メソッドの違い
####newメソッド
saveメソッドと併用して、データベースに保存する。
####updateメソッド
updateメソッドは成功時に更新と保存を一括で行う。
ただし、1つでも失敗するとupdateメソッド自体が失敗する。
もし、特定の値のみupdateしたい場合はupdate_attributeメソッドを使う。
>> user.update_attribute(:name, "testName")
=> true
>> user.name
=> "testName"
###3 検証 Validation
####存在性 :presence
渡された属性が存在することを検証
(例)presence: true
####長さ :length
email等の長さに制限を設ける
(例)length: { maximum: 50 }
####フォーマット :format
適切なemailの形式になっているか等を確認することを要求できる
特にemailのフォーマットを設定する時には正規表現を用いる。
使いたい時に調べればいいかな〜って感じ。覚えておくのは難しい💦何回か実際に使えば自然に覚えるかな〜ぐらいのスタンス。。
(例)format: { with: ~~~ }
####一意性 :uniqueness
重複しないことを設定することができる
またRailsチュートリアルでは、ユーザーが新規登録する時に誤ってボタンを素早く2回押してしまうことでリクエストが2回送られた時に、一意性が保たれるよう、データベースレベルでもemail
のカラムにインデックスを追加している。
(例)uniqueness: true
class AddIndexToUsersEmail < ActiveRecord::Migration[6.0]
def change
add_index :users, :email, unique: true
end
end
最後にパスワードも含めたバリデーションをテストコード含め掲載してます
####errors.messages メソッド
バリデーションを行っている時にエラーが出たら、errors.messages(errors.full_messages)メソッドを使うことで、エラーの内容が確認できる。便利!
>> # 例
>> user.errors.full_messages
=> ["Name can't be blank"]
###4 セキュアなパスワード
セキュアパスワードの手法は、ユーザーにパスワードともう一度パスワードの確認を行い、ハッシュ化したものをデータベースに保存する。
ここでのハッシュ化とは、ハッシュ関数を使って、パスワードを元に戻すことができないデータに変換する処理のことである。
セキュアなパスワードの実装はまず、has_secure_password
メソッドをModelで呼び出す。
このメソッドを追加すると、
- セキュアにハッシュ化したパスワードを、
password_digest
属性でデータベースに保存 -
password
とpassword_confirmation
属性が使えるようになる。また、存在性と値が一致しているかどうかのバリデーションが追加される。 -
authenticate
メソッド(引数の文字列がパスワードと一致するとUserオブジェクト、間違っているとfalseを返す)が使用可能。
の3つの機能が使えるようになる。
has_secure_passwordメソッドの機能を使えるようにするための条件は、モデル内にpassword_digest
属性が含まれていること。ここにハッシュ化されたパスワードが保存される。
またhas_secure_password
メソッドを使ってハッシュ化するにはbcrypt
gemを追加する必要がある。
最後に、テストコードを抜粋して、学びになった部分を掲載
2周目になると、テストコードの流れがしっかり理解できる!!
class User < ApplicationRecord
# 保存前にemailを全て小文字に書き換え
before_save { email.downcase! }
validates :name, presence: true, length: { maximum: 50 }
# emailの正規表現を定数で用意
VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
validates :email, presence: true, length: { maximum: 255 },
format: { with: VALID_EMAIL_REGEX },
uniqueness: true
has_secure_password
validates :password, presence: true, length: { minimum: 6 }
end
require 'test_helper'
class UserTest < ActiveSupport::TestCase
def setup
@user = User.new(name: "Example User", email: "user@example.com",
password: "foobar", password_confirmation: "foobar")
end
# 抜粋して取り上げる
# 誤ったemailが適切に拒否されるかチェック
test "email validation should reject invalid addresses" do
# invalidなemailをいくつか配列にまとめる。%wを使用。空白で分ける
invalid_addresses = %w[user@example,com user_at_foo.org user.name@example.
foo@bar_baz.com foo@bar+baz.com]
invalid_addresses.each do |invalid_address|
@user.email = invalid_address
# valid? : その値が妥当かチェック。assert_notと併用して、妥当でないことが適切に判定されるかチェック
# 第2引数に、エラーが分かるように文字列を設定
assert_not @user.valid?, "#{invalid_addresses} should be invalid"
end
end
test "email addresses should be unique" do
# dupメソッド : 複製する
duplicate_user = @user.dup
@user.save
# 同じemailが適切に拒否されるかチェック
assert_not duplicate_user.valid?
end
test "password should be present (noneblank)" do
@user.password = @user.password_confirmation = " " * 6
assert_not @user.valid?
end
end