21

Submitting a class roster. Adding 3 students at once. Each student has first, last, age.

Question: How can we get all of the students in an array of arrays?

students[0] => Array (
  ["first"] => "first name for 0",
  ["last"] => "last name for 0",
  ["age"] => "age for 0"
),
students[1] => Array (
  ["first"] => "first name for 1",
  ["last"] => "last name for 1",
  ["age"] => "age for 1"
), 
...  

Details
For one student:

<input type="text" name="first">  
<input type="text" name="last">  
<input type="text" name="age">  

We can return multiple students in separate arrays like this:

<input type="text" name="students[first][]">  
<input type="text" name="students[last][]">  
<input type="text" name="students[age][]">  

which returns an array of firsts, lasts and ages

students["first"] = [array of first names]
students["last"] = [array of last names]
students["age"] = [array of ages]  

Theoretically we can get all the info for a student by accessing the same index (say "3" for each array).

We do not want to programatically add an index in the form.
Do not want:

<input type="text" name="students[hardcoded_index][first]">  
<input type="text" name="students[hardcoded_index][last]">  
<input type="text" name="students[hardcoded_index][age]">  

If for any reason it matters, we are using Rails for views but can use form helpers or HTML.

csi
  • 8,059
  • 8
  • 55
  • 78

2 Answers2

28

tl;dr: Add empty brackets ([]) after students to the input names.

Fiddling with Rack::Utils.parse_nested_query it seems you can get the payload you want like this:

<!-- first student -->
<input type="text" name="students[][first]">
<input type="text" name="students[][last]">
<input type="text" name="students[][age]">

<!-- second student -->
<input type="text" name="students[][first]">
<input type="text" name="students[][last]">
<input type="text" name="students[][age]">

Note the empty brackets ([]) after students. This tells Rack you want the students param to be an array. Subsequent params encountered (with the same name) will start a new element.

POST /myroute?students[][first]=foo&students[][last]=bar&students[][age]=21&students[][first]=baz&students[][last]=qux&students[][age]=19

Gets parsed like this:

{"students" => [
  {
    "first" => "foo",
     "last" => "bar",
      "age" => "21"
  },
  {
    "first" => "baz",
     "last" => "qux",
      "age" => "19"
  }
]}

Further reading: http://codefol.io/posts/How-Does-Rack-Parse-Query-Params-With-parse-nested-query

messanjah
  • 7,288
  • 4
  • 23
  • 34
  • I don't know what Flask is, but probably not. This answer is specific to Ruby on Rails. – messanjah Mar 19 '18 at 13:49
  • I am using Rails4. This approach made the HTTP POST request correctly with all the students info (as i confirmed from the chrome network inspector). But inside the `controller.create` method (using binding.pry), when i see `params` it shows an array of the students but contains ONLY one hash in it - only the last student's hash - the previous students are missing inside the params. What am i doing wrong here? – Rakib Feb 01 '19 at 17:44
  • For those using Django & DRF, the format required is `students[0]first` (no dot, unique, specified indexes) as I finally found here: https://stackoverflow.com/a/57013811/3507333 – madannes Oct 01 '20 at 15:13
14

I know the question is old , but I would like to add my experiences also for future readers.

For those of you who want to process the data in a PHP enviroment , @messanjah's method won't work ,

The methods for parsing data like the built-in serializeArray or serialize are not parsing it as expected either.

This is what I tried so far ...

  • students[name]
  • students[][name] - Very Strange since it was meant to automatically index the array
  • students[name][]

Neither of them worked, but this students[<hardcoded-index>][name] worked for PHP ,

I know that although the question is against this method , but it will be useful for PHP users who will land here in the nearby future as the asker needed it for Ruby On Rails.

The method you choose to hard code the indexes is upto you , you can use a cleaner method by using javascript or you can manually hard code them initially in your form element.

Cheers

Fahad
  • 1,713
  • 20
  • 25
  • This is very interesting. Does this imply the difficulty surrounding this particular task is not a rails specific thing, but a HTML thing? – stevec Aug 22 '20 at 15:04
  • 1
    Exactly! - but I believe the problem is already solved by now or at least a workaround is available more prettier than this one :D – Fahad Aug 23 '20 at 17:20
  • i hope so, it’s a little confusing for me, but still a great help. If you know I’d any newer techniques please share the link – stevec Aug 23 '20 at 17:23