2011年7月7日木曜日

crontabを設定するプラグイン「whenever」

Railsの機能を使った処理を簡単にcrontabに設定するプラグイン「whenever」があります。DSLによって、Rubyライクな書き方でcrontabを設定できるのが特徴です。

whenever

mysqlのバックアップを定期的に行うプログラムを使って、バッチ処理を組み込む方法を紹介します。

まずバッチ処理を記述します。ファイル名「lib/batch_backup.rb」とします。
# coding: utf-8
class BatchBackup
  def self.execute
    backup_database
  end

  # データベースのバックアップ
  def self.backup_database
    env = Rails.env
    # バックアップファイルを格納するフォルダ(作っておく)
    location = "~/backup/database/"
    password = mypassword
    backup_file = "myapp_#{env}_#{Date.today.strftime("%Y%m%d")}.sql"

    command = "mysqldump myapp_#{env} > #{location}#{backup_file} -u root -p#{password}"
    system(command)
end
私はバッチ処理プログラムをlibフォルダに格納します。このままではRailsはこのファイルを起動時に読み込まないので、config/application.rbに下記を追加します。
config.autoload_paths += %W(#{Rails.root}/lib)
次にwheneverの設定を行います。インストールは
$ sudo gem install whenever
か、Gemfileに下記を追加して、sudo bundle installするかのいずれかを選択します。
gem "whenever", :require => false
インストールが完了したら、wheneverの初期設定です。Railsのルートフォルダで下記を実行します。
$ wheneverize .
すると、config/schedule.rbが作成されます。ここにcrontabに設定したバッチ処理を記述します。
set :output, "/home/rails/myapp/cron_log"

every 1.day, :at => '5:00am' do
  runner "BatchBackup.execute"
end
ここでは毎日5:00にこのバッチ処理を実行するように記述しています。

また、cronの実行ログを出力するため「set :output」を指定しています。cronの実行ログは(ubuntuの場合)/var/log/syslogに記述されていますが、プログラム上の問題を出力するにはこれが必要になります。

次にcapistranoでデプロイした際、バッチ処理を設定するようにconfig/deploy.rbを編集します。
ここではwheneverが用意したcapistrano用のレシピファイルを使うことにします。config/deploy.rbに下記を追記します。
require "whenever/capistrano"
これでcap deployしたときに自動でcrontabに設定してくれるようになります。

では、サーバーへアップします。
$ git add .
$ git commit -a -m "バックアップバッチ処理を追加"
$ git push origin master
$ cap deploy
次にサーバーへアクセスして設定できているかチェックします。
$ ssh rails@mydomain.jp
$ crontab -l
設定されていれば下記のように表示されると思います。
0 5 * * * /bin/bash -l -c 'cd /var/rails/myapp/releases/xxxxxxxxxxxxx && script/rails runner -e production '\''BatchBackup.execute'\'' >> /home/rails/myapp/cron_log 2>&1'
これでOKです。

ちなみに私はこの先ではまってしまいました。
~/myapp/cron_logに下記のようなエラーが出力されていました。
/usr/lib/ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require': no such file to load -- bundler/setup (LoadError)
        from /usr/lib/ruby/1.8/rubygems/custom_require.rb:31:in `require'
        from /var/rails/myapp/releases/xxxxxxxxxxxxxx/config/boot.rb:6
        from script/rails:5:in `require'
        from script/rails:5
どうやらバッチ処理を実行する際、以前使用していたRuby 1.8のgemを見に行っているようです。

そこでconfig/schedule.rbに実行時のパスの指定を行います。
set :output, "/home/rails/myapp/cron_log"
env :PATH, "/usr/local/bin:/usr/bin:/bin" # <= 追加

every 1.day, :at => '5:00am' do
  runner "BatchBackup.execute"
end
これで動作するようになりました!

<参考>
http://stackoverflow.com/questions/5698028/whenever-path-in-crontab-file-for-rails-3-ubuntu

2011年7月4日月曜日

Railsとスマートフォン対応

これからのサービスはフィーチャーフォンだけでなく、スマートフォンへの対応が必須だと思います。ただ、スマートフォンをもっていないため、いまいちぴんときていません。そこで、まずはiPod touchを購入して、iPhoneでの関連技術について調べてみました。

1)ネイティブアプリ
アプリといえばこれですね。有料や無料のアプリをApp Storeで展開します。Appleの審査が必要で、開発にはObjective-Cを使用します。いまはRubyに特化して開発を進めていますが、もう一つ言語を習得し、Xcodeという開発環境にも慣れる必要があります。すこし敷居が高そう。

評判のよかった下記の本を参考にすこし試してみました。
よくわかるiPhoneアプリ開発の教科書

確かにわかりやすいが、やはりObjective-Cは気持ちいいとはいえない。しかも、ローカルで動くアプリはできても、インターネットにあるサーバーとの連携は手強そうだ。これは最終手段で、何か他によい方法がないか調べてみます。

2)ObjectiveResource
ObjectiveResourceはRailsとiPhoneネイティブアプリの連携をかんたんにする仕組みです。RailsとObjectiveCのコードに少し付け足すだけで、簡単に連携ができるようになります。

しかし、どうやらiOSのバージョンアップで動作しなくようになり、しかも、開発がコントロールできていない模様。Githubでフォークされたものも試してみたが、どうも動作しない。クッキーなどのブラウザの機能に対応できているか不安になり、不採用。

3)PhoneGap
HTML + CSS + JavaScriptでネイティブアプリを開発する環境。セミナーに参加して、何者かを調べてみました。

どうやらカメラやGPSなどのiPhone特有の機能はJavaScriptをつかって制御し、見栄えをHTMLで記述するもののようです。

一番気になっていたサーバーとの連携はできないのではないかと想像しています。(検証していません)あくまでもHTMLは静的なもので、それをPhoneGapのWebViewというコンポーネントで表示しているように思えます。ということで不採用。

<PhoneGap>
http://www.phonegap.com/

4)JQuery MobileとJQTouch
Webアプリはブラウザ技術と一体で考えなければなりません。ブラウザ技術は未だに発展中ですし、Railsとの連携を前提すると、ブラウザ上で動作するものが最もリスク、コストが低くなるのかもしれません。

調べてみるとネイティブアプリ風に見せる仕組みがあることがわかりました。それが「JQuery Mobile」と「JQTouch」です。

<JQuery Mobile>
http://jquerymobile.com/

<JQTouch>
http://jqtouch.com/

RailscastsにJQTouchをつかったビデオがあったので、これを見ながら試してみましたが、最新のRails、JQueryだとアニメーションがうまく動作しませんでした。

そこでJQuery Mobileを試してみると、最新の技術でもうまくいきました。ネイティブアプリと比べると動きなどいまいちですが、まだJQuery Mobileはベータですし、今後もちゃんとサポートされていきそうなので、ひとまずこれを採用することにしました。

試していないのですが、このほかに「Titanium」「Rhodes」といったものもありました。この分野は競争が激しそう。しばらくは目が離せませんね。