【ruby】クラスCGIを改造して、クエリの文字コードを変えたい

このQ&Aのポイント
  • RubyのCGIクラスを改造して、クエリの文字コードを自動的に変換する方法を探しています。
  • Windowsサーバで使用しているため、取得したクエリ(フォームフィールド)をs-jisに変換する必要があります。
  • 以前にはaliasを使用して同様のことを試みましたが、成功しませんでした。改造方法についてのご指導をお願いします。
回答を見る
  • ベストアンサー

【ruby】クラスCGIを改造して、クエリの文字コードを変えたい

クエリパラメータを取得するのにCGIクラスを使っています。 Rubyのマニュアルでは『フォームフィールドの値を得る』として以下の様に記載してあります。 require "cgi" cgi = CGI.new values = cgi['field_name'] # <== 'field_name' の配列 私が使用しているサーバはWindowsサーバでして、取得したクエリ(フォームフィールド)は文字コードをs-jisに変換して使う事が大半です。 そこで、CGIクラスそのものを改造して、いちいちvalues.tosjisしなくてもよい様にしたいです。 実は以前に、同じような事を質問してまして(http://oshiete1.goo.ne.jp/qa4944090.html)alias を使えばこのようなことが出来るかなと思い、以下の様に書いてみました。(行頭は全角スペースです。) #!/usr/local/bin/ruby require 'cgi' require 'kconv' STDOUT.binmode STDIN.binmode class CGI  alias :initialize_orig :initialize  def initialize()   hash=initialize_orig()   hash.each do|key,val|    hash[key]=val.collect{|x|x.tosjis}   end   hash  end end cgi=CGI.new if cgi.has_key?('arg') then  STDERR.puts cgi['arg']  cgi.out(){'ok'} end 結果は `initialize': undefined method `each' for nil: NilClass (NoMethodError) で実行不可でした。 initializeはリターンできないからかな。 次に、 class CGI  alias :params_orig :params  def params()   hash=params_orig   hash.each do|key,val|    hash[key]=val.collect{|x|'*' + x + '*'}   end  hash end end などとも書いてみましたが、 undefined method `params' for class `CGI' で実行不可でした。 ご指導のほど、よろしくお願いいたします。

  • Ruby
  • 回答数2
  • ありがとう数2

質問者が選んだベストアンサー

  • ベストアンサー
  • notnot
  • ベストアンサー率47% (4846/10257)
回答No.1

テストしてませんが、これでどうでしょう。 class MyCGI < CGI  def initialize(type = "query")   super   @params = @params.each do|key,val|    @params[key]=val.collect{|x|x.tosjis}   end  end end cgi=MyCGI.new if cgi.has_key?('arg') then  STDERR.puts cgi['arg']  cgi.out(){'ok'} end あと、tosjisメソッドは入力文字列コード自動判定ですが、短い文字列だと判定が間違う可能性があるので、kconvメソッドで入力文字コードも指定した方がいいです。

kingfruits
質問者

補足

notnotさん ご回答ありがとうございます。 #たびたびのご回答、ありがとうございます。 >def initialize(type = "query") のtype = "query"の意味がよくわかりませんでしたが、 def initialize()として動かしてみたところ、問題なく動作しました。 ご回答頂いた解法は、CGIクラスそのものを改造というより、CGIクラスを 継承して、新しいクラスMyCGIを作る方法ですが、できればCGIクラスそのものを改造したいです。 もしくは、新しいクラスを生成しないで、特異クラス定義でなんとかならないでしょうか? cgi=CGI.new class << cgi ここをどう書いたらよいか解らない。 end 上手く伝えられないのですが、『cgi=MyCGI.new』と記述する事になぜか 抵抗がありまして。。 良案ありましたら、よろしくお願いいたします。

その他の回答 (1)

  • notnot
  • ベストアンサー率47% (4846/10257)
回答No.2

>継承して、新しいクラスMyCGIを作る方法ですが、できればCGIクラスそのものを改造したいです。 機能の追加じゃなくて機能を変えることになるので、新規クラスがいいと思いますが。 もとのクラスでやるとすると、cgi.rbの最後の方に書いてあるdef initialize(...) .... end を全部コピーして、その最後の部分に、@paramsの書き換えを追加するのでしょうか。 class CGI  def initialize(type = "query")   ここにオリジナルのコードをコピー   @params = @params.each do|key,val|    @params[key]=val.collect{|x|x.tosjis}   end  end end あるいは、paramsメソッドだけ書き換えればいいのであれば、 class CGI  module QueryExtension   def params    w = {}    @params.each{|k,v| w[k]=v.collect{|x| x.tosjis}}    w   end  end end 毎回全部をコード変換するので、あまり良くないかな?フラグを設けて、初回だけ@paramsを書き換えるようなほうがいいでしょうね。 いずれにせよ、CGIクラスの機能を変更したい(orサブクラスを作りたい)のならば、cgi.rbを読まないとだめですよ。

kingfruits
質問者

お礼

notnotさん ご回答、ありがとうございます。 大変勉強になります。 >>機能の追加じゃなくて機能を変えることになるので、新規クラスがいいと思いますが。 先日notnotさんにご回答頂いた【ruby】クラスCGIを改造したい(​http://oshiete1.goo.ne.jp/qa4944090.html​)ですと、aliasを使って CGIクラスの機能を変えていたので、『あり』なのかと思ってましたが、今回の解法をみますと、一番最初のご回答がスッキリしてるように思います。 >>cgi.rbを読まないとだめですよ。 はい。

関連するQ&A

  • Ruby1.8.7 ファイルアップロードCGI

    CGI を使ったファイルのアップローダを作りたくて、今日初めて Ruby を触っていますが、質問があります。 アップロードするファイル本体以外の情報を name="version" で受け取って、保存するディレクトリを分けるようにしています。書きかけのコードは以下の通りです。(タブによるインデントが入らなかったので、アンダースコアで表現しています) ----------ここからソースコード---------- #!/usr/local/bin/ruby require "cgi" begin __print "Content-Type: text/plain\n\n" __cgi = CGI.new __print "Ruby version is " __print RUBY_VERSION,"\n" __print "filename = " __print cgi['upload_file'].original_filename, "\n" __file = cgi.params['version'][0] __if file.class == StringIO then ____print "File is StringIO Class.\n" ____print "version = " ____print cgi["version"].string, "\n" ____if File.exist? cgi["version"].string then ______print "このバージョンのディレクトリは既に存在しているため、ディレクトリは作成されませんでした。" ____else ______print "ディレクトリが存在しないので作成します。" ______Dir::mkdir(cgi["version"].string, 0755) ____end ____OUTPUT_DIR = (cgi["version"].string + "/") ____open(OUTPUT_DIR + cgi['upload_file'].original_filename, "w") {|fh| ____fh.binmode ____fh.write cgi['upload_file'].read ____} __else ____print "File is TempFile Class.\n" ____#ここから先が書きかけで分からない部分です。 __end rescue => e __print "Error!" + e end ----------ここまでソースコード---------- Ruby の CGI モジュールを使っていますが、受け取ったファイルが 10240 バイト未満だと StringIOオブジェクト、10240 バイト以上だと TempFile オブジェクトになるという規則があるそうで、オブジェクトの種類によって分岐させています。 StringIO オブジェクト(10240バイト未満の送信)の場合はこれで想定通りに動いたのですが、TempFile オブジェクトと判別された場合に、 version のテキストフィールドの文字列を print により表示(出力)したりディレクトリ名にしたりする方法が分かりません。また、ファイル本体 upload_file は TempFile オブジェクトの場合でも同じ記述でファイルに保存できますでしょうか? サーバにインストールされている Ruby のバージョンは 1.8.7 です。

  • Ruby ハッシュ継承クラス、作成方法について

    ハッシュを拡張し、値をキーで指定した範囲内から取得したいと思っているのですが、ハッシュと同じように作成できないのでしょうか? 試行錯誤してみたのですが、記述が分かりません・・・。 class Range_List < Hash  #  # 範囲に対応する、値を取得(速度が気になりますが・・・)  #  def [](other)   @list.each { |range, value|    return value if range === other   }   nil  end end # 角度 (0..1) に対応する、十キーのリストを作成 angle_to_direction = Range_List{  # => エラー。このような記述で呼び出したい  0.0625..0.1875 => 3,  0.1875..0.3125 => 2,  0.3125..0.4375 => 1,  0.4375..0.5625 => 4,  0.5625..0.6875 => 7,  0.6875..0.8125 => 8,  0.8125..0.9375 => 9,  0.9375..1    => 6,  0..0.0625    => 6 } # 角度対応の十キーを求める p angle_to_direction[0.1]  # => 3 どうかご回答お願いいたします。

    • ベストアンサー
    • Ruby
  • Ruby:CGI Content-Type: の設定方法

    以下に示すcgiの実行結果をContent-Type: application/x-javascriptにしたいのですが、どうしたら良いですか? #!/usr/local/bin/ruby require "cgi" cgi = CGI.new time=Time.new cgi.out do "document.write(\"#{time}\");" end

  • 処理内容

    以下の3点について有識者へ伺いたいです。 (1)このプログラムが何をするものなのか (2)最後のfor文が無限ループしてしまう理由 (3)可能であれば、各行(各処理)が何をしているのかを教えていただければ嬉しいです。 #include <stdio.h> #include <string.h> #define NUM_HASH 10 char *hash_key[NUM_HASH]; unsigned char hash_val[NUM_HASH]; unsigned char calc_hash_value(const char *key) { int i; unsigned char val = 0; for (i = 0; key[i] != '\0'; i++) val += key[i]; return val; } int main(int argc, char *argv[]) { int i, cnt = 0; unsigned char val; for (--argc, ++argv; argc > 0 && cnt < sizeof(hash_val)/sizeof(hash_val[0]); --argc, ++argv, cnt++) { hash_key[cnt] = *argv; hash_val[cnt] = calc_hash_value(hash_key[cnt]); } for (val = 0; val < 256; val++) { for (i = 0; i < cnt; i++) { if (val == hash_val[i]) { printf("key = |"%s|"|n", hash_key[i]); printf("hash value = 0x%.2X|n", hash_val[i]); } } } return 0; }

  • 日本語文字化け(GETメソッド?)

    以下のようにすると日本語の受け渡しがうまくいきません。(抜粋) そももこの場合、日本語の受け渡しは、出来ないのでしょうか。 それともコンバートのやり方がまずいのでしょうか。 お知恵をおかしください。宜しくお願い致します。 URL:test.cgi?name=日本語 #!/usr/local/bin/perl require './cgi-lib.pl'; require './jcode.pl'; # 読込 &getinput; $name = $form{'name'}; print "Content-Type: text/html\n\n", $name; exit; sub getinput { &ReadParse; while (($key,$val) = each %in) { &jcode'convert(*val, "sjis", "", "z"); $form{$key} = $val; } }

    • 締切済み
    • CGI
  • XREA MySQL CGI Ruby エラー

    XREAの無料サーバーに設定されたMySQLのデータベースをCGIとして設定したRubyからアクセスしたいのですが、require 文を入れると Internal Server Error が出ます。(コメントアウトすると動きます) よろしくお願いします。 #!/usr/local/bin/ruby require 'mysql' #↑ここが問題と思われます puts 'Content-Type: text/html' puts '' puts '<!doctype html>' puts '<html>' puts '<head>' puts '<meta charset="utf-8">' puts '<title>TEST</title>' puts '</head>' puts '<body>' puts 'Hello World' #↓requireでエラーになるのでコメント中 #my = Mysql.new('127.0.0.1', 'id', 'password', 'dbname') #res = my.query('SELECT * from T_test') #res.each do |row| # puts row[0] #end puts '</body>' puts '</html>'

    • ベストアンサー
    • CGI
  • Ruby WEBrick cgiからgifが最後まで送れない。

    以下のようなHTTPサーバをWinXp上で動かしました。 #$ruby = "C:/ruby/bin/ruby.exe" require 'webrick' srv = WEBrick::HTTPServer.new({ :BindAddress => 'xxx.xxx.xxx.xxx', :CGIInterpreter => "c:/ruby/bin/ruby.exe", :Port => 80 }) srv.mount("/", WEBrick::HTTPServlet::FileHandler, "./", {:FancyIndexing=>true}) srv.start そして、以下のようなCGIをよびます。 #!/usr/bin/ruby STDOUT.binmode open("hoge.gif", "r") do |f| f.binmode body = f.read puts "content-type: image/gif" puts "content-length: #{body.size.to_s}" puts "" print body end すると、content-length分のHTTPボディーが送られてきません。 2種類のgifで試しましたが、193byte/724byte、289byte/451byteでした。 バージョンは、ruby 1.8.6、WEBrick 1.3.1です。 何が原因でしょうか?

  • 今更ながらdbmopenでutf8環境にハマってます。

    今更ながらdbmopenでutf8環境にハマってます。 #!/usr/bin/perl use strict; use warnings; use utf8; use open ":utf8"; use open ":std"; my $key1='test'; my $key2='test2'; my $val1 = 'あああ'; my $val2 = 'いいい'; print "$key1 $val1\n"; print "$key2 $val2\n"; open(my$fh,">./utf8DB2"); print $fh "$val1\n"; print $fh "$val2\n"; close $fh; my %HASH; dbmopen(%HASH, 'utf8DB', 0666); #utf8::decode($val1) if utf8::is_utf8($val1); #utf8::decode($val2) if utf8::is_utf8($val2); #下記2行が無いとWide character in null operation at ... utf8::encode($val1)if utf8::is_utf8($val1); utf8::encode($val2)if utf8::is_utf8($val2); $HASH{$key1}="$val1"; $HASH{$key2}="$val2"; dbmclose(%HASH); my%DBM; dbmopen(%DBM,'utf8DB',0666); while ( my( $key , $val ) = each %DBM ){ #utf8::decode($val) if utf8::is_utf8($val); #utf8::encode($val) if utf8::is_utf8($val); print "key1 : $key 値 : $val\n" ; } foreach my$key ( keys( %DBM ) ) { #utf8::decode($DBM{$key}) if utf8::is_utf8($DBM{$key}); #utf8::encode($DBM{$key}) if utf8::is_utf8($DBM{$key}); print "key2 : $key 値 : $DBM{$key}\n"; } dbmclose(%DBM); 上記スクリプトを実行時、値を表示する際に文字化けしているのですが、これは、dbmopenで保存時既に文字化けしているのでしょうか、それとも表示する際、適切にエンコードorデコード出来てないから文字化けしているのでしょうか。 また、どのようにすれば解決可能かご教授願えませんでしょうか。 いっその事、DataDumperで保存し、読み出すように修正しようかとも思うのですが、tieに変更した場合も、同様に文字化けするのでしょうか・・ その辺りも含め、アドバイス他ご教授願えますと助かります。

    • ベストアンサー
    • Perl
  • Array#eachのブロック中で要素追加

    初歩的な質問で申し訳ありません ary = [Foo.new] ary.each do |i|  if (条件)   ary.push(Foo.new)  end end 上の様にブロックの中である条件でaryに要素が追加されます。 この場合、この追加された要素はeachで漏れなく扱えるのでしょうか? 簡単なプログラムで試した限りではpushされたFooインスタンスについてもeachで取り出せているようなのですが、自信が無いので質問致します。 # coding: windows-31J class Foo attr_accessor :checked attr_reader :val RAND_MAX = 5 def initialize rnd = Random.new @checked = false @val = rnd.rand(RAND_MAX).to_i end end ary = [Foo.new] ary.each do |f| if f.val > 0 ary.push(Foo.new) end f.checked = true end cnt_true = 0 cnt_false = 0 ary.each_index do |idx| print "#{idx} #{ary[idx].checked} #{ary[idx].val}\n" if ary[idx].checked cnt_true += 1 else cnt_false += 1 end end puts "checked true = #{cnt_true}" puts "checked false = #{cnt_false}" よろしくお願いします。

    • ベストアンサー
    • Ruby
  • 【ruby】クラスCGIを改造したい

    #!/usr/local/bin/ruby require 'cgi' require 'kconv' headers={ "status"=>"OK", "type"=>"text/html; charset=utf-8" } cgi=CGI.new hoge=cgi['arg'] cgi.out(headers){Kconv.toutf8(hoge)} 上記はcgiはクエリパラメータargに与えた文字列がUTF-8で表示される 物の基本骨格として記しました。 実際に作りたい物は、もう少し複雑で、cgi.outのブロックに渡す部分 は、ケースにより複数あります。 そこで、毎回ブロックに渡す部分をKconv.toutf8でくくるのは、如何な ものかと思い、CGIクラスそのものを改造して、 cgi.out(headers){hoge} と記述しても、UTF-8で出力されるようにしたいのですが、やり方が解 りません。 CGIクラスのoutメソッドをオーバーライドするのかなぁ? と思うのですが、オーバーライドってやった事が無いので、 手がかりがつかめません。 お手ほどきの、よろしくお願いいたします。

    • ベストアンサー
    • Ruby

専門家に質問してみよう