I have a condition where i need to pass a parameter as an array of hashes which looks like this:
The following is the Rack::Test post method for API call.
post "#{url}.json",
:api_key => application.key,
:data => [{"Company"=>"Apple,Inc","Website"=>"Apple.com"},{"Company"=>"Google","Website"=>"google.com"}],
:run => { :title => "The First Run" }
And this is the log of the rails app.
Parameters: {"api_key"=>"6a9acb84d0ea625be75e70a1e04d26360606ca5b", "data"=>[{"Company"=>"Apple,Inc", "Website"=>"Apple.com"}, {"Company"=>"Google", "Website"=>"google.com"}], "run"=>{"title"=>"The First Run"}, "line_id"=>"4e018e2c55112729bd00000a"}
Now, this is the RestClient post method I’m using to call the API.
RestClient.post("/lines/#{@line.id}/runs.json", {:run => {:title => @title}, @param_for_input => @param_data})
And this is the log of the rails app.
Parameters: {"run"=>{"title"=>"run name"}, "data"=>{"Company"=>"Google", "Website"=>"google.com"}, "api_key"=>"f488a62d0307e79ec4f1e6131fa220be47e83d44", "line_id"=>"4e018a505511271f82000144"}
The difference is in the data parameter.
When sending with Rack::Test method, the data is passed as "data"=>[{"Company"=>"Apple,Inc", "Website"=>"Apple.com"}, {"Company"=>"Google", "Website"=>"google.com"}]
but via RestClient way, the parameter data array is stripped out and only the last hash is passed as "data"=>{"Company"=>"Google", "Website"=>"google.com"}
Why the RestClient is stripping out the array of hashes to just a last hash of the array?
I suspect it’s to do with differences in how they convert a hash into params. Rack::Test will probably be using Hash#to_param, which gives the following results:
This is the troublesome part:
data[][Company]=Apple,Inc&data[][Website]=Apple.com&data[][Company]=Google&data[][Website]=google.com
The rails uri parser has to read this and turn it back into a hash. In my opinion putting an array of hashes into your params is asking for trouble as it creates a string, like the above, which is fundamentally difficult to parse. For example, presented with these two params
The parser may decide that both of them are describing the Company variable in the first hash in the array called “data”, and so overwrite the first with the second, which is what’s happening with you.
It sounds like your problem is at the generation stage rather than the intepretation stage, but still, i would try to create a cleaner scheme for your parameters, in which arrays are only ever used as the final part of the param name, (ie use a hash instead of an array to hold company data) and you instead insert some unique keys to differentiate the company hashes from each other. Something like this:
1 and 2 could be the actual ids of some company record, or they could just be some numbers you put in to make unique keys, which are chucked away at the other end. This will generate params like this:
Which are now in no danger of overwriting each other.
In your subsequent controller action, it’s just a change from doing this:
to