seed-fuでバリデーションがスキップされる

seed-fuを使って初期データを作成していたのですが、ドハマリをしたのでメモっておきます。現象としては、特にエラーも出ずおかしなデータが作られているといったものです。

## 検証してみる

モデルのバリデーションはこんな感じでかけています。

```rb:user.rb
validates :name, presence: true
```

試しに、初期データ作成を以下のようにコメントアウトします。
作成時にバリデーションに引っかかることを期待して、nameもコメントアウト。

```rb:db/fixtures/users.rb
User.seed do |obj|
  #obj.name = "ユーザー1"
  #obj.email = "test+100@gmail.com"
  #obj.password = 'password'
  #obj.password_confirmation = 'password'
end
u = User.first
u.update(name: 'test')
```

初期データ投入を実行します。
何事もなく実行されました。

```shell-session:
» bundle exec rake db:seed_fu FILTER=users

== Filtering seed files against regexp: /users/

== Seed from /Users/hoge/projects/hoge/db/fixtures/users.rb
 - User {}
```

え！？っと思い、ログを確認するも、特にエラーは出ていません。

```shell-session:log/development.log
[2017-05-02 15:12:03] (pida=4863) DEBUG -- : [db:seed_fu ] started
[2017-05-02 15:12:03] (pida=4863) DEBUG -- :    (0.4ms)  begin transaction
[2017-05-02 15:12:03] (pida=4863) DEBUG -- :   User Load (0.2ms)  SELECT  "users".* FROM "users" WHERE "users"."deleted_at" IS NULL AND "users"."id" IS NULL LIMIT ?  [["LIMIT", 1]]
[2017-05-02 15:12:03] (pida=4863) DEBUG -- :   SQL (3.1ms)  INSERT INTO "users" ("confirmation_token", "confirmation_sent_at", "created_at", "updated_at") VALUES (?, ?, ?, ?)  [["confirmation_token", "XoT-7mK4K8RCsvzJcH4_"], ["confirmation_sent_at", 2017-05-02 06:12:03 UTC], ["created_at", 2017-05-02 06:12:03 UTC], ["updated_at", 2017-05-02 06:12:03 UTC]]
[2017-05-02 15:12:03] (pida=4863) DEBUG -- :    (1.7ms)  commit transaction
[2017-05-02 15:12:03] (pida=4863) DEBUG -- : [db:seed_fu ] finished
````

データもちゃんと入っている。。。ちゃんとと言うか、本当は入ってほしくないんです。え！？バリデーションどこいっちゃたの？

```sqlite3
1||||||0|||||KTsFoLHadSQf3wvGAJsZ||2017-05-02 06:27:21.799427||2017-05-02 06:27:21.799210|2017-05-02 06:27:21.799210||||0|
````
しかし、レコードは作成されているものの、その後で実行されているupdateによるnameは空のまま。updateはこけている模様。しかし何もエラーなし。

update時に、例外を吐くようにupdate!に、てみる。

```rb:db/fixtures/user.rb
User.seed do |obj|
  #obj.name = "ユーザー1"
  #obj.email = "test+100@gmail.com"
  #obj.password = 'password'
  #obj.password_confirmation = 'password'
end
u = User.first
u.update!(name: 'test')
```

同じく、実行すると標準出力にエラーがでました。
ログをみても、ロールバックされていることがわかる。
ロールバックが働いているため、レコード自身も作成されていませんでした。

```shell-session:log/development.log

[2017-05-02 15:18:28] (pida=5180) DEBUG -- : [db:seed_fu ] started
[2017-05-02 15:18:28] (pida=5180) DEBUG -- :    (0.4ms)  begin transaction
[2017-05-02 15:18:28] (pida=5180) DEBUG -- :   User Load (0.2ms)  SELECT  "users".* FROM "users" WHERE "users"."deleted_at" IS NULL AND "users"."id" IS NULL LIMIT ?  [["LIMIT", 1]]
[2017-05-02 15:18:28] (pida=5180) DEBUG -- :   SQL (0.4ms)  INSERT INTO "users" ("confirmation_token", "confirmation_sent_at", "created_at", "updated_at") VALUES (?, ?, ?, ?)  [["confirmation_token", "CnY6D24dv7zj_sRzo8Zf"], ["confirmation_sent_at", 2017-05-02 06:18:28 UTC], ["created_at", 2017-05-02 06:18:28 UTC], ["updated_at", 2017-05-02 06:18:28 UTC]]
[2017-05-02 15:18:28] (pida=5180) DEBUG -- :   User Load (0.2ms)  SELECT  "users".* FROM "users" WHERE "users"."deleted_at" IS NULL ORDER BY "users"."id" ASC LIMIT ?  [["LIMIT", 1]]
[2017-05-02 15:18:28] (pida=5180) DEBUG -- :    (1.3ms)  rollback transaction
```

実際にアップデートされていると思い込んでいたデータが一向に更新されず、プログラムのバグかと思い、永遠にはまりました。

## まとめると、
1. Model.seedでデータを作る際には、モデルで設定しているバリデーションに関係なくレコードが作成される。
2. ActiveRecordで取得したデータ(インスタンス)に対して、updateなどをかけるとモデルに設定しているバリデーションが働く。当然と言っちゃ当然か。

## 注意すること
1. モデルでバリデーションを設定していても、Seedだと直接ガンガンレコードがインサートされてしまう。
2. なんとなく使うのやめよう。。。ツールにはツールのポリシーがあって使う側も勉強しないとアカン、、、

## 課題
1. seed-fuでデータを作成する際にバリデーションでチェックさせる方法はないのか？

結構、違和感の残る検証結果になってしまいました。もしそもそも使い方が間違ってるぞ！などのご指摘があれば、ご教授いただけると幸いです。