###Userモデルを生成する
ubuntu:~/environment/my_app (modeling-users) $ rails generate model User name:string email:string
Running via Spring preloader in process 3689
invoke active_record
create db/migrate/*********_create_users.rb
# Usersテーブルの詳細を設定させるファイル
create app/models/user.rb
# useデータモデルの使用を書く
invoke test_unit
create test/models/user_test.rb
# そのテストファイル
create test/fixtures/users.yml
# テストユーザーのファイル
###(usersテーブルを作るための)Userモデルのマイグレーション
マイグレーションは元のシステムからデータなどを抽出して移行させる
db/migrate/[timestamp]_create_users.rb
class CreateUsers < ActiveRecord::Migration[6.0]
def change
# userのデータモデルのカラムを設定させる
create_table :users do |t|
# create_table テーブルを作成
# usersというテーブルから要素を一つずつ取り出す
t.string :name
# nameカラムを生成 属性 文字列
t.string :email
# emailカラムを生成 属性 文字列
t.timestamps
# created_atとupdated_atを作成
# 多分日付が代入させる
end
end
end
###有効なUserかどうかをテストする
test/models/user_test.rb
require 'test_helper'
class UserTest < ActiveSupport::TestCase
def setup
@user = User.new(name: "Example User", email: "user@example.com")
# テストユーザー
# create_user.rbでusersテーブルに沿って作成
# 現時点では有効
end
test "should be valid" do
assert @user.valid?
# usersテーブルで有効なデータモデルか確認
end
test "name should be present" do
@user.name = " "
# 名前を空にする
assert_not @user.valid?
# 空にしたデータテーブルは無効か?
end
end
ubuntu:~/environment/my_app (modeling-users) $ rails test:models
Run options: --seed 28244
Running:
F
Failure:
UserTest#test_name_should_be_present [/home/ubuntu/environment/my_app/test/models/user_test.rb:20]:
Expected true to be nil or false
rails test test/models/user_test.rb:17
.
Finished in 0.031667s, 63.1576 runs/s, 63.1576 assertions/s.
2 runs, 2 assertions, 1 failures, 0 errors, 0 skips
nilかfalseが返ってくるからどうかしてほしいらしい。
なので
渡された属性が存在することを検証します。「存在性(Presence)を調べる。のか?
name属性の存在性を検証する
app/models/user.rb
class User < ApplicationRecord
# 継承させる
validates :name, presence: true
# nameカラムが存在する
# validates(:name, presence: true)と書くこともできる
end
存在性(presence)の検証、長さ(length)の検証、フォーマット(format)の検証、一意性(uniqueness)の検証です。6.3.2では、よく使われる最終検証として確認(confirmation)を追加します。
###ユーザー側の入力する名前とメアドの仕様
user.rb
class User < ApplicationRecord
# 継承させる
validates :name, presence: true, length: { maximum: 50 }
# nameカラムが存在する
# validates(:name, presence: true)
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: { case_sensitive: false }
# :case_sensitive 大文字と小文字を区別しないで一意性を検証する
end
###ユーザー側の入力された名前とメアドのテスト
test/models/user_test.rb
require 'test_helper'
class UserTest < ActiveSupport::TestCase
def setup
@user = User.new(name: "Example User", email: "user@example.com")
# テストユーザー
# create_user.rbでusersテーブルに沿って作成
# 現時点では有効
end
test "should be valid" do
# 有効を検証
assert @user.valid?
# usersテーブルで有効なデータモデルか確認
end
test "name should be present" do
@user.name = ""
# 名前を空にする
assert_not @user.valid?
# 空にしたデータテーブルは無効か?
end
test "email should be present" do
# 存在性の検証
@user.email = " "
# メールを空にする
assert_not @user.valid?
# 無効か?
end
test "name should not be too long" do
# 長さの検証
@user.name = "a" * 51
# 文字列の長さを検証
assert_not @user.valid?
# 無効か?
end
test "email should not be too long" do
@user.email = "a" * 244 + "@example.com"
# 文字列の長さの検証
assert_not @user.valid?
# 無効か?
end
test "email validation should accept valid addresses" do
# メールフォーマットの検証をする
valid_addresses = %w[user@example.com USER@foo.COM A_US-ER@foo.bar.org
first.last@foo.jp alice+bob@baz.cn]
# メールのアドレスのドメイン名の配列
valid_addresses.each do |valid_address|
# いくつものアドレスを代入していく。
@user.email = valid_address
assert @user.valid?, "#{valid_address.inspect} should be valid"
# ドメイン名は有効か?
# "#{valid_address.inspect} should be valid" エラ〜メッセージ
end
end
test "email validation should reject invalid addresses" do
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
assert_not @user.valid?, "#{invalid_address.inspect} should be invalid"
end
end
test "email addresses should be unique" do
# 一意性の検証
duplicate_user = @user.dup
# dup オブジェクトのコピーを作成するメソッド
# 同じものを作って比較する
duplicate_user.email = @user.email.upcase
# 大文字のアドレスに上書き
@user.save
assert_not duplicate_user.valid?
# 無効か?
end
end
これだけでは正常にデータベース上に保存できない可能性があるので、
データベース上でも一意性を持たせるようにする
ubuntu:~/environment/my_app (modeling-users) $ rails generate migration add_index_to_users_email
Running via Spring preloader in process 9987
invoke active_record
create db/migrate/20211115141312_add_index_to_users_email.rb
# このファイルでデータベース上の一意性を担保させる
###メールアドレスの一意性を強制するためのマイグレーション
db/migrate/[timestamp]_add_index_to_users_email.rb
class AddIndexToUsersEmail < ActiveRecord::Migration[6.0]
def change
# データベースの一意性を保つ
add_index :users, :email, unique: true
# add_index 指定したテーブルにインデックスを追加
# usersデータモデルのemailカラムを追加 一意性もつける
# 一度データベースに保存されたら同じのは保存できない
end
end
$ rails db:migrate
ubuntu:~/environment/my_app (modeling-users) $ rails generate migration add_password_digest_to_users password_digest:string
Running via Spring preloader in process 11571
invoke active_record
create db/migrate/20211115142724_add_password_digest_to_users.rb
###password_digestカラムを追加するマイグレーション
db/migrate/[timestamp]_add_password_digest_to_users.rb
class AddPasswordDigestToUsers < ActiveRecord::Migration[6.0]
def change
add_column :users, :password_digest, :string
# usersテーブルのpassword_digesetカラムを追加 属性は文字列
end
end
$rails db:migrate
###gemfile
gem 'rails' ....
gem 'bcrypt', '3.1.13'
class User < ApplicationRecord
# 継承させる
before_save { self.email = email.downcase }
# 保存する前に メアドは小文字にする
validates :name, presence: true, length: { maximum: 50 }
# nameカラムが存在する
# validates(:name, presence: true)
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: { case_sensitive: false }
# :case_sensitive 大文字と小文字を区別しないで一意性を検証する
has_secure_password
# 仮想的なpassword属性とpassword_confirmation属性に対してバリデーションをする機能も(強制的に)追加
end
selfは省略形
セキュアなパスワーを実装するために
has_secure_password
と書くらしい。
class AddIndexToUsersEmail < ActiveRecord::Migration[6.0]
def change
# データベースの一意性を保つ
add_index :users, :email, unique: true
# add_index 指定したテーブルにインデックスを追加
# usersデータモデルのemailカラムを追加 一意性もつける
# 一度データベースに保存されたら同じのは保存できない
end
end
データベースのカラムの追加をしたら
rails db:migrate
を行うらしい。
password_digestも追加する
class AddPasswordDigestToUsers < ActiveRecord::Migration[6.0]
def change
add_column :users, :password_digest, :string
# usersテーブルのpassword_digesetカラムを追加 属性は文字列
end
end
###パスワードの最小文字数を設定
その前にテストを作成し、どう動いてほしいかをかく。
.
.
.
test "password should be present (nonblank)" do
@user.password = @user.password_confirmation = " " * 6
# パスワードに空白を入力
assert_not @user.valid?
# 有効にしない
end
test "password should have a minimum length" do
@user.password = @user.password_confirmation = "a" * 5
# 五文字の文字列を入力
assert_not @user.valid?
# 有効にしない
end
end
空白と五文字以下の場合はパスワードととして認定しないようにしたい。
なので
.
.
.
has_secure_password
# 仮想的なpassword属性とpassword_confirmation属性に対してバリデーションをする機能も(強制的に)追加
validates :password, presence: true, length: { minimum: 6 }
# 最低でも六文字異常 存在性のある文字列をパスワードととする。
# 渡された属性が存在していることを検証する
end
これでパスワードの様式を設定できた。