Setiap kali saya ingin POST array objek JSON dengan jQuery to Rails, saya mengalami masalah ini. Jika saya merangkai array, saya dapat melihat bahwa jQuery melakukan tugasnya dengan benar:
"shared_items"=>"[{\"entity_id\":\"253\",\"position\":1},{\"entity_id\":\"823\",\"position\":2}]"
Tetapi jika saya hanya mengirim array itu sebagai data panggilan AJAX saya mendapatkan:
"shared_items"=>{"0"=>{"entity_id"=>"253", "position"=>"1"}, "1"=>{"entity_id"=>"823", "position"=>"2"}}
Sedangkan jika saya hanya mengirim array biasa itu berfungsi:
"shared_items"=>["entity_253"]
Mengapa Rails mengubah array menjadi hash aneh itu? Satu-satunya alasan yang terlintas dalam pikiran adalah bahwa Rails tidak dapat memahami konten dengan benar karena tidak ada tipe di sini (apakah ada cara untuk mengaturnya dalam panggilan jQuery?):
Processing by SharedListsController#create as
Terima kasih!
Pembaruan:
Saya mengirim data sebagai array, bukan string dan array dibuat secara dinamis menggunakan .push()
fungsi tersebut. Mencoba dengan $.post
dan $.ajax
, hasil yang sama.
Content-Type
permintaan keapplication/json
, tetapi mengirim data sebagai bentuk html? Sulit untuk memikirkan kembali sejauh ini. Rails berfungsi dengan baik, setelahContent-Type
disetel ke nilai yang benar, dan data yang dikirim adalah JSON yang valid.contentType: 'application/json'
Pertanyaan yang agak lama, tetapi saya berjuang dengan ini sendiri hari ini, dan inilah jawaban yang saya dapatkan: Saya percaya ini sedikit kesalahan jQuery, tetapi itu hanya melakukan apa yang wajar untuk itu. Saya, bagaimanapun, punya solusi.
Diberikan panggilan ajax jQuery berikut:
$.ajax({ type : "POST", url : 'http://localhost:3001/plugin/bulk_import/', dataType: 'json', data : {"shared_items": [{"entity_id":"253","position":1},{"entity_id":"823","position":2}]} });
Nilai-nilai yang akan dikirim jQuery akan terlihat seperti ini (jika Anda melihat Permintaan di Firebug-of-choice Anda) akan memberi Anda data formulir yang terlihat seperti:
shared_items%5B0%5D%5Bentity_id%5D:1 shared_items%5B0%5D%5Bposition%5D:1
Jika Anda CGI.unencode itu Anda akan mendapatkan
shared_items[0][entity_id]:1 shared_items[0][position]:1
Saya percaya ini karena jQuery berpikir bahwa kunci tersebut di JSON Anda adalah nama elemen formulir, dan harus memperlakukannya seolah-olah Anda memiliki bidang bernama "pengguna [nama]".
Jadi mereka datang ke aplikasi Rails Anda, Rails melihat tanda kurung, dan membuat hash untuk menahan kunci terdalam dari nama field ("1" yang ditambahkan jQuery "membantu").
Bagaimanapun, saya mengatasi perilaku ini dengan membangun panggilan ajax saya dengan cara berikut;
$.ajax({ type : "POST", url : 'http://localhost:3001/plugin/bulk_import/', dataType: 'json', data : {"data": JSON.stringify({"shared_items": [{"entity_id":"253","position":1},{"entity_id":"823","position":2}])}, } });
Yang memaksa jQuery untuk berpikir bahwa JSON ini adalah nilai yang ingin Anda teruskan, seluruhnya, dan bukan objek Javascript yang harus diambil dan mengubah semua kunci menjadi nama bidang formulir.
Namun, itu berarti ada sedikit perbedaan di sisi Rails, karena Anda perlu secara eksplisit mendekode JSON di params [: data].
Tapi tidak apa-apa:
ActiveSupport::JSON.decode( params[:data] )
TL; DR: Jadi, solusinya adalah: di parameter data ke panggilan jQuery.ajax () Anda, lakukan
{"data": JSON.stringify(my_object) }
secara eksplisit, alih-alih memberi makan array JSON ke jQuery (di mana ia salah menebak apa yang ingin Anda lakukan dengannya.sumber
Saya baru saja mengalami masalah ini dengan Rails 4. Untuk menjawab pertanyaan Anda secara eksplisit ("Mengapa Rails mengubah array menjadi hash aneh itu?"), Lihat bagian 4.1 dari panduan Rails di Pengontrol Tindakan :
Masalahnya adalah, jQuery memformat permintaan dengan indeks array eksplisit, bukan dengan tanda kurung siku kosong. Jadi, misalnya, alih-alih mengirim
shared_items[]=1&shared_items[]=2
, ia mengirimshared_items[0]=1&shared_items[1]=2
. Rails melihat indeks array dan menafsirkannya sebagai kunci hash daripada indeks array, mengubah permintaan menjadi hash Ruby yang aneh:{ shared_items: { '0' => '1', '1' => '2' } }
.Jika Anda tidak memiliki kendali atas klien, Anda dapat memperbaiki masalah ini di sisi server dengan mengonversi hash menjadi sebuah array. Begini cara saya melakukannya:
shared_items = [] params[:shared_items].each { |k, v| shared_items << v }
sumber
metode berikut dapat membantu jika Anda menggunakan parameter yang kuat
def safe_params values = params.require(:shared_items) values = items.values if items.keys.first == '0' ActionController::Parameters.new(shared_items: values).permit(shared_items: [:entity_id, :position]).require(:shared_items) end
sumber
Sudahkah Anda mempertimbangkan untuk melakukan
parsed_json = ActiveSupport::JSON.decode(your_json_string)
? Jika Anda mengirim barang dengan cara lain, Anda dapat menggunakan.to_json
untuk membuat serial data.sumber
Apakah Anda hanya mencoba memasukkan string JSON menjadi tindakan pengontrol Rails?
Saya tidak yakin apa yang dilakukan Rails dengan hash tersebut, tetapi Anda mungkin dapat mengatasi masalah dan lebih beruntung dengan membuat objek Javascript / JSON (sebagai lawan dari string JSON) dan mengirimkannya sebagai parameter data untuk Ajax Anda. panggilan.
myData = { "shared_items": [ { "entity_id": "253", "position": 1 }, { "entity_id": "823", "position": 2 } ] };
Jika Anda ingin mengirim ini melalui ajax maka Anda akan melakukan sesuatu seperti ini:
$.ajax({ type: "POST", url: "my_url", // be sure to set this in your routes.rb data: myData, success: function(data) { console.log("success. data:"); console.log(data); } });
Perhatikan dengan cuplikan ajax di atas, jQuery akan membuat tebakan cerdas pada dataType, meskipun biasanya baik untuk menetapkannya secara eksplisit.
Apa pun itu, dalam aksi pengontrol Anda, Anda bisa mendapatkan objek JSON yang diteruskan dengan hash params, yaitu
params[:shared_items]
Misalnya tindakan ini akan meludahkan objek json Anda kembali kepada Anda:
def reply_in_json @shared = params[:shared_items] render :json => @shared end
sumber
Gunakan permata rack-jquery-params (penafian: Saya penulisnya). Ini memperbaiki masalah array Anda menjadi hashes dengan kunci integer.
sumber