8764


Javascriptを利用してフォームに設定する値を増やす事ができるようにしています。

[code]

    <form action="./" accept-charset="UTF-8" method="post">
      <input type="hidden" name="authenticity_token" value="略...">
      <input type="submit" name="commit" value="登録">
    
      <!-- 以下jsから追加されたデータ -->     
      <input type="hidden" name="items[0][name]" value="剣">
      <input type="hidden" name="items[0][info]" value="鉄の剣">
      <input type="hidden" name="items[1][name]" value="盾">
      <input type="hidden" name="items[1][info]" value="鉄の盾">
      <input type="hidden" name="items[2][name]" value="鎧">
      <input type="hidden" name="items[2][info]" value="鉄の鎧">
      <input type="hidden" name="items[3][name]" value="杖">
      <input type="hidden" name="items[3][info]" value="鉄の杖">
    </form>
    
[/code]

上記のようにJavascriptから追加された要素を送信するとRailsのparamでは以下の様な値を取得することができました。

[code]

    {
      "utf8" => "✓",
      "authenticity_token" => "略...",
      "commit" => "登録",
      "items" => {
        "0" => {
          "name"=>"剣",
          "info"=>"鉄の剣"
        },
        "1" => {
          "name"=>"盾",
          "info"=>"鉄の盾"
        },
        "2" => {
          "name"=>"鎧",
          "info"=>"鉄の鎧"
        },
        "3" => {
          "name"=>"杖",
          "info"=>"鉄の杖"
        }
      }
    }
    
[/code]

配列のインデックスが文字列として認識されてしまい、期待していたデータ構造の`[]（Array）`が`{}（Hash）`になってしまっているのが原因だと思うのですが。とりあえず無視して以下のコードを実行します。

[code]

    params[:items].each do |v|
      logger.debug v
    end
    
[/code]

すると、何故かvの値が以下のような配列に変換されて何故かindexが付いているような構造になってしまいます。

[code]

    => ["0", {"name"=>"剣", "info"=>"鉄の剣"}]
    => ["1", {"name"=>"盾", "info"=>"鉄の盾"}]
    => ["2", {"name"=>"鎧", "info"=>"鉄の鎧"}]
    => ["3", {"name"=>"杖", "info"=>"鉄の杖"}]
    
[/code]

これはいったいどういうことなのでしょうか？

そして、formから送信された配列の箇所をparamで配列として受け取り、`params[:items].each`のブロック内で`{"name"=>"値",
"info"=>"値"}`の形式のHashを取得するにはどうすればよいのでしょうか。

よろしくお願いいたしますm(_ _)m


CC BY-SA 3.0
2015-04-04T06:50:49.600
8753
2015-04-04T09:50:40.227
2015-04-04T06:59:27.413
5840
5840
question
ruby-on-rails
Rails4でformから配列データを受け取った際のparamsのデータ構造がArrayにならない。


> indexが付いているような構造

`Hash#each` はkeyとvalueを引数にブロックを評価するので、そういうことになります。

<http://docs.ruby-lang.org/ja/2.0.0/method/Hash/i/each.html>

> formから送信された配列の箇所をparamで配列として受け取り

配列の添え字として不適切なキーが混ざったときのことを考えると、「キーが明示されたら常にHashとして扱う」というルールの方が明確ですから、Railsもそういう仕様なのかなと。

上記ヘルプにもありますが、2引数を受け取るようにすると簡単です。もしくは [`Hash#values`](http://docs.ruby-
lang.org/ja/2.1.0/method/Hash/i/values.html)。

[code]

    params[:items].each do |k,v|
        logger.debug v
    end
    
[/code]

ただ、添え字順にしたいならソートした方がいいでしょう。

[code]

    params[:items].sort {|a,b| a[0].to_i <=> b[0].to_i }.each do |k,v|
        logger.debug v
    end
    
[/code]

飛び飛びの添え字を維持したいなら配列を作っておいて入れるとか。

[code]

    tmp = []
    params[:items].each {|k,v| tmp[k.to_i] = v }
    tmp.each do |v|
        logger.debug v
    end
    
[/code]

あとは、`name="items[name][]"` といった形で別々の配列で受け取り、あとでzipするという方法もおもしろいですね。

[html - Rails params should read an array - Stack
Overflow](https://stackoverflow.com/a/19980312/2818869)


CC BY-SA 3.0
2015-04-04T09:50:40.227
8764
2015-04-04T09:50:40.227
2017-05-23T12:38:55.250
-1
8000
8753
answer