From: adgjmptw@... Date: 2008-07-01T14:55:42+09:00 Subject: [ruby-list:45177] Re: MySQLに書き込む前にSJISのエスケープ文字を入れる処理ってどうされてますか? かなり苦労しましたが何とかできました。(勉強になった。) ■まとめ。 MySQL/Rubyを使っている場合は my = Mysql.init my.options Mysql::SET_CHARSET_NAME, "cp932" で解決。 Ruby/MySQLはoptionsが無いっぽいので、 ・require "kconv"する。 ・MySQLに書き込む前にUTF-8にする。 (str.toutf8) ・MySQLから読み込んだ後にSJISにする。(str.tosjis) ■ソース(ちょっと長くなりますが、後学の為) ## Main.rb ################################################ require "mysql" # MySQLクラス require "lib/classup.rb" # 既存のクラスに関数を追加 ## MySQLインスタンス作成 (setparmは追加した関数) db=Mysql.init() db.setparm("localhost","user","pass","mydb","UTF-8","SJIS") ## SQL実行 (runsqlは追加した関数) sql="select DATA from tbl_test" csl=db.runsql sql ## 結果を表示 (cslは通常のhashの配列になっている) csl.each { |r| print "#{r['DATA']}" } ## Main.rb ここまで ###################################### ## classup.rb ############################################ require "kconv" ## Hashをオーバーライド ## hashにmapすると、どうしても結果が配列になってしまうので ## 結果をhashで返してくれるように関数を追加。 class Hash def maph(&b) inject(clone) {|h, (k, v)| h.update(k => b[k, v]) } end end ## MySQLをオーバーライド class Mysql ## 初期設定 def setparm(dbh,dbu,dbp,dbn,dbchar,txchar) @_host,@_user,@_pass,@_dbname,@_dbchar,@_txchar=[dbh,dbu,dbp,dbn,dbchar,txchar] end ## SQL実行 def runsql(sql) #SQL文の文字コードを変更 sql=sql.toutf8 if @_dbchar == "UTF-8" #SQL実行 self.connect(@_host,@_user,@_pass,@_dbname) csl=self.query sql self.close #SQLの実行結果をハッシュ配列に変換(selectの場合のみ) splt=sql.split(" ") if splt[0].upcase == "SELECT" then cursol=[] csl.each_hash(with_table=false) do |cline| hary=cline.maph{|x,y| y.tosjis} cursol< これがオープンクラス。 > 既存のクラスにメソッドを追加するとき、既存のメソッドやインスタンス変数と > かぶらないよう気をつければ、オープンクラスは味方になってくれます。 > 逆に、かぶってしまうと見付けづらいバグになります。 やっぱそうですよね。 「そういうリスクがあることを踏まえたうえで使いましょう」という 仕様ということで理解です。 > まあ、ほんとはブロック使うべきですがそれは次の段階ということで。 善処します... > eachの代わりにmapを使えばいいという指摘は既出なのでおいといて、 > この場合わざわざインスタンス変数にする意味がないと思います。 > @sql、@cursor、@curはローカル変数で十分です。 ついにローカル変数とインスタンス変数の違いを覚える時が来たのですね... 「どちらも他のオブジェクト(インスタンス)からは見えないけど、 特にローカル変数はインスタンス内の他の関数からも見えない」 でしたっけ。 一通り修正しました。ついでに変数名も@_hostとかわかりやすく。 mapがうまく使えなかったのでHashに関数を追加して仮対策したのは 前述のとおりです。将来の自分が解決することに期待。 >> self.connect("#{@dbh}","#{@dbu}","#{@dbp}","#{@dbn}") > ここも式展開を使うまでもなく、普通に変数で指定すればよい。 ここ以外にもこういう扱いをしている部分があったので だいぶ掃除しました。 POSTで受け取った値の扱いがイマイチよくわからない(to_iとか するとエラーになる)のですが、それはまた別途。 > というかdbが未定義だから、 > undefined local variable or method `db' for main:Object (NameError 一因でした。(ノ∀`)タハー >> ・runsqlの中でrequire "kconv"をやっている。 >> initializeで出来ないかなぁ...MySQLのinitializeとぶつかりそうだなぁ > > lib/classup.rbの冒頭に置けばいいです。 これもそのうち整理しないと。 Mainのソース内でrequireしたライブラリ(モジュール?)は、Mainの中で使っている他のク ラスに影響するかとか。 > # adgjmptwが気になってぐぐってみたら、携帯電話でアルファベットにして2〜9を > # 順番に打つと出るんですね… フフフ....そうなのです。人にアドレスを教えるときに便利なのです。まあ、最近は赤外 線とか使えば一発ですが。 結構競争率が高いのですが、自分のプロバイダと携帯電話はこのアドレスをGETしました。 いっぱいアカペンありがとうございました。 (スーパープログラマーな人もこうやってKnowHowを吸収してきたんかなぁ) -- ============================ Katsumi Tada mailto:adgjmptw@super-r.net