if it does't challenge you, it can't change you

RubyのWebエンジニアやってます。主にRuby on Railsのことで勉強になったこと書いていきます。

railsコマンドでファイル名を指定してseedデータを入れる方法

バージョン

テストデータやマスタデータの挿入

Railsにはデフォルトでdb/seeds.rbというファイルが生成されていて、
ここにインサート文などを書いておくと、
rails db:seedでデータをDBに挿入してくれます。

指定したseedファイルだけを挿入

ただ、特定のデータだけ挿入したいというときには、
毎回、seeds.rbを書き換えないといけません。
1回だけならまだいいですが、間隔をおいて何回も挿入しなければいけないときは、だいぶめんどくさいです。
そんなときのために、このような

rails db:seed_from_file SEED_FILENAME='seeds/ファイル名'

railsコマンドの引数でファイル名を渡して、seedデータを挿入する方法を書いていきます。
なお、ディレクトリの構成はこんな感じです。

root/
  lib/
    tasks/
      db.rake
  db/
    seeds/
      01_sample_seeds.rb
      02_sample_seeds.rb
      03_sample_seeds.rb

挿入したいテストデータをdb/seeds配下のファイルに記載している想定です。

タスクファイルを作成する

rails g task ファイル名でタスクファイルを作成することができます。
今回は、rails g task dbとコマンドを叩き、lib/tasks/db.rakeを作成しました。

どのseedファイルを実行するか記載

タスクファイルが作成できたら、中身を書いていきます。
今回叩きたいコマンドrails db:seed_from_file SEED_FILENAME='seeds/03_sample_seeds.rb'に合わせて書いていきます。
今回はこのような感じで書いてみました。

namespace :db do
  desc 'Load the seed data from SEED_FILENAME'
  task :seed_from_file => 'db:abort_if_pending_migrations' do
    seed_file = File.join(Rails.root, 'db', ENV['SEED_FILENAME'])
    if File.exist?(seed_file)
      puts "seeding -- #{ENV['SEED_FILENAME']}"
      load(seed_file)
    else
      puts "the seed file does not exist."
    end
  end
end

以下から各メソッドの解説です。

・namespace

apiのルーティングなどでよく使われるnamespaceメソッドですが、
ここではコマンドを叩くときのコマンド名みたいなものです。
これをネストしていくとコマンドもネストされます。

namespace :apple do 
  namespace :banana do
    namespace :orange do 
      task :eat do
        #省略
      end
    end
  end
end

であればrails apple:banana:orange:eat という風なコマンドになります。

・desc

メソッドの説明文になります。
rails -Tでタスクを表示したときに一緒に説明文が表示されます。

・task

実行するメソッド名です。
成功していないマイグレーションがあるとデータを入れるのはよくないので、先に'db:abort_if_pending_migrations'を実行するようにしています。

・File.join

seedファイルまでのパスを生成するメソッドです。
コマンドの引数であるSEED_FILENAMEからファイル名を受け取り、実行するファイルを特定します。
Rails.root, 'db'と記載しておくことで、コマンドからの引数であるファイルまでのパスを省略できます。
load(seed_file)で実行しています。

まとめ

僕のカップル専用家計簿アプリでは、
月毎に合計値や前月などを計算しています。
そのため、月が変わると計算する値がなく、
真っ白になってしまうページがあり、
実装するときに不便になるので、
今回のようなテストデータを入れられるタスクを作りました。
(まだ毎月挿入するシードデータを作ってないですがw)
いろんなメソッドを使いますが、どれも単純なものなので、
試してみてください。
改善点あれば是非ご指摘ください。