ActionMailer でテンプレートを指定する2009/08/11

ActionMailer のRDocでは何故か解説が無いようですが

Model側で

class FooMailer < ActionMailer::Base
  def bar
    from 'foobar@example.com'
    recipients 'foobar@example.com'
    
    template 'hoge'
    body :mes1 => 'hogehoge', :mes2 => 'foobar'
  end
end

FooMailer.create_bar # foo_mailer/bar.erb ではなく foo_mailer/hoge.erbが使用される

と、templateメソッドを利用すると、当該のメールがcreate!される際のテンプレートが明示的に指定できます。 引数は、APP_ROOT/app/views/foo_mailer からの相対パスです。 拡張子は、例のルールで補完されます。

テンプレートをファイルではなく String で与えたい場合に適切なメソッドは無いのですが、 ActionMailer::Base#create! は実行された際、@body が 既にStringのインスタンスならレンダリング処理はスキップして @body の内容をそのままメール本文とするようです。

class FooMailer < ActionMailer::Base
  def piyo
    from 'foobar@example.com'
    recipients 'foobar@example.com'
    
    body 'piyo piyo'
  end
end

FooMailer.create_piyo.body #=> 'piyo piyo'

あとは、自前でerbのコンパイルをするか、 ActionController::Base#render に、:inlineを与えたときのようなメソッドを実装すればいけるはず。 (ActionMailer::Base#render はファイル名しか取れない)

とりあえず、今日はここまで

win32ole で Execlファイルのフォーマット変換2009/08/11

Spreadsheetでどうにもパースできないxlsファイルがあったので、 久し振りにwin32ole経由でExcelを制御しようとしたら、結構忘れていたので自分用メモ

require 'win32ole'

module Excel
end

excel = WIN32OLE.new('Excel.Application')
excel.displayAlerts = false
WIN32OLE.const_load(excel, Excel)

Dir['*.xls'].each do |fn|
  ifn = File.expand_path(fn).gsub('/', '\\')
  ofn = ifn.sub(/xls$/, 'tsv')
  wb = excel.Workbooks.Open(ifn)
  wb.Worksheets(1).Select
  wb.SaveAs(ofn, Excel::XlText)
  wb.Close
end

Workbooks.Openにはフルパスを与える必要があるのと、パスの区切り記号を'\'にするのを忘れないこと。

フォーマット定数はこちら

Ruby のwin32oleで扱うときは、先頭のxを大文字にすること。

TSV(Excelでの表記は"テキスト形式")がリストに無いような気がするけど Excel::XlText(-4158) を指定すると、TSVになる。

Excel::XlUnicodeText(42) は UTF-16のTSVなので扱いに困る。

CSVが良ければ Excel::XlCSV(6) を指定する。

Closeを忘れると60ぐらいで落ちる。