1
0

More than 1 year has passed since last update.

アプリを作る ユーザーのモデルを作成する

Last updated at Posted at 2022-01-22

###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/models/user_test.rb
.
.
.
  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

空白と五文字以下の場合はパスワードととして認定しないようにしたい。
なので

app/models/user.rb
.
.
.
  has_secure_password
  # 仮想的なpassword属性とpassword_confirmation属性に対してバリデーションをする機能も(強制的に)追加
  validates :password, presence: true, length: { minimum: 6 }
  # 最低でも六文字異常 存在性のある文字列をパスワードととする。
  # 渡された属性が存在していることを検証する
end

これでパスワードの様式を設定できた。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0