のえら

技術備忘とかメモとか.間違いはつっこんでいただきたい所存.

ruby on rails で utf-8 から shift_jis にしたかった

起きたこと

csvをダウンロードする機能を作っていたんだけども、ダウンロードしてみたら例外が発生。

Encoding::UndefinedConversionError in HogesController#index
U+2212 from UTF-8 to Windows-31J

エンコーディング的な??
で、調べてみたら全角マイナス、っていうのが変換できてなくて怒られていた。


とりあえずやってみたこと

CSV.generateのオプションに :encoding => 'sjis' を指定
 ⇒効かない(変化なし)
・force_encoding使ったりcharsetいじってみたり
 ⇒効かない(変化なし)
・data.encode(Encoding::SJIS)にオプション :undef => :replace を追加
 ⇒変換できないものを ? に置き換えるのでダウンロード自体はできる

ぐぬぬ・・・
色々ググって、特定の文字をSJISに変換できるようにするメソッドを作ることにした。


ごりごり書いてみる

Stringにメソッド生やすのではなく、変換モジュールを作る。
#メソッド追加するのちょっと怖い
師匠に手伝っていただきながらごりごり書く。

# coding: utf-8

module StringEncoder
  # 文字コードをUTF-8からSJISに変換する
  def self.convert(str)
    str.gsub(REPLACE_KEYS, CONVERSIONS)
  end

  private
  # Unicode変換組み合わせ
  CONVERSIONS = {
    "\u301c" => "\uff5e", # wave-dash
    "\u2212" => "\uff0d", # full-width minus
    "\u00a2" => "\uffe0", # cent sign
    "\u00a3" => "\uffe1", # pound sign
    "\u00ac" => "\uffe2", # not sign
    "\u2014" => "\u2015", # full-width dash
    "\u2016" => "\u2225"  # double vertical line
  }

  # 変換対象
  REPLACE_KEYS = /[#{CONVERSIONS.keys.join}]/
end


使うときは StringEncoder.convert "〜−¢£¬−‖" ってな感じ。
Stringに追加したバージョンも試してみたいなー。