【第6章】Railsチュートリアル 5.1(第4版)　ユーザーのモデルを作成する

大まかな流れの自己整理が目的のため、不足・誤り等あれば追記していきますのでご容赦頂けますと幸いです。
なお、筆者は書籍版＋動画版で学んでいるため、本記事はチュートリアル「sample_app」寄りになります。
（講師：安川さんの「エラーは怖くない、エラーは味方！」のメッセージは個人的にかなり励みさせてもらってます😅）

# 環境
・ AWS
・ Ruby 2.6.3p62
・ Rails 5.1.6

# 6.0 入る前に
###Active Record
**『Ruby⇆SQLの翻訳機』**とされる。
Ruby　→　変数に一時的な保存はできるが、ユーザ情報など永続的な保存できない
SQL　→　DBに永続的に保存できるが、CRUD処理などで別言語として習得が必要
<font color="Red">Railsの***Active Record(AR)***を適用すると、DB関連をRubyのように書ける！</font>

ex.「DBからemailのデータを探したい」

```
>> user = User.find_by(email: "mhartl@example.com")
```
今後お世話になるのでメモしておきました。

< 参考 >
[【初心者向け】RailsのActive Recordの解説&メソッドまとめ](https://qiita.com/ryokky59/items/a1d0b4e86bacbd7ef6e8)

　
###gitのブランチを分ける
何か不具合が起こったら、ブランチごと消せばok!

```
$ git checkout -b 'modeling-users'
```

# 6.1 Userモデル
Userモデル

|カラム|型|
|:---:|:---:|
|id|integer|
|name|string|
|email|string|
|created_at|datetime|
|updated_at|datetime|

※ タイムスタンプ等はマジックカラム(Magic Column)と呼ばれ、デフォルトで設定のためモデル生成時は定義しない。

　

Userモデルを生成する。
マイグレーションファイルが生成される（マイグレーションの自体は、データベースに与える変更を定義したchangeメソッドの集まり）。

```
$ rails generate model User name:string email:string
```
　
`db/development.sqlite3` という名前のバイナリファイルが生成される。（これがSQLiteデータベースの実体）。

### バイナリファイルの確認
`db/development.sqlite3`はバイナリファイル(binary file)と呼ばれコンピュータ用(ex.^@^@^@...）だが、これをダウンロードして[DB Browser for SQLite](https://sqlitebrowser.org/)というアプリで中身の確認ができる。
<img width="853" alt="スクリーンショット 2019-12-04 3.00.15.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/434223/7cbe4261-cb38-0128-ec74-c9cb5df0fac9.png">


　　
生成されたマイグレーションファイルに対し、マイグレーションを実行（適用）

```
$ rails db:migrate
```
　

### サンドボックスモードでのconsoleの起動
コンソールを使いたいがDB反映させたくないなど試験的に動かしたい場合、
サンドボックスモードで起動するとコンソールの動きが1つのトランザクション（「ここからここまでワンセット」な処理単位）となり、行った変更はロールバック（DBのトランザクション処理において、変更等を取り消してモード開始前のものに戻すこと）ができる。

< 参考 >
[rails console まとめ - kzy52's blog](https://kzy52.com/entry/2014/11/28/235958)
[「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典](https://wa3.i-3-i.info/diff350db.html)


```
$ rails console --sandbox
Running via Spring preloader in process 5446
Loading development environment in sandbox (Rails 5.1.6)
Any modifications you make will be rolled back on exit
```
　　

ユーザオブジェクトの新規作成、確認、変更、保存、生成＋保存(同時)、削除は下記
普段、変数は保存されないが、メソッド使用っぽく代入ができる。

※ `.destroy`で削除されたオブジェクトはメモリ上にはまだ残っている

```
>> testuser = User.new(name: "Michael Hartl", email: "mhartl@example.com")
 
>> testuser.name

>> testuser.name = "railstest"

>> testuser.save

>> testuser.destroy
```




# 6.2 ユーザーを検証する

名前が存在するか？フォーマットは正しいか？
名前やメールアドレスを検証（validation）する。
nameは空でないか？（存在性）
emailは重複していないか？（一意性）
検証項目例：存在性、一意性、フォーマット、文字数長さ

　
モデル(test/models/user_test.rb)に関してのみテストするコマンド

```
$ rails test:models
```
　
###setup メソッド
有効なUserオブジェクト (@user) を作成する特殊なメソッド。メソッド内に書かれた処理は、各テストが走る直前に実行される。
(test/models/user_test.rb)


```
def setup
    @user = User.new(
      name: "Example User",
      email: "user@example.com")
end
```

### 正規表現（メールの正規表現分解の一例）

|正規表現|意味|
|:---:|:---:|
|/\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i|(完全な正規表現)|
|/|正規表現の開始を示す|
|\A|文字列の先頭|
|[\w+\-.]+|英数字、アンダースコア (_)、プラス (+)、ハイフン (-)、ドット (.) のいずれかを少なくとも1文字以上繰り返す|
|@|アットマーク|
|[a-z\d\-.]+|英小文字、数字、ハイフン、ドットのいずれかを少なくとも1文字以上繰り返す|
|\.|ドット|
|[a-z]+|英小文字を少なくとも1文字以上繰り返す|
|\z|文字列の末尾|
|/|正規表現の終わりを示す|
|i|大文字小文字を無視するオプション|

####Rubular
Rubyでの正規表現については[Rubular](https://rubular.com/)で試しながら学ぶことができる。
![スクリーンショット 2019-12-08 10.03.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/434223/e57acdb7-0226-202f-5d7b-4a3a1b5e6c99.png)



### 補足
Macでのバックスラッシュ ( \ ) の入力方法
「 option 」 ＋ 「 ¥ 」

マイグレーションにお願いする

```
$ rails generate migration add_index_to_users_email
```


# 6.3 セキュアなパスワードを追加する
大まかな前提として、パスワードはそのまま保存せずにいったん不可逆な変換をかけてから保存する

###１．Railsが用意したレール`has_secure_passoword`を使用
これが追加されると、
password
password_confirmationが一致してるかも検証される。

###2. 保存場所である***password_digest***を用意する

###3. ハッシュ関数(ex. BCrypt)を１個選ぶ

　
〜以下、主要部(個人的)のみ抽出〜

`app/models/user.rb`完成型
( has_secure_passoword の追加 )

```
class User < ApplicationRecord
   validates :name, presence: true, length: { maximum: 50 }
   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 }
                       has_secure_password
                       validates :password, presence: true, length: { minimum: 6 }
end
```
　
password_digestカラム用のマイグレーションを生成

```
$ rails generate migration add_password_digest_to_users password_digest:string
```
　
add_columnメソッドを使って生成したusersテーブルpassword_digestカラムを適用させる

```
$ rails db:migrate
```

　
bcryptを使うため、bcrypt gemをGemfileに追加する

```
gem 'bcrypt',         '3.1.12'
```

```
$ bundle install
```
　
app/models/user.rb　にhas_secure_password等を追加する

```
class User < ApplicationRecord
  before_save { self.email = email.downcase }
  validates :name, presence: true, length: { maximum: 50 }
  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 }
  has_secure_password
  validates :password, presence: true, length: { minimum: 6 }
end
```
　
　
test/models/user_test.rbのsetupメソッドにパスワード追加、テストに文字数を指定する


```
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

省略

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

```
　

テストして終了

```
$ rails t
```