RestClient удаляет массив параметров хэшей только с последним хешем? - PullRequest
11 голосов
/ 22 июня 2011

У меня есть условие, когда мне нужно передать параметр в виде массива хэшей, который выглядит следующим образом:

Ниже приведен метод Rack :: Test post для вызова API.

post "#{url}.json",
:api_key => application.key,
:data => [{"Company"=>"Apple,Inc","Website"=>"Apple.com"},{"Company"=>"Google","Website"=>"google.com"}],
:run => { :title => "The First Run" }

И это журнал приложения rails.

Parameters: {"api_key"=>"6a9acb84d0ea625be75e70a1e04d26360606ca5b", "data"=>[{"Company"=>"Apple,Inc", "Website"=>"Apple.com"}, {"Company"=>"Google", "Website"=>"google.com"}], "run"=>{"title"=>"The First Run"}, "line_id"=>"4e018e2c55112729bd00000a"}

Теперь это метод публикации RestClient, который я использую для вызова API.

RestClient.post("/lines/#{@line.id}/runs.json", {:run => {:title => @title}, @param_for_input => @param_data})

И этоэто журнал приложения rails.

Parameters: {"run"=>{"title"=>"run name"}, "data"=>{"Company"=>"Google", "Website"=>"google.com"}, "api_key"=>"f488a62d0307e79ec4f1e6131fa220be47e83d44", "line_id"=>"4e018a505511271f82000144"}

Разница в параметре data.

При отправке с помощью метода Rack :: Test данные передаются как "data"=>[{"Company"=>"Apple,Inc", "Website"=>"Apple.com"}, {"Company"=>"Google", "Website"=>"google.com"}]

, но способом RestClient массив данных параметров удаляется, и только последний хэш передается как "data"=>{"Company"=>"Google", "Website"=>"google.com"}

Почему RestClient удаляет массив хэшей до последнего хэша массива?

Ответы [ 2 ]

19 голосов
/ 06 декабря 2011

Я столкнулся с той же проблемой с нашим приложением rails. Я нашел следующие обходные пути для работы с бэкэндом RestClient + Rails.

Rails ожидает данные [] [Company]. Используйте «data []» вместо «data» в качестве ключа. Например:

RestClient.post 'http://archive.greenviewdata.com/containers', { 
  :run => {:title => 'something'}, 
  'data[]' => [
    {"Company"=>"Apple,Inc","Website"=>"Apple.com"},
    {"Company"=>"Google","Website"=>"google.com"}
  ]
}

В нашем случае у нас был массив, вложенный в два уровня глубоко в хэш. Приведенный выше обходной путь не решает проблему из-за способа, которым RestClient форматирует параметры. Итак, если у вас есть массив, который вложен глубже, чем верхний уровень хэша, переданного RestClient, вы должны использовать следующий обходной путь:

RestClient.post 'http://archive.greenviewdata.com/containers', {
  :run => {:title => 'something'}, 
  :nested => {
    'data' => {
      '' => [
        {"Company"=>"Apple,Inc","Website"=>"Apple.com"},
        {"Company"=>"Google","Website"=>"google.com"}
      ]
    }
  }
}
14 голосов
/ 27 июня 2011

Я подозреваю, что это связано с различиями в том, как они конвертируют хэш в params. Rack :: Test, вероятно, будет использовать Hash # to_param, что даст следующие результаты:

> params = {:api_key => "12345", :data => [{"Company"=>"Apple,Inc","Website"=>"Apple.com"},{"Company"=>"Google","Website"=>"google.com"}], :run => { :title => "The First Run" }}

> paramstring = params.to_param
 => "api_key=12345&data%5B%5D%5BCompany%5D=Apple%2CInc&data%5B%5D%5BWebsite%5D=Apple.com&data%5B%5D%5BCompany%5D=Google&data%5B%5D%5BWebsite%5D=google.com&run%5Btitle%5D=The+First+Run" 

> URI.unescape(paramstring)
 => "api_key=12345&data[][Company]=Apple,Inc&data[][Website]=Apple.com&data[][Company]=Google&data[][Website]=google.com&run[title]=The+First+Run" 

Это неприятная часть:

данные [] [Компания] = яблоко, Inc и данные [] [Сайт] = Apple.com и данные [] [Компания] = Google и данные [] [Сайт] = google.com

Парсер rails uri должен прочитать это и превратить его обратно в хеш. По моему мнению, добавление массива хэшей в ваши параметры вызывает проблемы, так как создает строку, подобную приведенной выше, которую в принципе трудно разобрать. Например, представлены эти два параметра

data[][Company]=Apple,Inc
data[][Company]=Google

Парсер может решить, что они оба описывают переменную Company в первом хэше в массиве, называемом «data», и перезаписать первое вторым, что и происходит с вами.

Похоже, ваша проблема на стадии генерации, а не на стадии интерпретации, но все же я бы попытался создать более чистую схему для ваших параметров, в которой массивы будут когда-либо использоваться только в качестве заключительной части имени параметра (т. е. используйте хеш вместо массива для хранения данных компании), и вместо этого вы вставляете несколько уникальных ключей, чтобы отличить друг от друга хеши компании. Примерно так:

{:api_key => "12345", 
 :data => {1 => {"Company"=>"Apple,Inc","Website"=>"Apple.com"}, 2 => {"Company"=>"Google","Website"=>"google.com"}}, 
 :run => { :title => "The First Run" }}

1 и 2 могут быть фактическими идентификаторами записей какой-либо компании или просто цифрами, которые вы вводите для создания уникальных ключей, которые выкидываются на другом конце. Это сгенерирует такие параметры:

data[1][Company]=Apple,Inc
data[2][Company]=Google

Которые теперь не могут перезаписывать друг друга.

В вашем последующем действии контроллера это всего лишь изменение по сравнению с этим:

params[:data].each do |company_hash|
  #do something with company hash
end

до

params[:data].each do |k, company_hash|
  #do something with company hash and optionally k if you want, or ignore k
end
...