Toda vez que desejo POSTAR uma matriz de objetos JSON com jQuery to Rails, tenho esse problema. Se eu stringificar o array, posso ver que o jQuery está fazendo seu trabalho corretamente:
"shared_items"=>"[{\"entity_id\":\"253\",\"position\":1},{\"entity_id\":\"823\",\"position\":2}]"
Mas se eu apenas enviar o array como os dados da chamada AJAX, recebo:
"shared_items"=>{"0"=>{"entity_id"=>"253", "position"=>"1"}, "1"=>{"entity_id"=>"823", "position"=>"2"}}
Considerando que se eu apenas enviar um array simples, ele funciona:
"shared_items"=>["entity_253"]
Por que Rails está mudando o array para aquele hash estranho? A única razão que vem à mente é que o Rails não consegue entender corretamente o conteúdo porque não há nenhum tipo aqui (existe uma maneira de configurá-lo na chamada do jQuery?):
Processing by SharedListsController#create as
Obrigado!
Atualização:
estou enviando os dados como um array, não uma string e o array é criado dinamicamente usando a .push()
função. Tentei com $.post
e $.ajax
, mesmo resultado.
Content-Type
da solicitação comoapplication/json
, mas, em vez disso, estava enviando os dados como um formulário html faria? É difícil pensar tão longe. O Rails estava funcionando bem, depois que oContent-Type
foi configurado com o valor correto e os dados enviados eram JSON válido.contentType: 'application/json'
Uma pergunta um pouco antiga, mas eu mesma lutei contra isso hoje, e aqui está a resposta que eu encontrei: Eu acredito que isso é um pouco a culpa do jQuery, mas ele está apenas fazendo o que é natural. Eu, no entanto, tenho uma solução alternativa.
Dada a seguinte chamada jQuery ajax:
Os valores que o jQuery postará se parecerão com isto (se você olhar para a Solicitação em seu Firebug-of-choice) fornecerá dados de formulário semelhantes a:
Se você CGI.unencode que você obterá
Acredito que isso seja porque jQuery pensa que essas chaves em seu JSON são nomes de elementos de formulário e que deve tratá-las como se você tivesse um campo chamado "usuário [nome]".
Então, eles entram em seu aplicativo Rails, Rails vê os colchetes e constrói um hash para manter a chave mais interna do nome do campo (o "1" que o jQuery "utilmente" adicionou).
De qualquer forma, contornei esse comportamento construindo minha chamada ajax da seguinte maneira;
O que força o jQuery a pensar que esse JSON é um valor que você deseja passar, inteiramente, e não um objeto Javascript que ele deve pegar e transformar todas as chaves em nomes de campos de formulário.
No entanto, isso significa que as coisas são um pouco diferentes no lado do Rails, porque você precisa decodificar explicitamente o JSON em params [: data].
Mas tudo bem:
TL; DR: Então, a solução é: no parâmetro de dados para sua chamada jQuery.ajax (), faça
{"data": JSON.stringify(my_object) }
explicitamente, em vez de alimentar o array JSON no jQuery (onde ele adivinha erroneamente o que você deseja fazer com ele.fonte
Acabei de encontrar esse problema com o Rails 4. Para responder explicitamente à sua pergunta ("Por que o Rails está mudando o array para aquele hash estranho?"), Consulte a seção 4.1 do guia Rails sobre controladores de ação :
O problema é que o jQuery formata a solicitação com índices de array explícitos, em vez de colchetes vazios. Então, por exemplo, em vez de enviar
shared_items[]=1&shared_items[]=2
, ele enviashared_items[0]=1&shared_items[1]=2
. Trilhos vê os índices de array e interpreta como chaves de hash em vez de índices de array, transformando o pedido em um hash de Ruby estranho:{ shared_items: { '0' => '1', '1' => '2' } }
.Se você não tiver controle do cliente, poderá corrigir esse problema no lado do servidor, convertendo o hash em um array. Veja como eu fiz:
fonte
o método a seguir pode ser útil se você usar parâmetros fortes
fonte
Você já pensou em fazer
parsed_json = ActiveSupport::JSON.decode(your_json_string)
? Se estiver enviando coisas de outra forma, você pode usar.to_json
para serializar os dados.fonte
Você está apenas tentando colocar a string JSON em uma ação do controlador Rails?
Não tenho certeza do que Rails está fazendo com o hash, mas você pode contornar o problema e ter mais sorte criando um objeto Javascript / JSON (em oposição a uma string JSON) e enviando-o como o parâmetro de dados para seu Ajax ligar.
Se você quisesse enviar via ajax, faria algo assim:
Observe com o snippet ajax acima, jQuery fará uma suposição inteligente no dataType, embora geralmente seja bom especificá-lo explicitamente.
De qualquer forma, em sua ação do controlador, você pode obter o objeto JSON que você passou com o hash de parâmetros, ou seja,
Por exemplo, esta ação vai cuspir seu objeto json de volta para você:
fonte
Use a gem rack-jquery-params (isenção de responsabilidade: eu sou o autor). Ele corrige o problema de matrizes se tornarem hashes com chaves inteiras.
fonte