RubyにおけるPOSTデータの処理方法は?

このQ&Aのポイント
  • Rubyを使用してPOSTされたデータを処理する方法について教えてください。
  • Rails上でPOSTされたパラメータを受け取り、オブジェクトとして保存する方法を教えてください。
  • paramsが配列の可能性がある上、a, b, cのキーが存在するか不明な場合のデータ処理方法についてアドバイスをお願いします。
回答を見る
  • ベストアンサー

rubyにおけるPOSTされたデータの処理について

言語はRubyです。 場面としては、railsにPOSTされたパラメータを受け取ってオブジェクトであるdetaを保存しているところです。 #case1 #params = {'a' => 1, 'b'=> 2 ,'c' => 3} #case2 #params = [{'a' => 1, 'b'=> 2 ,'c' => 3}, {'a' => 4, 'c' => 5}] if params.kind_of?(Array) params.length.times do |i| @deta.new if a = params[i]['a'] end if b = params[i]['b'] end if c = params[i]['c'] end @deta.save! end else @deta.new if a = params['a'] end if b = params['b'] end if c = params['c'] end @deta.save! end paramsが配列の可能性がある上、 paramsのハッシュである a, b, c のキーが毎回存在するかわからないので、 if文で例外がでないようにチェックしています。 自分で書いてて冗長な感じがして気持ち悪いです。 なにかよい方法があれば、教えてください。 よろしくお願いします。

  • Ruby
  • 回答数3
  • ありがとう数4

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

  • ベストアンサー
  • notnot
  • ベストアンサー率47% (4847/10260)
回答No.3

ああ、なるほど。そういう勘違いですね。Hash#[]で例外は発生しません。 その前にまず、 >代入された値、代入できなければnilが返ります。 代入演算子で、「代入できない」のはあり得ません。nilが返るのはnilを代入したときです。 >a = params[i]['a'] >この処理でもし、" params[i]['a'] "が存在せず、nilが代入されれば、 例外が発生しプログラムが停止すると思いますが、 しません。場合分けすると、 (1) 配列paramsのi番目がハッシュとして存在する場合 (2) 配列paramsのi番目がハッシュ以外で存在する場合 (3) 配列paramsのi番目が存在しない場合 ですが、今回は(2)(3)のケースは想定されていないと思いますので省きます。 (1)をさらに場合分けすると、 (1-1) そのハッシュにキー'a'が存在する場合   →対応する値が返る (1-2) そのハッシュにキー'a'が存在しない場合   →この場合はハッシュ生成時にデフォルト値を指定していないのでnilが返る どちらも例外は発生しません。 (1-2)の場合に、値の取り出しに[]メソッドでなく、fetch()メソッドを使うとキー無しの例外が発生します。この場合、 a=params[i].fetch('a') と書こうが、 if a=params[i].fetch('a') end と書こうが同じです。 if の条件部分は必ず実行されます(実行しないと値がわからないので)。 if の条件部分の値がnilやfalseだとthen部分が実行されません。 ハッシュからの値の取り出しは普通は[]を使い、キー無しの時に意図的に例外を発生させたいときにfetch()を使います。また、ロジックでキー有りキー無しで違う処理をさせたいときは、key?()を使います。 a = {} p a['X'] b = Hash.new("default value") p b['X'] p b.fetch('X')

j138cm
質問者

お礼

>>a = params[i]['a'] >>この処理でもし、" params[i]['a'] "が存在せず、nilが代入されれば、 >>例外が発生しプログラムが停止すると思いますが、 >しません。場合分けすると、 さっそく試してみました。確かに例外が発生しませんでした。 私の完全な勘違いのようです。ご指摘ありがとうございます。 今回は、例外を意図的に発生させたいわけではないので、 fetchを使う必要はないです。 ながながとおつきあいいただきありがとうございました。 回りくどいコードを書かないよう努力します。

その他の回答 (2)

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

>>>if分の部分で何がしたいのかわかりません。 >ifの条件式の部分で行いたい処理を行い、代入ができない場合、 >つまり返り値がnilである場合を、if側で処理して例外が発生しないようにしてます。 やっぱりわかりません。 if a = params[i]['a'] end のthen部分に何も書いてないのですが?何も書かないと、 a = params[i]['a'] と同じですよ。

j138cm
質問者

補足

a = params[i]['a'] の式に返り値があるのはご存知ですか? 代入された値、代入できなければnilが返ります。 また、ifの条件式ではfalseはもちろんですが、nilを受け取っても実行されません。 逆に言うとfalseやnil以外では、実行されるということです。 a = params[i]['a'] この処理でもし、" params[i]['a'] "が存在せず、nilが代入されれば、 例外が発生しプログラムが停止すると思いますが、 if a = params[i]['a'] end だと、ifの条件式でnilを受け取り、例外が発生しません。 条件式の部分で、代入がちゃんと行われているので、thenの部分で処理する必要もありません。 rubyを触り始めて1週間程度ということもあり、私自身知識が浅いのと、 例外処理のやり方を調べるのがめんどくさいため、このような変態的な処理になっています。 余談ですが、 この方法は、C言語で似たようなことをしたことがあり、rubyでもやってみたらできたという感じです。 こういう変則的な書き方は、この本が参考になりました。 Short Coding ~職人達の技法~ http://www.amazon.co.jp/exec/obidos/ASIN/4839925232/

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

if分の部分で何がしたいのかわかりません。 キーが存在するかどうかは、if params.key?('a')のようにして調べます。 case1,2の統合は、下記のようにすれば出来ます。 [params].flatten.each do |prms|  if a = prms['a'] ・・・ end

j138cm
質問者

補足

>>if分の部分で何がしたいのかわかりません。 ifの条件式の部分で行いたい処理を行い、代入ができない場合、 つまり返り値がnilである場合を、if側で処理して例外が発生しないようにしてます。 存在するか確認して、代入するよりは文字数減るかもしれませんが、 わかりにくいですね。 普通に if params.key?('a') で処理します。 [params].flatten.each do |prms|  if a = prms['a'] ・・・ end flatten.eachは初めて知りました。 使わせていただきます。 返答が遅くなりましたが、ありがとうございました。

関連するQ&A

  • rubyにてデータが変更されているかチェックしたいのですが

    現在Ruby on Railsでプログラムを作成していますが、よくわかりません。周りに聞ける人もいないので、よろしければどなたか教えてください。 ユーザーファイルのパスワードが変更されていたら changepassdateの内容を変更して、 変更されていなかったらchangepassdateの内容はそのままにするという内容のプログラムを作りたいです。 現在の内容だと、パスワードを変更しないでもchangepassdateの内容が変わってしまいます。 どうしたらこの問題が解決されるでしょうか? お手数おかけして申し訳ありませんが、どなたか教えてください。お願いします。 def update @user = User.find(params[:id]) if @user.password =! params[:password] t = DateTime.now @user.changepassdate = t + 1 end respond_to do |format| if @user.update_attributes(params[:user]) flash[:notice] = 'ユーザー情報が更新されました。' format.html { redirect_to(@user) } format.xml { head :ok } else format.html { render :action => "edit" } format.xml { render :xml => @user.errors, :status => :unprocessable_entity } end end end

  • Rubyのパスワード変更画面について

    rubyでのプログラム作成についての質問です。 パスワードの変更画面を作成したいのですが、作り方がよくわかりません。 会社でrubyを使用したプログラム作成を命じられましたが、社内にrubyを使用できる人がいないので質問できず困っています。 パスワードを変更する際に、パスワードの入力と確認用パスワードの入力をして、 双方が一致したらパスワードを変更、双方が不一致ならエラーメッセージを表示するようにしたいのですが、どうしたらいいのでしょうか。 現在、コントローラ内は以下のようになっています。 def new @user = User.new respond_to do |format| format.html # new.html.erb format.xml { render :xml => @user } end end def create @user = User.new(params[:user]) if(params[:password]!=params[:password_confirm]) ←ここでパスワードと確認用パスワードをチェック? flash[:notice] = 'パスワードが間違っています。' redirect_to:back return end respond_to do |format| if @user.save flash[:notice] = 'User was successfully created.' format.html { redirect_to(@user) } format.xml { render :xml => @user, :status => :created, :location => @user } else format.html { render :action => "new" } format.xml { render :xml => @user.errors, :status => :unprocessable_entity } end end end パスワードチェックをしているつもりはあるのですが、パスワードと確認用パスワードが違っていても現在は登録処理がされてしまいます。どうしたらいいのでしょうか。 大変困っているのでどなたか教えてください。

  • ruby forkについて教えて下さい

    親プロで用意した配列の中の要素を一つづつ子プロでputsした後、最後一回、親プロで生成した子プロのPIDを確認したいです。 こんなふうに書いてみました。 #!/usr/bin/ruby table=%w(a b c d) array=[] while i=table.pop do if pid=fork then array.push pid puts pid break if table.size > 0 p array else puts i end end 実行すると、以下のような結果になりました。 $9200 c 9201 b 9202 [9202] a $ PIDが一つしか得られてません。 どうしたらよいでしょうか? ご教授の程、宜しくお願いいたします。 rubyは 1.8.7 を使ってます。 以上、宜しくお願いいたします。

    • ベストアンサー
    • Ruby
  • ruby serverが起動出来なく困ってます。

    下記のような状態になってしまいサーバが動いてくれません。 エラー文を見るとファイルかディレクトリが存在しないとの事だと思いますが 色々調べてみましたが同じような状態からの解決法が見つからなかった為こちらに質問させて頂きました。 C:\ruby\work>rails new sample create create README create Rakefile create config.ru ----------中略------------ create public/javascripts/prototype.js create public/javascripts/rails.js C:\ruby\work>cd sample C:\ruby\work\sample>ruby script/server ruby: No such file or directory -- script/server (LoadError) ruby のバージョンは1.9.2p180、gemのバージョンが1.6.2です。 環境設定でどこかにミスがあると思って念の為、再度インストールし直しでやってみましたが全く同じで変わりませんでした。 追記、数年前だとC:\>rails sampleと書くだけでファイルが生成されたのですが、 今日試してみたところC:\>rails new sampleとnewを付けないとファイルが作成されない事がわかりました。 サーバ立ち上げの記述も数年前とは違うという事でしょうか? どなたか教えて下さい。

    • ベストアンサー
    • Ruby
  • ruby on railsのscaffoldで配列を定義するには

    ruby on railsのscaffoldで配列を定義するには rails2.3での質問です。 通常、scaffoldで >ruby script/generate migration TestData name:string id:integer のようにデータ構造を指定すると思うのですが、この時に配列を定義するには どうしたら良いのでしょうか? 通常の(C言語のような)配列でもハッシュでも構いません。 よろしくお願いいたします。

    • ベストアンサー
    • Ruby
  • rubyの繰り返し処理の仕方を教えてください

    rubyの繰り返し処理の仕方がわかりません rubyを使ってのプログラムを勉強してます。最終的には表の書き換えをする プログラムがつくりたいのですが最初でコケましたruby イテレーター ネストで検索してもわからなかったので質問します。どなたか お時間あれ ば教えてください。 お店の番号SA003とSA005を次の "SA001",0,10,20,10 "SA003",0,10,20,20 "SA004",0,10,20,100 "SA005",0,10,20,50 の表なかから探すプログラムを作成しようとしましたが。 繰り返し処理の仕方がわかりません変数のスコープが外れていると思いますし dataの行数は4とはかぎらないので 4.times は使えないのはわかるのですが とりあえずイメージ的に描いたプログラムです。よろしくお願いいたします。 ====testimage.rb======== class Shop_number def initialize @mise=["SA003","SA005"] end def tenposuu() return @mise.size end def tenpo_no(n) return @mise[n] end end data =[["SA001",0,10,20,10],["SA003",0,10,20,20],["SA004",0,10,20,100],["SA005",0,10,20,50]] obj = Shop_number.new obj.tenposuu.times do |i| 4.times do |j| if data[j][0]=~/{obj.tenpo_no(i)}/ then puts data end end ======================= =>["SA003",0,10,20,20] =>["SA005",0,10,20,50] と出したいのですが・・・

    • ベストアンサー
    • Ruby
  • どこが間違いか分かりません。(Ruby)

    Rubyを使ったプログラムが巧く行かないのですが、どこでエラーが出ているのか分かりません。どなたか何が原因でエラーが起こったのか教えて頂けないでしょうか。 以下ソースコードです。 class SolitaireCipher $deck = (1..52).to_a+['A','B'] def solitaire(count) key_stream = [] until key_stream.size == count a = $deck.index("A") $deck.delete("A") if a == 53 a = 0 else a += 1 end $deck.insert(a,"A") b = $deck.index("B") $deck.delete("B") if b == 52 b = 1 elsif b == 53 b = 2 else b = b+2 end $deck.insert(b,"B") a1 = $deck[0..b-1] a2 = $deck[b..a] a3 = $deck[a+1..53] $deck = a3+a2+a1 if $deck[53] == 'A' t1 = 27 elsif $deck[53] == 'B' t1 = 27 else t1 = $deck[53] end a4 = $deck[0..t1-1] $deck = ($deck-a4).insert(52,a4).flatten! i = $deck[0].to_i key = $deck[i] key_stream << key end key_stream_s = key_stream.join n = 5 while n < key_stream_s.size key_stream_s[n,0] = " " n += 6 end key_stream = key_stream_s.split(" ") end end s = SolitaireCipher.new p s.solitaire(20) このプログラムを実行したときに、どういう訳かuntil文の中で毎回$deckの値が初期化されるようです。 そのため結果が以下のようになります。 ["44444", "44444", "44444", "44444"] 初心者プログラマーなので何か初歩的な間違いをしているのかもしれません。 どなたかエラーの原因を教えて頂けないでしょうか。 読みにくいプログラムではありますがよろしくおねがいします。

  • Ruby on Rails に関する質問です。

    Ruby on Rails でデータベースにあいまい検索を複数条件でかけたいのですが、どのようにしたらよいのでしょうか?? def find   @bookinfo= Bookinfo.find(:all, :conditions => ["title like ?" => ["author like ?", "%#{params[:key]}%"]]) render :action => 'result.html.erb' end このような感じで複数のあいまい検索をかけたいのですがどのようにすればよいのか教えてください。 お願いします。SQLite3を使用しています。

    • ベストアンサー
    • Ruby
  • Ruby on Railsでデータベースに接続できない。

    Ruby on Railsでデータベースに接続できない。 『RailsによるアジャイルWebアプリケーション開発(第3版)』 http://www.amazon.co.jp/Rails%E3%81%AB%E3%82%88%E3%82%8B%E3%82%A2%E3%82%B8%E3%83%A3%E3%82%A4%E3%83%ABWeb%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E9%96%8B%E7%99%BA-Sam-Ruby/dp/4274067858/ref=sr_1_1?ie=UTF8&s=books&qid=1279209371&sr=8-1 という本でRuby on Railsの勉強をしています。現在、「第10章チェックアウト」の136ページあたりで行き詰っています。 ActiveRecord::AssociationTypeMismatch in StoreController#save_orderのメッセージが表示されていますが、どうやらデータベースに接続できていないようです。 configのdatabase.yml等を色々試行錯誤してみたり、色々ググってみたりしましたが、解決できませんでした。 どうやったらデータベースに接続できるのでしょうか。恐らくInstantRails-2.0に予め入っているMySQLやApacheと別々に入れたMySQLやApacheと競合しているからでしょうか。InstantRails-2.0の入っているMySQLやApacheは停止しています。 また、別々に入れたMySQLの方にはマイグレーション(?)で問題なくデータベースやテーブルが作成されています。なのにデータベースに接続できていないようです。 もう一つ、Ruby on Railsについて文字コードはcontrollers,helpers,models,views等に入っているファイルは全てutf-8にしなければならないでしょうか。何かWindowsでRuby on railsを開発するとコマンドプロンプトの関係でShift-JISに依存しているような気がします。

    • ベストアンサー
    • Ruby
  • rubyのプログラムについて

    rubyのプログラムで2~1000までの素数を列挙のものなんですがどこか違ってますか汗 考えたんですがよくわからなくて汗すみませんどなたかお願いします i=2 print "素数は\n" while i<=1000 do warukazu=2 flag=0 while warukazu<i do if i%warukazu==0 then flag=flag+1 warukazu=warukazu+1 else warukazu=warukazu+1 end end if (flag==0) then print i print"\n" end i=i+1 end

専門家に質問してみよう