Rails チュートリアル　第6章　まとめ

#全体像の把握
Modelを作成。Application recordを継承したクラスでは、情報を永続的に保存できる。
User.create User.find_by User.saveなどの操作。
ValidationをTDDで実装


フォームで実現したいこと
永続的なデータを保存したい、一時的な変数ではなく
そのためにはDBを使う必要がある
DBを扱うには別の言語を学ぶ必要があるが、RailsのActiveRecordを使えば、変数のように保存できる

ユーザー用のデータモデルを作成（以下2つのファイルが自動生成）

```rb:
rails g model User name:string email:string 
```

DBの変更を反映

```
rails db:migrate
```
をすると、db/にdevelopment.sqlite3というバイナリファイルが作成される
ここにDBが保存される


migrationファイルの中身を確認(自動生成1）

```ruby:db/migrate/2019-----_create_users.rb 
class CreateUsers < ActiveRecord::Migration[5.1] #クラスの継承
  def change #changeメソッドの定義
    create_table :users do |t| #create_tableというブロック付きメソッドの定義
      t.string :name #t.stringのnameというシンボル
      t.string :email

      t.timestamps
    end
  end
end
```

モデル(自動生成2)

```
app/model/user.rb
```
usersのtableが見つからないというエラーが出た時は、もう一度rails db:migrate

app/model/user.rbで、ApplicationRecordを継承していることで、Userクラスに何ができるようになったのかがポイント
・Rail console上で、User.newを使いnameとemailを作成する。普通なら、consoleを閉じると、データは消えるはずだが、u（変数名）.saveとするとDBに保存されるため、次にconsoleを立ち上げても、Userのデータが残っている
・継承していることで、DBに保存したり(save)、DBから情報を取得したり(all)、情報を検索したり(find_by)、情報を更新する(update_attributes)ことができる
・普通更新する時はu[:name] = "---"だが、u.name = "^^^"のように代入することもできる
・User.createは作成と保存を同時に行える。戻り値を生成しているので、変数に入れることもできる
foo =  User.create(---)
・Validationができるようになる

-------
Validation

テスト(test/models/user_test.rb)と修正(app/models/user.rb)を繰り返すTDD


```ruby:app/test/models/user_test.rb
# setupはtest do-endの直前で呼ばれる
 def setup
    @user = User.new(
      name: "Example User",
      email: "user@example.com")
  end
# サンプルデータの形式が適切であるかのチェック
# valid?はvalidationが全て通るべきという意味
  test "should be valid" do
    assert @user.valid?
  end
#　nameが空文字のユーザーはvalidationではじけているべき(assert_not)であるというチェック
  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
# nameが51字以上の場合にはvaliではじけているべき
  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
  #成功しているemailのフォーマットは全て通るべき
   test "email validation should accept valid addresses" do
  #成功しているemailのフォーマットを配列で作成
    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 #変数に代入
#validationを通っているかチェック、さらに失敗したならどのemailで失敗したのか表示
      assert @user.valid?, "#{valid_address.inspect} should be valid"
    end
#失敗しているemailのformatは全てはじけているべきである
    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
  #一意性の確認
  test "email addresses should be unique" do
  #@user.dupで@userを複製する
    duplicate_user = @user.dup
    @user.save #@userを保存
  #@userが保存されているので、同じデータのduplicate_userは保存されずにはじかれるべき
    assert_not duplicate_user.valid?
  end
```

一意性の検証
railsだけではなくDBでも検証する仕組みを作る（ほぼ同時のユーザー登録に対処）
すでにあるモデルにカラムを追加したい
rails g migrationの形式は、ここが初めて

`rails generate migration add_index_to_users_email `
DBにemailカラムが一意であることを確認させる

```rb:db/migrate/[timestamp]_add_index_to_users_email.rb
def change
    add_index :users, :email, unique: true
  # add_index :テーブル名, :カラム名, 一意性の確保
end
```
indexであることに注意

Password 
passwordはハッシュ関数をかけて、ハッシュ値に変換してからDBに保存
DBにハッシュ値を保存するための場所を準備

```rb:
rails generate migration add_password_digest_to_users password_digest:string
# usersテーブルにpassword_digestカラムを追加したい
# この形式で書くと自動生成してくれる 
# 先のadd_indexと違い add_columnだから、追加したいカラムとデータ型password_digest:string
rails db:migrate
```

ハッシュ関数の用意

1.gem 'bcrypt',         '3.1.12' #gemインストール
2.has_secure_password を追加

has_secure_passwordはpasswordとpassword_confirmationを最初から用意してくれている
password,confのカラムはないが、アクセスすることはできる(u.password)
代入できるが、セーブはしない、ハッシュ値をかけたダイジェストだけが保存されている

Passwordのテスト

```ruby:test/models/user_test.rb
# 空文字で６字にしたらはじかれているべき
# valiではpresenceで対処
  test "password should be present (nonblank)" do
    @user.password = @user.password_confirmation = " " * 6
    assert_not @user.valid?
  end
# 文字数が5のpasswordははじかれているべき
  test "password should have a minimum length" do
    @user.password = @user.password_confirmation = "a" * 5
    assert_not @user.valid?
  end
```

認証の方法
u.authenticate("---")を使うと、引数の値と本当のパスワードが正しいかチェックし、一致したらユーザーオブジェクトを返し、一致しなかったらfalseを返してくれる

未確認

herokuにデプロイした後、dbを使ったので、heroku run