Как передать JSON в приложение RAILS, чтобы он создал вложенные дочерние объекты в отношениях has_many?
Вот что я до сих пор:
Два объекта модели.
class Commute < ActiveRecord::Base
has_many :locations
accepts_nested_attributes_for :locations, :allow_destroy => true
end
class Location < ActiveRecord::Base
belongs_to :commute
end
С Commute у меня установлен стандартный контроллер. Я хотел бы иметь возможность создать объект Commute, а также несколько дочерних объектов Location в одном вызове REST с использованием JSON. Я пробовал такие вещи:
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
Или более читаемым, JSON:
{
"commute": {
"minutes": 0,
"startTime": "Wed May 06 22:14:12 EDT 2009",
"locations": [
{
"latitude": "40.4220061",
"longitude": "40.4220061"
}
]
}
}
Когда я его выполню, я получаю этот вывод:
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'
Похоже, что содержимое массива JSON считывается, но не интерпретируется как объект Location.
Я могу легко изменить либо клиент, либо сервер, поэтому решение может появиться с обеих сторон.
Итак, делает ли RAILS это легко для меня? Или мне нужно добавить некоторую поддержку для этого объекта Commute? Возможно, добавьте метод from_json?
Спасибо за любую помощь.
Как я уже работал, одним из решений является изменение моего контроллера. Но это не похоже на способ "рельсов", поэтому, пожалуйста, дайте мне знать, есть ли лучший способ.
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