0

I'm witnessing an odd behavior in Rails, when sending a post request, with the following body: enter image description here

If you check is a Hash (converted to JSON when sending). But ODDLY when being read by params in controller, is recognized like this:

enter image description here

If you check carefully, the attributes of :first_name and :email are moved to the previous item in the array.

I'd thought if you have an array with certain attributes on the first item, but some different attributes on the following items, the array would be respecting the positions of which the attributes are set for.

I know most likely the answer would be "just put a nil or empty value of those attributes on the first item of the array", but I'm more interested in the reason of why this is happening.

Thank you.

UPDATE

Thanks to a question, I replicated the scenario form a browser (I was originally doing the request from the test feature of rails), and checking the Network from the browser, this is what is being sent:

{
  "name": "un nombre",
  "team_members": [
    {
      "user_id": 1,
      "team_member_role_id": 4
    },
    {
      "email": "cpamerica@avengers.com",
      "first_name": "Cap America",
      "team_member_role_id": 4,
      "admin": true
    },
    {
      "email": "hulk@avenrgers.com",
      "first_name": "Bruce Banner",
      "team_member_role_id": 1,
      "admin": false
    },
    {
      "email": "ironman@avengers.com",
      "first_name": "Tony Stark",
      "team_member_role_id": 1,
      "admin": false
    },
    {
      "email": "thor@avengers.com",
      "first_name": "Thor Hijo de Odín",
      "team_member_role_id": 2,
      "admin": false
    }
  ]
}

And it works. So I focused on how I was sending the info from the test environment, this is the actual code:

team        = {
    :name         => 'un nombre',
    :team_members => [
        {
            :user_id             => 1,
            :team_member_role_id => TeamMemberRole.role_communicator_id
        },
        {
            :email               => 'cpamerica@avengers.com',
            :first_name          => 'Cap America',
            :team_member_role_id => TeamMemberRole.role_communicator_id,
            :admin               => true
        },
        {
            :email               => 'hulk@avenrgers.com',
            :first_name          => 'Bruce Banner',
            :team_member_role_id => TeamMemberRole.role_visionary_id,
            :admin               => false
        },
        {
            :email               => 'ironman@avengers.com',
            :first_name          => 'Tony Stark',
            :team_member_role_id => TeamMemberRole.role_visionary_id,
            :admin               => false
        },
        {
            :email               => 'thor@avengers.com',
            :first_name          => 'Thor Hijo de Odín',
            :team_member_role_id => TeamMemberRole.role_developer_id,
            :admin               => false
        }
    ]
}
post create_team_path, :team => team, :format => :json

And what is being read in the controller by request.raw, this is what is getting (using the debugger):

team[name]=un+nombre&
team[team_members][][user_id]=1&
team[team_members][][team_member_role_id]=4&
team[team_members][][email]=cpamerica%40avengers.com&
team[team_members][][first_name]=Cap+America&
team[team_members][][team_member_role_id]=4&
team[team_members][][admin]=true&
team[team_members][][email]=hulk%40avenrgers.com&
team[team_members][][first_name]=Bruce+Banner&
team[team_members][][team_member_role_id]=1&
team[team_members][][admin]=false&
team[team_members][][email]=ironman%40avengers.com&
team[team_members][][first_name]=Tony+Stark&
team[team_members][][team_member_role_id]=1&
team[team_members][][admin]=false&
team[team_members][][email]=thor%40avengers.com&
team[team_members][][first_name]=Thor+Hijo+de+Od%C3%ADn&
team[team_members][][team_member_role_id]=2&
team[team_members][][admin]=false&
format=json

Any idea on why the index of each team_member is missing? Am I sending the array wrong?

unmultimedio
  • 1,224
  • 2
  • 13
  • 39
  • Have you checked what is actually being sent on the wire (e.g. use chrome's network inspector) ? – Frederick Cheung Jun 03 '16 at 16:38
  • @FrederickCheung I'm making the request using the testing framework of Rails, not the browser. So I wrote `post create_team_path, { :format => :json, :team => team }` where `team` is the Hash. – unmultimedio Jun 03 '16 at 16:52
  • @FrederickCheung updates on the new approach of the question – unmultimedio Jun 03 '16 at 17:46
  • Looks like the test framework's post method is serialising the request parameters as if it were normal, non JSON data and that does have limitations when arrays and hashes are combined in some ways. Not sure how you get it to do an actual JSON post – Frederick Cheung Jun 03 '16 at 18:15

1 Answers1

1

To send an acceptable json request you need to send as a formed String instead the hash, also add the headers your code must look something like this:

post create_team_path, {:team => team}.to_json, 'CONTENT_TYPE' => 'application/json;charset=utf-8'

Note the problem is within the parser hash to form-request not adding the index of each object

Source: How to post JSON data in rails 3 functional test

Community
  • 1
  • 1
DFOXpro
  • 303
  • 1
  • 13