11

次のようなハッシュの配列としてパラメーターを渡す必要がある条件があります。

以下は、API 呼び出しの Rack::Test ポスト メソッドです。

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"}

さて、これは API を呼び出すために使用している RestClient ポスト メソッドです。

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 がハッシュの配列を削除して、配列の最後のハッシュにするのはなぜですか?

4

2 に答える 2

19

Railsアプリケーションで同じ問題が発生しました。RestClient+Railsバックエンドで動作する次の回避策を見つけました。

Railsはdata[][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"}
  ]
}

この例では、ハッシュの深さ2レベルにネストされた配列がありました。上記の回避策では、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"}
      ]
    }
  }
}
于 2011-12-05T20:10:35.843 に答える
14

ハッシュをパラメーターに変換する方法の違いに関係していると思われます。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" 

これは厄介な部分です:

data[][Company]=Apple,Inc&data[][Website]=Apple.com&data[][Company]=Google&data[][Website]=google.com

Rails uri パーサーはこれを読み取り、ハッシュに戻す必要があります。私の意見では、ハッシュの配列をパラメーターに入れることは、上記のような文字列を作成するため、基本的に解析が難しいため、問題が発生します。たとえば、次の 2 つのパラメーターが表示されます

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

パーサーは、どちらも "data" と呼ばれる配列の最初のハッシュで Company 変数を記述していると判断し、最初のハッシュを 2 番目のハッシュで上書きします。

問題は解釈段階ではなく生成段階にあるようですが、それでも、配列がパラメーター名の最後の部分としてのみ使用されるパラメーターのよりクリーンなスキームを作成しようとします(つまり、使用します会社のデータを保持するための配列ではなくハッシュ) を使用し、代わりにいくつかの一意のキーを挿入して、会社のハッシュを互いに区別します。このようなもの:

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

1 と 2 は、会社のレコードの実際の ID である場合もあれば、一意のキーを作成するために入力した数値である場合もあります。これにより、次のようなパラメーターが生成されます。

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
于 2011-06-27T09:08:19.823 に答える