seed-fu を導入してみた
seed-fu はデフォルトの seeds.rb よりも seed を扱いやすいということを聞いて、試しに自分のアプリケーションに入れてみることにしました。
seeds.rb を使っている場合、同じ操作をしようとすると、データを一度削除してから再度追加する必要があリます。一方で seed-fu なら、seed データの変更をしてもrails db:seed_fu
だけで変更が反映されるという点が便利です。
導入は
gem 'seed-fu'
として、bundle install
するだけです。
よくある作り方
user の seed を作る時を考えてみます。user は email がユニークなモデルです。
まずは公式の README を読んで次のように書いてみました。
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 が作成されます。
また、
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 を削除してから、
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
を実行するとエラーになってしまいます。
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 があるので、これを利用します。
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 を導入することが出来ました。