railsチュートリアル第6章 存在性を検証する

###存在性を検証する
最も基本的なバリデーションは「存在性（Presence）」です。
これは単に、渡された属性が存在することを検証します。
例えばこの節では、ユーザーがデータベースに保存される前にnameとemailフィールドの両方が存在することを保証します。
ここではこの要求を新しいユーザーを作るための```ユーザー登録フォームにまで徹底させる方法を確認```します。
まずはname属性の存在性に関する```テストを追加```します。
具体的にはリスト 6.7のように、まず```@user変数のname属性に対して空白の文字列をセット```します。
そして、assert_notメソッドを使って ```Userオブジェクトが有効でなくなったこと```を確認します。
####name属性にバリデーションに対するテスト

```rb
require 'test_helper'

class UserTest < ActiveSupport::TestCase
  def setup
    @user = User.new(name: "Example User", email: "user@example.com")
  end

  test "should be valid" do
    assert @user.valid?
    # Userオブジェクトの有効性を調べる。
  end
  
  test "name should be present" do
    @user.name = "     "
    assert_not @user.valid?
    
  end  
end
```

```
ubuntu:~/environment/sample_app (modeling-users) $ rails test:models
Started with run options --seed 24064

 FAIL["test_name_should_be_present", #<Minitest::Reporters::Suite:0x000055b2fa9fc588 @name="UserTest">, 0.036220663999984026]
 test_name_should_be_present#UserTest (0.04s)
        Expected true to be nil or false
        test/models/user_test.rb:14:in `block in <class:UserTest>'

  2/2: [==============================] 100% Time: 00:00:00, Time: 00:00:00

Finished in 0.04021s
2 tests, 2 assertions, 1 failures, 0 errors, 0 skips
```

```name属性の存在を検査する方法```は、リスト 6.9に示したとおり、
validates メソッドに```presence: true```という引数を与えて使うことです。
presence: trueという引数は、要素が１つの```オプションハッシュ```です。
メソッドの最後の引数としてハッシュを渡す場合、波カッコを付けなくても問題ありません。

####name属性の存在性を検証する 

```rb
class User < ApplicationRecord
  validates :name, presence: true
end
```
```validates```は単なるメソッドです。カッコを使ってリスト 6.9を同等のコードに書き換えたものを次に示します。

```rb
class User < ApplicationRecord
  validates(:name, presence: true)
end
```
カッコが省略できる。

```rb
>> user = User.new(name: "", email: "michael@example.com")
   (0.1ms)  begin transaction
=> #<User id: nil, name: "", email: "michael@example.com", created_at: nil, updated_at: nil>
>> user.valid?
=> false
```
user変数が```有効```かどうかをvalid?メソッドでチェックすることができます。
もしオブジェクトが１つ以上の検証に失敗したときは、falseを返します。
また、すべてのバリデーションに通ったときにtrueを返します。
今回の場合、検証が1つしかないので、どの検証が失敗したかわかります。
しかし、失敗したときに作られる```errorsオブジェクトを使って確認```すれば、便利。

```
>> user.errors.full_messages
=> ["Name can't be blank"]
```

```
>> user.save
=> false
```

```rb
ubuntu:~/environment/sample_app (modeling-users) $ rails test:models
Started with run options --seed 32299

  2/2: [==============================] 100% Time: 00:00:00, Time: 00:00:00

Finished in 0.04125s
2 tests, 2 assertions, 0 failures, 0 errors, 0 skips
```

email属性の存在性についてもテストを書いてみましょう。
最初は失敗しますが、コードを追加することで成功する
####email属性の検証に対するテスト

```rb
require 'test_helper'

class UserTest < ActiveSupport::TestCase
  def setup
    @user = User.new(name: "Example User", email: "user@example.com")
  end

  test "should be valid" do
    assert @user.valid?
  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
end
```

####email属性の存在性を検証する

```rb
class User < ApplicationRecord
  validates :name, presence: true
  validates :email, presence: true
end
```

```
ubuntu:~/environment/sample_app (modeling-users) $ rails t
Running via Spring preloader in process 6088
Started with run options --seed 7475

  11/11: [============================] 100% Time: 00:00:01, Time: 00:00:01

Finished in 1.93017s
11 tests, 22 assertions, 0 failures, 0 errors, 0 skips
```

###演習
1.新しいユーザーuを作成し、作成した時点では有効ではない（invalid）ことを確認してください。
なぜ有効ではないのでしょうか? エラーメッセージを確認してみましょう。

2.u.errors.messagesを実行すると、ハッシュ形式でエラーが取得できることを確認してください。
emailに関するエラー情報だけを取得したい場合、どうやって取得すれば良いでしょうか?

```rb
>> u = User.new(name: "", email: "")
   (0.1ms)  begin transaction
=> #<User id: nil, name: "", email: "", created_at: nil, updated_at: nil>
>> u.errors.full_messages
=> []
#どう言う意味？ 両方空という意味なのかな。
>> u.email = "abc@def.com"
=> "abc@def.com"
>> u.save
=> false
>> u.save
=> false
>> u
=> #<User id: nil, name: "", email: "abc@def.com", created_at: nil, updated_at: nil>
>> u.errors.full_messages
=> ["Name can't be blank"]
#名前が空
>> u.email = ""
=> ""
>> u
=> #<User id: nil, name: "", email: "", created_at: nil, updated_at: nil>
>> u.name = "abc"
=> "abc"
>> u
=> #<User id: nil, name: "abc", email: "", created_at: nil, updated_at: nil>
>> u.errors.full_messages
=> ["Name can't be blank"]
>> u.save
=> false
#保存されていないはずなのに
#↓はなんで結果が変わるの？
>> u.errors.full_messages
=> ["Email can't be blank"]
#emailが空
```