Rails5+Capistrano3+seed-fuで、最新のマスターデータをデプロイのたびに自動で突っ込む。

いやぁ、とても久しぶりになってしまいました。
そして前回まではあんなにザックリした内容だったのに、今回は急に細かい話です。

seed-fuというそれはそれは便利なgemがありまして

マスターデータをDBに詰めたい欲求がありまして。それも自動じゃなきゃやーよとごねてもおりまして。でもrailsのデフォルトのseedはいろいろ扱いにくいので、どうしようかいろいろ調べました。seedをいろいろ上手いことやりくりしている人もいれば、rakeタスクを作ってるぜという人もいるみたいです。
しかしseed-fuは!capistranoと連携できる!つまりデプロイ時に自動で実行できる!それも簡単に!いいではないか!
ということでseed-fu、はじめました。

タスク作るのは簡単なので、capistranoとの連携の取り方に進みますよね

タスク作りはさっきののREADMEの通りにやれば問題ないはずです。
さあ、capistranoです。
まずはseed-fuに組み込まれているcapistrano用のタスクファイルを読み込むために、Capfileにこうです。

require 'seed-fu/capistrano3'

それから、ちゃんとタスクを処理してもらうために、deploy.rbのnamespace :deploy do のところにこうです。

before 'deploy:publishing', 'db:seed_fu'

namespace :deployの中に書けばこうでもいいみたい。

before :publishing, 'db:seed_fu'


はい、以上、これだけ。
かと思いきやそういうわけにはいきませんでした。

呼ばれている形跡はあるのに、実行された気配がない。

capistranoのログを見る限り「invoke db:seed-fu」とかいって確かに呼ばれているみたい。でもDBにデータは入っていない、その心は?
としばらく悩んでdeploy.rbの書き方をいじくったりしたけれど改善せず。
この辺に時間を取られたのは僕が坊やだから(capistranoをいまいち理解できていないから)です。
でもログをよくよく見ると、他のdb:migrateとかと違って実際に実行しているログがないみたい。

「へ?」となった時はソースを読もう、と思えるようになってきたことは少しはプログラマらしくなってきたのかなと思える点です

ソース読みました。

https://github.com/mbleigh/seed-fu/blob/master/lib/tasks/seed_fu_capistrano3.rake

namespace :db do
  desc 'Load seed data into database'
  task :seed_fu do
    on roles(:db) do
      within release_path do
        with rails_env: fetch(:rails_env) do
          execute :bundle, :exec, :rake, 'db:seed_fu'
        end
      end
    end
  end
end

ん?roles(:db)?
そんな役職の子は雇った記憶がありませんねぇ。

そこでした。

DBはRDSを使っていたので、そんなroleを持ったEC2がいなかったから実行されなかったのですね。
なるほど。
じゃあ、オーバーライド、というか自分で書き直さなきゃいけませんね。

仕方がないから、自作するタスク

(↑少し、ライムを効かせてみました)

lib/capistrano/tasks/seed_fu.rake
namespace :db do
  desc 'Load seed data into database'
  task :seed_fu do
    on roles(:app) do
      within release_path do
        with rails_env: fetch(:rails_env) do
          execute :bundle, :exec, :rails, 'db:seed_fu'
        end
      end
    end
  end
end

roleがappのEC2に流したいので、「:db」を「:app」に変えました。
結果、流れました。やった。
あとついでに、rails5を使っているのが嬉しくってつい、実行コマンドの「:rake」も「:rails」に変えさせていただきました。

結局、自分でタスク作ったので、最初のCapfileへの記述はいらなくなりましたね。

それから、上のやつでも問題ないんだろうけど、汎用性を持たせるためにこんな感じにして、

namespace :db do
  desc 'Load seed data into database'
  task :seed_fu do
    on roles(fetch(:seed_fu_roles) || :app) do
      within release_path do
        with rails_env: fetch(:rails_env) do
          execute :bundle, :exec, :rails, 'db:seed_fu'
        end
      end
    end
  end
end

基本:appで変えたきゃご自由にどうぞ状態にしておくのがいいんじゃないかなと思った。
今日びEC2でDBサーバー作る人なんてそうはいないだろうし。(でもAWS以外では違うのかな。。)

本家もこうしてくれたらいいのにと思うけど、これってプルリクエスト送るほどのことなのでしょうか。各々の環境の差分が大きすぎてあまり意味がないのですかね。

感想

capistranoはやっぱり難しくて、何が起こっているのかをまだあまり把握できていないので、今回も結構手間取りました。が、そのお陰で仕組みが少し見えた気がするので、これでよかったのだと思い込んでいます。

あとはAWSしか使ったことがないので、サーバーのroleって普通のサーバーではどうなっているのだろう、という感じです。

ご清聴ありがとうございました。