Railsで,簡単にメッセージ管理する方法 (メッセージ定義書からメッセージ処理クラスを自動生成するVBAマクロ)
アプリケーション開発で,表示文言やエラーメッセージを一元管理したい場合,GetTextを使うのがスタンダードだ。
Ruby on RailsでRuby-GetText-Packageを使う (Rails-2.1.x以前)
http://www.yotabanana.com/hiki/ja/rub...
しかしこの方法は汎用的である反面,結構面倒だったりする。
.po/.moの処理系を別途組み込む必要があるためだ。
また,単にメッセージ管理をしたいだけなら,国際化(i18n)の機能は不要になる。
かわりに
- メッセージを処理するためのシンプルなクラスを利用することにして
- そのクラスを,プロジェクトのメッセージ定義書から自動生成する
という方法がある。
Ruby on Rails では,例えば下記のようなクラスを作ればよい。
置き場は lib/simple_msg.rb。
# システム中で利用されるメッセージを保持するクラス class SimpleMsg # メッセージ一覧 # メインメニュー:正常 MENU_NORMAL_SELECT = "動作を選択してください。" MENU_NORMAL_WELCOME_USER = "ようこそ%{1}さん" # メインメニュー:異常 MENU_ERR_MAINTENANCE = "ただいまメンテナンス中です。" MENU_ERR_CANT_LOGIN = "ログインできません。" # 入力フォーム:正常 FORM_NORMAL_PLEASE_INPUT = "下記の項目を入力してください。" FORM_NORMAL_NOTICE_HISSU = "※がついた項目は入力必須です。" # 入力フォーム:異常 FORM_ERR_STRLEN_MAX = "%{1}文字以内で入力してください。" FORM_ERR_SELECT_MAX = "%{1}は%{2}個まで選択可能です。" FORM_ERR_FORBID_DOUBLEQUOTE = "「\"」は使用できません。" # 置換済みメッセージを出力 def self.plain(msg_id, args = []) str = self.const_get(msg_id) args.each_with_index{ |value, index| str = str.sub("%{#{ ( index + 1 ).to_s }}", value.to_s)} str end # HTML要素として出力 def self.span(msg_id, args = []) "<span class='#{ msg_id }'>#{ self.plain(msg_id, args) }</span>" end end
このクラスの中に,メッセージID=メッセージ内容 の形式で,メッセージ・文言を保持しておく。
置換文字列は%{n}の形式で埋め込むことが可能。
※メッセージのキーとしてとりあえず,NORMALが正常系,ERRが異常系という分け方をしている。
これは別に,メッセージ呼び出し部分のコードを見た時にそれが何のメッセージなのか伝わりさえすれば何でもよい。
まさかとは思うが,メッセージIDを数字で振るなどの愚行は犯さないように。
使い方は,たとえばビュー(rhtml)の中で
<%= SimpleMsg.span("MENU_NORMAL_WELCOME_USER", [ "ゲスト" ]) %> <%= SimpleMsg.span("FORM_ERR_SELECT_MAX", [ "カテゴリー", 3 ]) %> <%= SimpleMsg.span("FORM_ERR_FORBID_DOUBLEQUOTE") %>
とすれば,HTMLとして
<span class='MENU_NORMAL_WELCOME_USER'>ようこそゲストさん</span> <span class='FORM_ERR_SELECT_MAX'>カテゴリーは3個まで選択可能です。</span> <span class='FORM_ERR_FORBID_DOUBLEQUOTE'>「"」は使用できません。</span>
が出力される。
そして,そのようなSimpleMsgクラスをExcelのメッセージ定義書から生成するためのシートは,下記からダウンロードできる。
メッセージ処理クラスを生成可能なメッセージ定義書
http://www.name-of-this-site.org/codi...
マクロは下記のとおり。
Sub メッセージ処理クラスを作成() ' 定数 Const adTypeText = 2 Const adTypeBinary = 1 ' 出力パス output_path = get_class_filepath ' UTF-8で書き出し(あとでBOMを除去する) Dim ados As Object Set ados = CreateObject("ADODB.Stream") ados.Open ados.Type = adTypeText ados.Charset = "UTF-8" br = vbNewLine ' 改行 ados.WriteText "# システム中で利用されるメッセージを保持するクラス" & br ados.WriteText "class SimpleMsg" & br ' シート内をスキャン x_page = 2 x_msgtype = 3 x_msgid = 4 x_msgstr = 5 y_offset = 5 y = y_offset continue_flag = True old_page = "" old_msgtype = "" ' 全メッセージに対して Do While (continue_flag = True) ' 行内容を取得 msg_page = Cells(y, x_page).Value msg_type = Cells(y, x_msgtype).Value msg_id = Cells(y, x_msgid).Value msg_str = Replace(Cells(y, x_msgstr).Value, """", "\""") ' 有効な行か If (Len(msg_id) > 0) And (Len(msg_str) > 0) Then ' メッセージの種別が変わったか If (Not (old_page = msg_page)) Or (Not (old_msgtype = msg_type)) Then old_page = msg_page old_msgtype = msg_type ' 種別コメントを振り直し ados.WriteText br & " # " & msg_page & ":" & msg_type & br End If ' 書き出し ados.WriteText " " & msg_id & " = """ & msg_str & """" & br y = y + 1 Else continue_flag = False End If Loop ' クラスメソッド ados.WriteText " " & br ados.WriteText " # 置換済みメッセージを出力" & br ados.WriteText " def self.plain(msg_id, args = [])" & br ados.WriteText " str = self.const_get(msg_id)" & br ados.WriteText " args.each_with_index{ |value, index| str = str.sub(""%{#{ ( index + 1 ).to_s }}"", value.to_s)}" & br ados.WriteText " str" & br ados.WriteText " end" & br ados.WriteText " " & br ados.WriteText " # HTML要素として出力" & br ados.WriteText " def self.span(msg_id, args = [])" & br ados.WriteText " ""<span class='#{ msg_id }'>#{ self.plain(msg_id, args) }</span>""" & br ados.WriteText " end" & br ados.WriteText "end" & br ' 先頭のBOM取り ados.Position = 0 ados.Type = adTypeBinary ados.Position = 3 byte_data = ados.Read ados.Close ' UTF-8Nコードのデータを保存 ados.Open ados.Type = adTypeBinary ados.Write byte_data ados.SaveToFile output_path, 2 ados.Close End Sub ' 処理クラス名を返します Function get_class_name() get_class_name = Sheets("設定").Cells(4, 3).Value End Function ' クラス設置パスを返します Function get_class_filepath() get_class_filepath = Sheets("設定").Cells(5, 3).Value End Function
VBAでファイル出力をする場合,ふつうはFreeFileを使ってSJISで書き出す。
しかし,Ruby on Rails では何もかもUTF-8NでないとSyntax Errorになったりする。
上記のマクロでは,いったんUTF8(BOMあり)で書きだしたあとで,BOMを除去している。
参考:
CSVファイルをUTF-8Nで作成したい
http://www.vbalab.net/vbaqa/c-board.c...