Come passare JSON a un'applicazione RAILS in modo che crei oggetti figlio nidificati in una relazione has_many?Creazione di oggetti nidificati con JSON in Rails
Ecco quello che ho finora:
Due oggetti del modello.
class Commute < ActiveRecord::Base
has_many :locations
accepts_nested_attributes_for :locations, :allow_destroy => true
end
class Location < ActiveRecord::Base
belongs_to :commute
end
Con Commute, ho impostato un controller standard. Mi piacerebbe essere in grado di creare un oggetto Commute così come diversi oggetti Location child in una singola chiamata REST usando JSON. Ho provato cose come questa:
curl -H "Content-Type:application/json" -H "Accept:application/json"
-d "{\"commute\":{\"minutes\":0,
\"startTime\":\"Wed May 06 22:14:12 EDT 2009\",
\"locations\":[{\"latitude\":\"40.4220061\",
\"longitude\":\"40.4220061\"}]}}" http://localhost:3000/commutes
O, più leggibile, il JSON è:
{
"commute": {
"minutes": 0,
"startTime": "Wed May 06 22:14:12 EDT 2009",
"locations": [
{
"latitude": "40.4220061",
"longitude": "40.4220061"
}
]
}
}
Quando eseguo che, ottengo questo output:
Processing CommutesController#create (for 127.0.0.1 at 2009-05-10 09:48:04) [POST]
Parameters: {"commute"=>{"minutes"=>0, "locations"=>[{"latitude"=>"40.4220061", "longitude"=>"40.4220061"}], "startTime"=>"Wed May 06 22:14:12 EDT 2009"}}
ActiveRecord::AssociationTypeMismatch (Location(#19300550) expected, got HashWithIndifferentAccess(#2654720)):
app/controllers/commutes_controller.rb:46:in `new'
app/controllers/commutes_controller.rb:46:in `create'
Si guarda come le posizioni in cui viene letto l'array JSON, ma non interpretato come un oggetto Location.
Posso facilmente cambiare il client o il server, quindi la soluzione potrebbe provenire da entrambi i lati.
Quindi, RAILS rende questo facile per me da fare? O devo aggiungere qualche supporto per questo al mio oggetto Commute? Forse aggiungi un metodo from_json?
Grazie per qualsiasi aiuto.
Come ho lavorato su questo, una soluzione che funziona è modificare il mio controller. Ma questo non sembra il modo "rotaie" per farlo, quindi per favore fatemi sapere se c'è un modo migliore.
def create
locations = params[:commute].delete("locations");
@commute = Commute.new(params[:commute])
result = @commute.save
if locations
locations.each do |location|
@commute.locations.create(location)
end
end
respond_to do |format|
if result
flash[:notice] = 'Commute was successfully created.'
format.html { redirect_to(@commute) }
format.xml { render :xml => @commute, :status => :created, :location => @commute }
else
format.html { render :action => "new" }
format.xml { render :xml => @commute.errors, :status => :unprocessable_entity }
end
end
end
Sembra che tu sia in grado di controllare il JSON di origine, ma cosa succede se non puoi, come gestiresti "posizioni"? – Jerome
Dai un'occhiata, ho appena postato una modifica da una risposta che è stata cancellata. –
Per chiunque abbia ancora problemi con questo, è necessario consentire manualmente gli attributi nel controller. Esempio: 'params.require (: commute) .permit (: minutes,: startTime, locations_attributes: [: latitude,: longitude])' – Kevin