Ruby(Rails)からExcelで文字化けしないCSVファイル作成
CSVファイル作成でハマったのでメモ。
今回作ろう思っていたのはリンクになっているボタンを押したらCSVファイルがダウンロードされるという単純なものです。
HTML載せようと思いましたがはてブ内での書き方わからないので省略、、
バージョンはRuby2.0, Rails4です。
controllerは下記のような感じで処理はmodelに。
# controllers/management_controller.rb def event_csv respond_to do |format| format.csv { send_data Event.event_csv(start_date, end_date), :filename => "events_#{start_date}-#{end_date}.csv" } end end
もともとはここで:type => ""でcontent-typeをcsvと指定していたのですがそれではうまくいきませんでした。
modelは下記
# models/event.rb class Event < ActiveRecord::Base class << self def event_csv(start_date, end_date) data = self.all csv_data = CSV.generate do |csv| csv << %w(ユーザー 所属 合計) # headerになる部分を先にpush data.each do |record| csv << [record[:username], record[:belonging], record[:sum]] end end csv_data end end end
ここでもまだ文字コード指定はしていません。
CSV.generate自体ウェブ上にあまり情報がなくて、しかもdocumentを見るとgenerate('', :encoding => 'sjis')みたいな感じで:encodingで指定できるよ!って書いてあるのですが できませんでした。。(文字コードは上記の場合、csv_data.encodeで調べられます。)
なのでさらに戻ってcontrollerから最後吐き出すときにafter_filterでnkfを使ってShift_JISにエンコードするという方法で解決しました。
class ApplicationController < ActionController::Base after_filter :cahnge_charset_to_sjis, :if => csv? ... private def csv? return request.original_url.match(/csv/) ? true : flase end def change_charset_to_sjis require 'nkf' response.body = NKF::nkf('-Ws', response.body) headers["Content-Type"] = "text/csv; charset=Shift_JIS" end end end
パスがcsvだったらsjisに文字コードを変えるメソッドを通してるって感じです。ここでheader["Content-Type"]も設定しています。
ちなみに念のためconfig/routes.rbにはこんな感じで書いてます。
get 'management/event_csv/(:start_date)/(:end_date)', :to => 'management#event_csv'
controllerの中でrespond_toでcsvを指定しているので上記のパスに.csvでアクセスするとcsvファイルがダウンロードされる、という感じです。(ex. /management/event_csv.csv)
文字化けは相変わらず辛い・・・。
うまく行かなかったところはもうちょい追求しなければ。
もっと良い実装があればぜひコメント下さい!m(_ _)m