LoginSignup
10

More than 3 years have passed since last update.

【Rails】seed-fu で user の seed を作りたい

Posted at

seed-fu を導入してみた

seed-fu はデフォルトの seeds.rb よりも seed を扱いやすいということを聞いて、試しに自分のアプリケーションに入れてみることにしました。
seeds.rb を使っている場合、同じ操作をしようとすると、データを一度削除してから再度追加する必要があリます。一方で seed-fu なら、seed データの変更をしてもrails db:seed_fuだけで変更が反映されるという点が便利です。

導入は

Gemfile
gem 'seed-fu'

として、bundle installするだけです。

よくある作り方

user の seed を作る時を考えてみます。user は email がユニークなモデルです。
まずは公式の README を読んで次のように書いてみました。

db/fixtures/01_user.rb
User.seed do |s|
  s.id    = 1
  s.name = "foo"
  s.email = "foo@example.com"
  s.password  = "password"
end

User.seed do |s|
  s.id    = 2
  s.name = "bar"
  s.email = "bar@example.com"
  s.password  = "password"
end

これでrails db:seed_fuを実行すれば問題なく seed が作成されます。
また、

db/fixtures/01_user.rb
User.seed do |s|
  s.id    = 1
- s.name = "foo"
+ s.name = "hoo"
  s.email = "foo@example.com"
  s.password  = "password"
end

このように一部を変更してもrails db:seed_fuで問題なく変更が適応されます。

問題点

一方でこの方法では一つ問題点があります。それは、seed が増えたときに、id を手で変えなくてはならないことです。seed が少ないうちは全く問題ありませんが、増えてくると打ち直す数も比例して増えてきます。

整数固定値 の id を使わない方法

実は、id は記述しなくても seed は生成できます。
先程の状態から一旦rails db:reset等で seed を削除してから、

db/fixtures/01_user.rb
User.seed do |s|
  s.name = "foo"
  s.email = "foo@example.com"
  s.password  = "password"
end

User.seed do |s|
  s.name = "bar"
  s.email = "bar@example.com"
  s.password  = "password"
end

上記の様に変更しrails db:seed_fuを実行すると、問題なく seed が生成されます。
しかし、このままでは、値を変更し、再度rails db:seed_fuを実行するとエラーになってしまいます。

db/fixtures/01_user.rb
User.seed do |s|
  s.id    = 1
- s.name = "foo"
+ s.name = "hoo"
  s.email = "foo@example.com"
  s.password  = "password"
end
$ rails db:seed_fu

== Seed from /Users/punkshiraihsi/environment/e-navigator/db/fixtures/01_user.rb
 - User {:name=>"hoo", :email=>"foo@example.com", :password=>"password", }
rails aborted!
ActiveRecord::RecordNotUnique: PG::UniqueViolation: ERROR:  duplicate key value violates unique constraint "index_users_on_email"
DETAIL:  Key (email)=(foo@example.com) already exists.

これは、seed-fu が「どの seed が変更されたか」を判断するための情報を失ってしまっているためです。デフォルトでは id で判断していますが、今回はそれを省略してしまったため、生成はできるものの変更は出来ないのです。

幸いにも id 以外でユニークなカラム email があるので、これを利用します。

db/fixtures/01_user.rb
User.seed(:email) do |s|
  s.name = "foo"
  s.email = "foo@example.com"
  s.password  = "password"
end

User.seed(:email) do |s|
  s.name = "bar"
  s.email = "bar@example.com"
  s.password  = "password"
end

seed メソッドに引数 :email を付けるだけです。これで seed-fu はどの seed が変更されたかを判断できるようになるので、rails db:seed_fuだけで変更を適応できるようになります。

以上で**整数固定値の id を入力せず、seed-fu を導入することが出来ました。

参考

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
10