2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

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

Last updated at Posted at 2017-05-02

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

検証してみる

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

user.rb
validates :name, presence: true

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

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')

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

» 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 {}

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

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

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

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!に、てみる。

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')

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

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でデータを作成する際にバリデーションでチェックさせる方法はないのか?

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

2
2
2

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?