Seed Fu の rake タスクではなく、API を使用する際のアレコレです。
Seed Fu の インストールや基本的な使用方法
公式ドキュメントを参照。
Tip1: rake db:seed
された場合にも Seed Fu を実行させる。
db/seeds.rb
に Seed Fu を使うように書いておくと、 間違って rake db:seed
された場合にも Seed Fu が実行されるため便利だと思います。
その場合、以下の2点に気をつける必要があります。
1. fixture_path を設定
README には Fixtureファイルを探すパスのデフォルトは db/fixtures
と db/fixtures/#{Rails.env}
と記載されていますが、
これはrakeタスクを実行した場合のデフォルトです。
SeedFu.seed
APIを使用する場合のデフォルトは db/fixtures
です。
そのため、Rails.envに応じたFixtureファイルを使い分けたい場合には fixture_path の設定が必要です。
2. FILTER を変換
環境変数を用いて FILTER=users,articles
のように適用するファイルを指定できますが、この環境変数の値をそのままAPIに渡しても期待通りに動きません。
正規表現に変換する必要があります。
以上の2点を踏まえた具体的な記述例は以下の通りです。
paths = [Rails.root.join("db/fixtures"), Rails.root.join("db/fixtures/#{Rails.env}")]
filters = ENV["FILTER"].presence && /#{ENV["FILTER"].gsub(/,/, "|")}/
SeedFu.seed(paths, filters)
参考: https://github.com/mbleigh/seed-fu/blob/v2.3.9/lib/tasks/seed_fu.rake#L27
Tip2: FILTER の指定はファイル名の一部でOK
環境変数 FILTER
で指定した文字列は正規表現に変換されて、ファイル名とマッチするか判定されます。
そのため、ファイル名の一部だけを指定しても部分一致するファイルが実行されます。
ファイル名の順番で実行されるため、ファイル名の先頭に連番をつけているケースが少なくないと思いますが、そのようなケースでは例えば FILTER=01,02
のような指定ができます。
前述の通り、正規表現として使用されるので、頑張れば除外するファイル名を指定することもできます。FILTER='^(?!users)'
で「 users
で始まるファイル以外」ということになります。
Tip3: Fixture ファイルの中で FactoryBot を使用する。
Seed Fu でも FactoryBot を使用できます。
しかし require や include が必要な場合には少し気をつける必要があります。
Fixtureファイルは API を呼び出した場所と同じコンテキストで実行されるため、require や include もそこで行う必要があります。
require "factory_bot_rails"
include FactoryBot::Syntax::Methods
SeedFu.seed
これで Fixtureファイル内でもFactoryBotのメソッドを使用できます。(include しなくても FactoryBot.attributes_for
のような形式であれば使用できます)
User.seed(
:id,
attributes_for(:user, id: 1, name: "Alice"),
attributes_for(:user, id: 2, name: "Bob")
)
Tip4: 共通で使用するメソッドを作る
前述の FactoryBot と同様ですが、API を呼び出した場所にメソッドを定義したり、別ファイルに書いてそれを require すると、各Fixtureファイルで使用することができます。
def triple(num)
num * 3
end
require_relative "./utils"
def double(num)
num * 2
end
SeedFu.seed
User.seed(
:id,
{ :user, id: 1, num1: double(2), num2: triple(3) }
)
Tip5: シードデータのプリントを抑制する。
rake db:seed_fu
を実行すると、標準では以下のような内容が出力されます。
== Seed from /path/to/app/db/fixtures/users.rb
- User {:id=>1, :name=>"Alice"}
- User {:id=>2, :name=>"Bob"}
データのプリントを抑制したい場合、 SeedFu.quiet = true
をセットするとファイル名まで出力されなくなります。
そこで各Fixtureファイルでファイル名を出力するようにします。
ちなみに、Fixtureファイルは文字列として読み込まれ、evalされます。そのため puts "== #{__FILE__}"
のように __FILE__
を使用できません。
代わりに filename
を使用することができ、 puts "== Seed from #{filename}"
と書けば各ファイルの正しいファイル名が出力できます。
ただし filename
は公式のものではなく、evalされた場所でたまたま見えているローカル変数(メソッド引数)です。そのため将来のアップデート等で参照できなくなる可能性があります。