はぐれメタルBOTをRuby on Railsに移植しました

はぐれメタルのBOTそのサイトRuby on Railsに移植しました。2〜3年前に最初のはぐれメタルができてからほとんど手を加えずに動かしてきたのですが、TwitterAPIがそろそろ使えなくなりそうなのと、当時の自分のコードなんてメンテナンスする気になれないので、1から作り直しています。
今回の移植で勉強になったことをつらつらと書き連ねます。

Haml

http://haml.info/
もともとのはぐれメタルのサイトはベタ書きの静的なhtmlで構成されていました。それをマルッとHamlに書き直しています。これと言って特別なことはしていません。HamlかわいいよHamlペロペロ。

rails runner

はぐれメタルBOTは定期的に動かすスクリプトなのでRailsには乗せられないかと思ってたんですが、そんなことはなかった。これを使えばRailsに乗ったRubyのコードを簡単に実行できます。

# lib/batches/battle/main.rb
module Batches
  module Battle
    class Main
      def self.start
        # はぐれメタルの処理
      end
    end
  end
end
$ rails runner Batches::Battle::Main.start
本番環境では
$ rails runner -e production Batches::Battle::Main.start

ファイルをどこに置くか迷ったのですが、lib/batches/battle/main.rbに置きました。

便利なGemたち

便利な世の中になったもので、何かしたいと思ったらたいてい誰かが便利なgemを作ってくれています。今回使ったgemの中で特に便利だと思ったものをいくつか挙げます。

tweetstream

https://github.com/intridea/tweetstream
twitterのストリーミングAPIに対応したgem。このgemのおかげではぐれメタルがリアルタイムに応答するようになりました。以下のように使用しています。

EM.run do
  stream = TweetStream::Client.new

  EM::Timer.new(180) do
    stream.stop # 180秒後にストップ
  end

  stream.userstream do |status|
    # はぐれメタルへの攻撃に対する処理
  end
end
settingslogic

https://github.com/binarylogic/settingslogic
YAMLで定数を管理することができるgem。develop環境とproduction環境で値を変えるなんてこともできます。
こんな感じでtwitterの接続情報をYAMLに書いてます。

# config/twitter.yml
development:
    consumer_key: hogehoge
    consumer_secret: fugafuga
    oauth_token: foofoo
    oauth_token_secret: barbar

production:
    consumer_key: hogehoge
    consumer_secret: fugafuga
    oauth_token: foofoo
    oauth_token_secret: barbar
# lib/settings/twitter.rb
module Settings
  class Twitter < Settingslogic
    source "#{Rails.root}/config/twitter.yml"
    namespace Rails.env
  end
end
capistrano

https://github.com/capistrano/capistrano
定番のデプロイツールです。今回使ってみてその簡単さに惚れ惚れしました。
最終的に以下のコマンドでデプロイできるようになりました。プログラムの更新、DBのmigration、assetsのprecompile、unicornの再起動、cronの設定などもろもろが1コマンドで完了です。

$ cap production deploy
whenever

https://github.com/javan/whenever
cronの設定をRubyで書ける優れものです。cronの設定って結構間違えやすいのですが、これなら間違えない設定を書き出してくれます。

# config/schedule.rb
set :output, {:error => 'log/error.log', :standard => 'log/cron.log'}
every 6.hours do
  runner 'Batches::Battle::Main.start'
end
# crontab -l
0 0,6,12,18 * * * /bin/bash -l -c 'cd /path/to/application && script/rails runner -e development '\''Batches::Battle::Main.start'\'' >> log/cron.log 2>> log/error.log'
asset_sync

https://github.com/rumblelabs/asset_sync
precompileしたassetsをクラウドに配置できるgemです。僕はこれを使ってCSSJavascriptと画像をAmazonS3に配置しています。静的なファイルを置くならAmazonS3が一番優秀だと思います。
以下の設定ファイルを用意すればassetsのprecompile時に自動的に配置してくれるようになります。

# config/asset_sync.yml
production:
  fog_provider: 'AWS'
  fog_directory: 'Bucket名'
  fog_region: 'ap-northeast-1'
  aws_access_key_id: 'AWSアクセスキー'
  aws_secret_access_key: 'AWSシークレットアクセスキー'
  existing_remote_files: delete
  manifest: true
  gzip_compression: true
# config/environment/production.rb
Hoge::Application.configure do
  ...
  config.action_controller.asset_host = '//s3-ap-northeast-1.amazonaws.com/バケット名'
end

三者レビュアー

今回は id:nise_nabe という第三者のレビュアーがいたので、趣味とはいえ緊張感をもってコードを書くことができました。ソースコードBitbucketで管理して、彼のアカウントにRead権限だけ与えていました。これはもっと流行らせるべき。
オープンにしたくないソースコードを、一部の知人に公開することでよりよいコードが書けるようになると思います。

これからのはぐれメタルBOT

今回のリニューアルでさりげなくゴールドがもらえるようになったはぐれメタルBOT。ゴールドを集めておくといいことあるかも?