Rspec-rails: RSpec API request merges array objects

Created on 4 Apr 2014  ·  11Comments  ·  Source: rspec/rspec-rails

I am not sure if it's exactly RSpec issue, but when I, for example, have the following code in my RSpec API test:

let(:params) {
  { 'fruits' =>
        [ { apples: [{ apple_field: '1' }, { apple_field: '2' }],
           oranges: [{ orange_field: '3' }, { orange_field: '4' }]
         },
         { apples: [{ apple_field: '5' }, { apple_field: '6' }],
           oranges: [{ orange_field: '7' }, { orange_field: '8' }]
         }]
  }
}

it do
  post '/api/v1/fruits', params
  #expect blabla here
end

My controller gets the params looking like this:

{ 'fruits' =>
    [ { apples: [{ apple_field: '1' }, { apple_field: '2' }, { apple_field: '5' }, { apple_field: '6' }],
        oranges: [{ orange_field: '3' }, { orange_field: '4' }, { orange_field: '7' }, { orange_field: '8' }]
      }
    ]
}

So it basically merges them all. When I add some other key to these objects like this:

let(:params) {
  { 'fruits' =>
        [ { some_key: 'some_value', apples: [{ apple_field: '1' }, { apple_field: '2' }],
           oranges: [{ orange_field: '3' }, { orange_field: '4' }]
         },
         { some_key: 'whatever', apples: [{ apple_field: '5' }, { apple_field: '6' }],
           oranges: [{ orange_field: '7' }, { orange_field: '8' }]
         }]
  }
}

They are handled properly and do not get merged. I am using edge Rails and RSpec. Advice please?

Needs reproduction case

Most helpful comment

I had a similar issue, but with a bit different type of "merging". I had been sending params like this:

put 'https://localhost:3000/api', params: {
  attributes: [
    { id: social_account.id, name: 'User' },
    { network: 'local', name: 'Another User', link: 'https://localhost:3000/another_user', main: true }
  ]
}

But after request was made params came to the server in the such form:

{
  attributes: [
    { id: social_account.id, name: 'User', network: 'local' },
    { name: 'Another User', link: 'https://localhost:3000/another_user', main: true }
  ]
}

And, as you understand, that led to the updating of the wrong field for the first user, and not updating the corresponding field for another user.

WHAT ACTUALLY HELPED ME!!!

I just added as: :json to the put request and it fixed the problem:

put 'https://localhost:3000/api', params: {...}, as: :json

🌈🌈🌈

All 11 comments

@Konnigun I believe this is a Rails issue. You can reproduce this in a normal form by manually creating your hashes and arrays.

Here is the equivalent where it merges everything:

  <%= hidden_field_tag "fruits[][apples][][apple_field]", "1" %>
  <%= hidden_field_tag "fruits[][apples][][apple_field]", "2" %>
  <%= hidden_field_tag "fruits[][oranges][][orange_field]", "3" %>
  <%= hidden_field_tag "fruits[][oranges][][orange_field]", "4" %>

  <%= hidden_field_tag "fruits[][apples][][apple_field]", "5" %>
  <%= hidden_field_tag "fruits[][apples][][apple_field]", "6" %>
  <%= hidden_field_tag "fruits[][oranges][][orange_field]", "7" %>
  <%= hidden_field_tag "fruits[][oranges][][orange_field]", "8" %>
Parameters: {
  "utf8"=>"✓",
  "authenticity_token"=>"RM7m4POPcnV5E5qRPSts1ax+/34rp/073A/2NykwErQ=",
  "fruits"=> [{
    "apples"=>[
      {"apple_field"=>"1"},
      {"apple_field"=>"2"},
      {"apple_field"=>"5"},
      {"apple_field"=>"6"}
    ],
    "oranges"=>[
      {"orange_field"=>"3"},
      {"orange_field"=>"4"},
      {"orange_field"=>"7"},
      {"orange_field"=>"8"}
    ]
  }]
}

And then where it does not merge them:

  <%= hidden_field_tag "fruits[][some_key]", "some_value" %>
  <%= hidden_field_tag "fruits[][apples][][apple_field]", "1" %>
  <%= hidden_field_tag "fruits[][apples][][apple_field]", "2" %>
  <%= hidden_field_tag "fruits[][oranges][][orange_field]", "3" %>
  <%= hidden_field_tag "fruits[][oranges][][orange_field]", "4" %>

  <%= hidden_field_tag "fruits[][some_key]", "whatever" %>
  <%= hidden_field_tag "fruits[][apples][][apple_field]", "5" %>
  <%= hidden_field_tag "fruits[][apples][][apple_field]", "6" %>
  <%= hidden_field_tag "fruits[][oranges][][orange_field]", "7" %>
  <%= hidden_field_tag "fruits[][oranges][][orange_field]", "8" %>
Parameters: {
  "utf8"=>"✓",
  "authenticity_token"=>"RM7m4POPcnV5E5qRPSts1ax+/34rp/073A/2NykwErQ=",
  "fruits"=>[
    {
      "some_key"=>"some_value",
      "apples"=>[{"apple_field"=>"1"}, {"apple_field"=>"2"}],
      "oranges"=>[{"orange_field"=>"3"}, {"orange_field"=>"4"}]
    },
    {
      "some_key"=>"whatever",
      "apples"=>[{"apple_field"=>"5"}, {"apple_field"=>"6"}],
      "oranges"=>[{"orange_field"=>"7"}, {"orange_field"=>"8"}]
    }
  ]
}

A quick test suggest mini test doesn't have this behaviour, so we should look into it.

@JonRowe do you want to take this one? If not, I'm happy to look into it.

I can't replicate this, can you gist a spec file and an empty controller to gist it against? I'm using https://gist.github.com/JonRowe/b025833cfdddd65e750e and can't reproduce this on RSpec 2.14 or RSpec 3, against Rails 3.2.17 or 4.1.0.rc1

I have the same issue
I try send request via rspec, and got them merged...

If you can provide a reproducible isolated example for s @cybdoom that would be a great help

Hi! Thank You for quick response!
Here is the link to my repo on bitbucket (I can not share it as public due
to commercial reasons): https://bitbucket.org/trackerrails
Give me Your bitbucket account if exists and I'll add You to collaborators!
The mentioned spec is app/specs/requests/tracks_spec.rb L:68

Thank You in advantage!

Eugene Narovlyansky, Software Developer

чт, 7 мая 2015 г. в 1:21, Jon Rowe [email protected]:

If you can provide a reproducible isolated example for s @cybdoom
https://github.com/cybdoom that would be a great help


Reply to this email directly or view it on GitHub
https://github.com/rspec/rspec-rails/issues/985#issuecomment-99628593.

Mistyped in the link, here it is: https://bitbucket.org/trackerrails
/trackerrails

пт, 8 мая 2015 г. в 18:23, Наровлянский Евгений [email protected]:

Hi! Thank You for quick response!
Here is the link to my repo on bitbucket (I can not share it as public due
to commercial reasons): https://bitbucket.org/trackerrails
Give me Your bitbucket account if exists and I'll add You to collaborators!
The mentioned spec is app/specs/requests/tracks_spec.rb L:68

Thank You in advantage!

Eugene Narovlyansky, Software Developer

чт, 7 мая 2015 г. в 1:21, Jon Rowe [email protected]:

If you can provide a reproducible isolated example for s @cybdoom

https://github.com/cybdoom that would be a great help


Reply to this email directly or view it on GitHub
https://github.com/rspec/rspec-rails/issues/985#issuecomment-99628593.

hi @cybdoom none of us can really be added to a private repo for all sorts of horrifying intellectual property and warranty reasons. We need you to either provide a new repo with a reproduction case, or we won't be able to help.

Could you please take the following steps:

  1. initialise a new repo with the correct version of rails
  2. commit just the rails new stuff
  3. do a second commit which includes all of your changes.

Thanks ^_^

Hi, all. I just encountered this problem and made a public repo with an example: https://github.com/meaton-potatoes/rspec-params-bug

I had a similar issue, but with a bit different type of "merging". I had been sending params like this:

put 'https://localhost:3000/api', params: {
  attributes: [
    { id: social_account.id, name: 'User' },
    { network: 'local', name: 'Another User', link: 'https://localhost:3000/another_user', main: true }
  ]
}

But after request was made params came to the server in the such form:

{
  attributes: [
    { id: social_account.id, name: 'User', network: 'local' },
    { name: 'Another User', link: 'https://localhost:3000/another_user', main: true }
  ]
}

And, as you understand, that led to the updating of the wrong field for the first user, and not updating the corresponding field for another user.

WHAT ACTUALLY HELPED ME!!!

I just added as: :json to the put request and it fixed the problem:

put 'https://localhost:3000/api', params: {...}, as: :json

🌈🌈🌈

Was this page helpful?
0 / 5 - 0 ratings